diff options
Diffstat (limited to '')
-rwxr-xr-x | linden/indra/llplugin/llpluginclassmedia.cpp | 1259 |
1 files changed, 1259 insertions, 0 deletions
diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp new file mode 100755 index 0000000..8664524 --- /dev/null +++ b/linden/indra/llplugin/llpluginclassmedia.cpp | |||
@@ -0,0 +1,1259 @@ | |||
1 | /** | ||
2 | * @file llpluginclassmedia.cpp | ||
3 | * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class. | ||
4 | * | ||
5 | * @cond | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2010, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlife.com/developers/opensource/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | * | ||
33 | * @endcond | ||
34 | */ | ||
35 | |||
36 | #include "linden_common.h" | ||
37 | #include "indra_constants.h" | ||
38 | |||
39 | #include "llpluginclassmedia.h" | ||
40 | #include "llpluginmessageclasses.h" | ||
41 | |||
42 | #include "llqtwebkit.h" | ||
43 | |||
44 | static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256; | ||
45 | |||
46 | static int nextPowerOf2( int value ) | ||
47 | { | ||
48 | int next_power_of_2 = 1; | ||
49 | while ( next_power_of_2 < value ) | ||
50 | { | ||
51 | next_power_of_2 <<= 1; | ||
52 | } | ||
53 | |||
54 | return next_power_of_2; | ||
55 | } | ||
56 | |||
57 | LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) | ||
58 | { | ||
59 | mOwner = owner; | ||
60 | mPlugin = NULL; | ||
61 | reset(); | ||
62 | |||
63 | //debug use | ||
64 | mDeleteOK = true ; | ||
65 | } | ||
66 | |||
67 | |||
68 | LLPluginClassMedia::~LLPluginClassMedia() | ||
69 | { | ||
70 | llassert_always(mDeleteOK) ; | ||
71 | reset(); | ||
72 | } | ||
73 | |||
74 | bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) | ||
75 | { | ||
76 | LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; | ||
77 | LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; | ||
78 | |||
79 | mPlugin = new LLPluginProcessParent(this); | ||
80 | mPlugin->setSleepTime(mSleepTime); | ||
81 | |||
82 | // Queue up the media init message -- it will be sent after all the currently queued messages. | ||
83 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init"); | ||
84 | sendMessage(message); | ||
85 | |||
86 | mPlugin->init(launcher_filename, plugin_filename, debug); | ||
87 | |||
88 | return true; | ||
89 | } | ||
90 | |||
91 | |||
92 | void LLPluginClassMedia::reset() | ||
93 | { | ||
94 | if(mPlugin != NULL) | ||
95 | { | ||
96 | delete mPlugin; | ||
97 | mPlugin = NULL; | ||
98 | } | ||
99 | |||
100 | mTextureParamsReceived = false; | ||
101 | mRequestedTextureDepth = 0; | ||
102 | mRequestedTextureInternalFormat = 0; | ||
103 | mRequestedTextureFormat = 0; | ||
104 | mRequestedTextureType = 0; | ||
105 | mRequestedTextureSwapBytes = false; | ||
106 | mRequestedTextureCoordsOpenGL = false; | ||
107 | mTextureSharedMemorySize = 0; | ||
108 | mTextureSharedMemoryName.clear(); | ||
109 | mDefaultMediaWidth = 0; | ||
110 | mDefaultMediaHeight = 0; | ||
111 | mNaturalMediaWidth = 0; | ||
112 | mNaturalMediaHeight = 0; | ||
113 | mSetMediaWidth = -1; | ||
114 | mSetMediaHeight = -1; | ||
115 | mRequestedMediaWidth = 0; | ||
116 | mRequestedMediaHeight = 0; | ||
117 | mRequestedTextureWidth = 0; | ||
118 | mRequestedTextureHeight = 0; | ||
119 | mFullMediaWidth = 0; | ||
120 | mFullMediaHeight = 0; | ||
121 | mTextureWidth = 0; | ||
122 | mTextureHeight = 0; | ||
123 | mMediaWidth = 0; | ||
124 | mMediaHeight = 0; | ||
125 | mDirtyRect = LLRect::null; | ||
126 | mAutoScaleMedia = false; | ||
127 | mRequestedVolume = 1.0f; | ||
128 | mPriority = PRIORITY_NORMAL; | ||
129 | mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; | ||
130 | mAllowDownsample = false; | ||
131 | mPadding = 0; | ||
132 | mLastMouseX = 0; | ||
133 | mLastMouseY = 0; | ||
134 | mStatus = LLPluginClassMediaOwner::MEDIA_NONE; | ||
135 | mSleepTime = 1.0f / 100.0f; | ||
136 | mCanCut = false; | ||
137 | mCanCopy = false; | ||
138 | mCanPaste = false; | ||
139 | mMediaName.clear(); | ||
140 | mMediaDescription.clear(); | ||
141 | mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f); | ||
142 | |||
143 | // media_browser class | ||
144 | mNavigateURI.clear(); | ||
145 | mNavigateResultCode = -1; | ||
146 | mNavigateResultString.clear(); | ||
147 | mHistoryBackAvailable = false; | ||
148 | mHistoryForwardAvailable = false; | ||
149 | mStatusText.clear(); | ||
150 | mProgressPercent = 0; | ||
151 | mClickURL.clear(); | ||
152 | mClickTarget.clear(); | ||
153 | mClickTargetType = TARGET_NONE; | ||
154 | |||
155 | // media_time class | ||
156 | mCurrentTime = 0.0f; | ||
157 | mDuration = 0.0f; | ||
158 | mCurrentRate = 0.0f; | ||
159 | mLoadedDuration = 0.0f; | ||
160 | } | ||
161 | |||
162 | void LLPluginClassMedia::idle(void) | ||
163 | { | ||
164 | if(mPlugin) | ||
165 | { | ||
166 | mPlugin->idle(); | ||
167 | } | ||
168 | |||
169 | if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked())) | ||
170 | { | ||
171 | // Can't process a size change at this time | ||
172 | } | ||
173 | else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight)) | ||
174 | { | ||
175 | // Calculate the correct size for the media texture | ||
176 | mRequestedTextureHeight = mRequestedMediaHeight; | ||
177 | if(mPadding < 0) | ||
178 | { | ||
179 | // negative values indicate the plugin wants a power of 2 | ||
180 | mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth); | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | mRequestedTextureWidth = mRequestedMediaWidth; | ||
185 | |||
186 | if(mPadding > 1) | ||
187 | { | ||
188 | // Pad up to a multiple of the specified number of bytes per row | ||
189 | int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth; | ||
190 | int pad = rowbytes % mPadding; | ||
191 | if(pad != 0) | ||
192 | { | ||
193 | rowbytes += mPadding - pad; | ||
194 | } | ||
195 | |||
196 | if(rowbytes % mRequestedTextureDepth == 0) | ||
197 | { | ||
198 | mRequestedTextureWidth = rowbytes / mRequestedTextureDepth; | ||
199 | } | ||
200 | else | ||
201 | { | ||
202 | LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL; | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | |||
208 | // Size change has been requested but not initiated yet. | ||
209 | size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth; | ||
210 | |||
211 | // Add an extra line for padding, just in case. | ||
212 | newsize += mRequestedTextureWidth * mRequestedTextureDepth; | ||
213 | |||
214 | if(newsize != mTextureSharedMemorySize) | ||
215 | { | ||
216 | if(!mTextureSharedMemoryName.empty()) | ||
217 | { | ||
218 | // Tell the plugin to remove the old memory segment | ||
219 | mPlugin->removeSharedMemory(mTextureSharedMemoryName); | ||
220 | mTextureSharedMemoryName.clear(); | ||
221 | } | ||
222 | |||
223 | mTextureSharedMemorySize = newsize; | ||
224 | mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize); | ||
225 | if(!mTextureSharedMemoryName.empty()) | ||
226 | { | ||
227 | void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); | ||
228 | |||
229 | // clear texture memory to avoid random screen visual fuzz from uninitialized texture data | ||
230 | memset( addr, 0x00, newsize ); | ||
231 | |||
232 | // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, | ||
233 | // so it may not be worthwhile. | ||
234 | // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | // This is our local indicator that a change is in progress. | ||
239 | mTextureWidth = -1; | ||
240 | mTextureHeight = -1; | ||
241 | mMediaWidth = -1; | ||
242 | mMediaHeight = -1; | ||
243 | |||
244 | // This invalidates any existing dirty rect. | ||
245 | resetDirty(); | ||
246 | |||
247 | // Send a size change message to the plugin | ||
248 | { | ||
249 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change"); | ||
250 | message.setValue("name", mTextureSharedMemoryName); | ||
251 | message.setValueS32("width", mRequestedMediaWidth); | ||
252 | message.setValueS32("height", mRequestedMediaHeight); | ||
253 | message.setValueS32("texture_width", mRequestedTextureWidth); | ||
254 | message.setValueS32("texture_height", mRequestedTextureHeight); | ||
255 | message.setValueReal("background_r", mBackgroundColor.mV[VX]); | ||
256 | message.setValueReal("background_g", mBackgroundColor.mV[VY]); | ||
257 | message.setValueReal("background_b", mBackgroundColor.mV[VZ]); | ||
258 | message.setValueReal("background_a", mBackgroundColor.mV[VW]); | ||
259 | mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. | ||
260 | |||
261 | LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | if(mPlugin && mPlugin->isRunning()) | ||
266 | { | ||
267 | // Send queued messages | ||
268 | while(!mSendQueue.empty()) | ||
269 | { | ||
270 | LLPluginMessage message = mSendQueue.front(); | ||
271 | mSendQueue.pop(); | ||
272 | mPlugin->sendMessage(message); | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | int LLPluginClassMedia::getTextureWidth() const | ||
278 | { | ||
279 | return nextPowerOf2(mTextureWidth); | ||
280 | } | ||
281 | |||
282 | int LLPluginClassMedia::getTextureHeight() const | ||
283 | { | ||
284 | return nextPowerOf2(mTextureHeight); | ||
285 | } | ||
286 | |||
287 | unsigned char* LLPluginClassMedia::getBitsData() | ||
288 | { | ||
289 | unsigned char *result = NULL; | ||
290 | if((mPlugin != NULL) && !mTextureSharedMemoryName.empty()) | ||
291 | { | ||
292 | result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); | ||
293 | } | ||
294 | return result; | ||
295 | } | ||
296 | |||
297 | void LLPluginClassMedia::setSize(int width, int height) | ||
298 | { | ||
299 | if((width > 0) && (height > 0)) | ||
300 | { | ||
301 | mSetMediaWidth = width; | ||
302 | mSetMediaHeight = height; | ||
303 | } | ||
304 | else | ||
305 | { | ||
306 | mSetMediaWidth = -1; | ||
307 | mSetMediaHeight = -1; | ||
308 | } | ||
309 | |||
310 | setSizeInternal(); | ||
311 | } | ||
312 | |||
313 | void LLPluginClassMedia::setSizeInternal(void) | ||
314 | { | ||
315 | if((mSetMediaWidth > 0) && (mSetMediaHeight > 0)) | ||
316 | { | ||
317 | mRequestedMediaWidth = mSetMediaWidth; | ||
318 | mRequestedMediaHeight = mSetMediaHeight; | ||
319 | } | ||
320 | else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0)) | ||
321 | { | ||
322 | mRequestedMediaWidth = mNaturalMediaWidth; | ||
323 | mRequestedMediaHeight = mNaturalMediaHeight; | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | mRequestedMediaWidth = mDefaultMediaWidth; | ||
328 | mRequestedMediaHeight = mDefaultMediaHeight; | ||
329 | } | ||
330 | |||
331 | // Save these for size/interest calculations | ||
332 | mFullMediaWidth = mRequestedMediaWidth; | ||
333 | mFullMediaHeight = mRequestedMediaHeight; | ||
334 | |||
335 | if(mAllowDownsample) | ||
336 | { | ||
337 | switch(mPriority) | ||
338 | { | ||
339 | case PRIORITY_SLIDESHOW: | ||
340 | case PRIORITY_LOW: | ||
341 | // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit | ||
342 | while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) | ||
343 | { | ||
344 | mRequestedMediaWidth /= 2; | ||
345 | mRequestedMediaHeight /= 2; | ||
346 | } | ||
347 | break; | ||
348 | |||
349 | default: | ||
350 | // Don't adjust texture size | ||
351 | break; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if(mAutoScaleMedia) | ||
356 | { | ||
357 | mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth); | ||
358 | mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight); | ||
359 | } | ||
360 | |||
361 | if(mRequestedMediaWidth > 2048) | ||
362 | mRequestedMediaWidth = 2048; | ||
363 | |||
364 | if(mRequestedMediaHeight > 2048) | ||
365 | mRequestedMediaHeight = 2048; | ||
366 | } | ||
367 | |||
368 | void LLPluginClassMedia::setAutoScale(bool auto_scale) | ||
369 | { | ||
370 | if(auto_scale != mAutoScaleMedia) | ||
371 | { | ||
372 | mAutoScaleMedia = auto_scale; | ||
373 | setSizeInternal(); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | bool LLPluginClassMedia::textureValid(void) | ||
378 | { | ||
379 | if( | ||
380 | !mTextureParamsReceived || | ||
381 | mTextureWidth <= 0 || | ||
382 | mTextureHeight <= 0 || | ||
383 | mMediaWidth <= 0 || | ||
384 | mMediaHeight <= 0 || | ||
385 | mRequestedMediaWidth != mMediaWidth || | ||
386 | mRequestedMediaHeight != mMediaHeight || | ||
387 | getBitsData() == NULL | ||
388 | ) | ||
389 | return false; | ||
390 | |||
391 | return true; | ||
392 | } | ||
393 | |||
394 | bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) | ||
395 | { | ||
396 | bool result = !mDirtyRect.isNull(); | ||
397 | |||
398 | if(dirty_rect != NULL) | ||
399 | { | ||
400 | *dirty_rect = mDirtyRect; | ||
401 | } | ||
402 | |||
403 | return result; | ||
404 | } | ||
405 | |||
406 | void LLPluginClassMedia::resetDirty(void) | ||
407 | { | ||
408 | mDirtyRect = LLRect::null; | ||
409 | } | ||
410 | |||
411 | std::string LLPluginClassMedia::translateModifiers(MASK modifiers) | ||
412 | { | ||
413 | std::string result; | ||
414 | |||
415 | |||
416 | if(modifiers & MASK_CONTROL) | ||
417 | { | ||
418 | result += "control|"; | ||
419 | } | ||
420 | |||
421 | if(modifiers & MASK_ALT) | ||
422 | { | ||
423 | result += "alt|"; | ||
424 | } | ||
425 | |||
426 | if(modifiers & MASK_SHIFT) | ||
427 | { | ||
428 | result += "shift|"; | ||
429 | } | ||
430 | |||
431 | // TODO: should I deal with platform differences here or in callers? | ||
432 | // TODO: how do we deal with the Mac "command" key? | ||
433 | /* | ||
434 | if(modifiers & MASK_SOMETHING) | ||
435 | { | ||
436 | result += "meta|"; | ||
437 | } | ||
438 | */ | ||
439 | return result; | ||
440 | } | ||
441 | |||
442 | void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) | ||
443 | { | ||
444 | if(type == MOUSE_EVENT_MOVE) | ||
445 | { | ||
446 | if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked()) | ||
447 | { | ||
448 | // Don't queue up mouse move events that can't be delivered. | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | if((x == mLastMouseX) && (y == mLastMouseY)) | ||
453 | { | ||
454 | // Don't spam unnecessary mouse move events. | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | mLastMouseX = x; | ||
459 | mLastMouseY = y; | ||
460 | } | ||
461 | |||
462 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event"); | ||
463 | std::string temp; | ||
464 | switch(type) | ||
465 | { | ||
466 | case MOUSE_EVENT_DOWN: temp = "down"; break; | ||
467 | case MOUSE_EVENT_UP: temp = "up"; break; | ||
468 | case MOUSE_EVENT_MOVE: temp = "move"; break; | ||
469 | case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break; | ||
470 | } | ||
471 | message.setValue("event", temp); | ||
472 | |||
473 | message.setValueS32("button", button); | ||
474 | |||
475 | message.setValueS32("x", x); | ||
476 | |||
477 | // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it. | ||
478 | if(!mRequestedTextureCoordsOpenGL) | ||
479 | { | ||
480 | // TODO: Should I use mMediaHeight or mRequestedMediaHeight here? | ||
481 | y = mMediaHeight - y; | ||
482 | } | ||
483 | message.setValueS32("y", y); | ||
484 | |||
485 | message.setValue("modifiers", translateModifiers(modifiers)); | ||
486 | |||
487 | sendMessage(message); | ||
488 | } | ||
489 | |||
490 | bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data) | ||
491 | { | ||
492 | bool result = true; | ||
493 | |||
494 | // FIXME: | ||
495 | // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode. | ||
496 | // For now, return false for the ones the webkit plugin won't handle properly. | ||
497 | |||
498 | switch(key_code) | ||
499 | { | ||
500 | case KEY_BACKSPACE: | ||
501 | case KEY_TAB: | ||
502 | case KEY_RETURN: | ||
503 | case KEY_PAD_RETURN: | ||
504 | case KEY_SHIFT: | ||
505 | case KEY_CONTROL: | ||
506 | case KEY_ALT: | ||
507 | case KEY_CAPSLOCK: | ||
508 | case KEY_ESCAPE: | ||
509 | case KEY_PAGE_UP: | ||
510 | case KEY_PAGE_DOWN: | ||
511 | case KEY_END: | ||
512 | case KEY_HOME: | ||
513 | case KEY_LEFT: | ||
514 | case KEY_UP: | ||
515 | case KEY_RIGHT: | ||
516 | case KEY_DOWN: | ||
517 | case KEY_INSERT: | ||
518 | case KEY_DELETE: | ||
519 | // These will be handled | ||
520 | break; | ||
521 | |||
522 | default: | ||
523 | // regular ASCII characters will also be handled | ||
524 | if(key_code >= KEY_SPECIAL) | ||
525 | { | ||
526 | // Other "special" codes will not work properly. | ||
527 | result = false; | ||
528 | } | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | if(result) | ||
533 | { | ||
534 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); | ||
535 | std::string temp; | ||
536 | switch(type) | ||
537 | { | ||
538 | case KEY_EVENT_DOWN: temp = "down"; break; | ||
539 | case KEY_EVENT_UP: temp = "up"; break; | ||
540 | case KEY_EVENT_REPEAT: temp = "repeat"; break; | ||
541 | } | ||
542 | message.setValue("event", temp); | ||
543 | |||
544 | message.setValueS32("key", key_code); | ||
545 | |||
546 | message.setValue("modifiers", translateModifiers(modifiers)); | ||
547 | message.setValueLLSD("native_key_data", native_key_data); | ||
548 | |||
549 | sendMessage(message); | ||
550 | } | ||
551 | |||
552 | return result; | ||
553 | } | ||
554 | |||
555 | void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers) | ||
556 | { | ||
557 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event"); | ||
558 | |||
559 | message.setValueS32("x", x); | ||
560 | message.setValueS32("y", y); | ||
561 | message.setValue("modifiers", translateModifiers(modifiers)); | ||
562 | |||
563 | sendMessage(message); | ||
564 | } | ||
565 | |||
566 | bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data) | ||
567 | { | ||
568 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event"); | ||
569 | |||
570 | message.setValue("text", text); | ||
571 | message.setValue("modifiers", translateModifiers(modifiers)); | ||
572 | message.setValueLLSD("native_key_data", native_key_data); | ||
573 | |||
574 | sendMessage(message); | ||
575 | |||
576 | return true; | ||
577 | } | ||
578 | |||
579 | void LLPluginClassMedia::loadURI(const std::string &uri) | ||
580 | { | ||
581 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri"); | ||
582 | |||
583 | message.setValue("uri", uri); | ||
584 | |||
585 | sendMessage(message); | ||
586 | } | ||
587 | |||
588 | const char* LLPluginClassMedia::priorityToString(EPriority priority) | ||
589 | { | ||
590 | const char* result = "UNKNOWN"; | ||
591 | switch(priority) | ||
592 | { | ||
593 | case PRIORITY_UNLOADED: result = "unloaded"; break; | ||
594 | case PRIORITY_STOPPED: result = "stopped"; break; | ||
595 | case PRIORITY_HIDDEN: result = "hidden"; break; | ||
596 | case PRIORITY_SLIDESHOW: result = "slideshow"; break; | ||
597 | case PRIORITY_LOW: result = "low"; break; | ||
598 | case PRIORITY_NORMAL: result = "normal"; break; | ||
599 | case PRIORITY_HIGH: result = "high"; break; | ||
600 | } | ||
601 | |||
602 | return result; | ||
603 | } | ||
604 | |||
605 | void LLPluginClassMedia::setPriority(EPriority priority) | ||
606 | { | ||
607 | if(mPriority != priority) | ||
608 | { | ||
609 | mPriority = priority; | ||
610 | |||
611 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority"); | ||
612 | |||
613 | std::string priority_string = priorityToString(priority); | ||
614 | switch(priority) | ||
615 | { | ||
616 | case PRIORITY_UNLOADED: | ||
617 | mSleepTime = 1.0f; | ||
618 | break; | ||
619 | case PRIORITY_STOPPED: | ||
620 | mSleepTime = 1.0f; | ||
621 | break; | ||
622 | case PRIORITY_HIDDEN: | ||
623 | mSleepTime = 1.0f; | ||
624 | break; | ||
625 | case PRIORITY_SLIDESHOW: | ||
626 | mSleepTime = 1.0f; | ||
627 | break; | ||
628 | case PRIORITY_LOW: | ||
629 | mSleepTime = 1.0f / 25.0f; | ||
630 | break; | ||
631 | case PRIORITY_NORMAL: | ||
632 | mSleepTime = 1.0f / 50.0f; | ||
633 | break; | ||
634 | case PRIORITY_HIGH: | ||
635 | mSleepTime = 1.0f / 100.0f; | ||
636 | break; | ||
637 | } | ||
638 | |||
639 | message.setValue("priority", priority_string); | ||
640 | |||
641 | sendMessage(message); | ||
642 | |||
643 | if(mPlugin) | ||
644 | { | ||
645 | mPlugin->setSleepTime(mSleepTime); | ||
646 | } | ||
647 | |||
648 | LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; | ||
649 | |||
650 | // This may affect the calculated size, so recalculate it here. | ||
651 | setSizeInternal(); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | void LLPluginClassMedia::setLowPrioritySizeLimit(int size) | ||
656 | { | ||
657 | int power = nextPowerOf2(size); | ||
658 | if(mLowPrioritySizeLimit != power) | ||
659 | { | ||
660 | mLowPrioritySizeLimit = power; | ||
661 | |||
662 | // This may affect the calculated size, so recalculate it here. | ||
663 | setSizeInternal(); | ||
664 | } | ||
665 | } | ||
666 | |||
667 | F64 LLPluginClassMedia::getCPUUsage() | ||
668 | { | ||
669 | F64 result = 0.0f; | ||
670 | |||
671 | if(mPlugin) | ||
672 | { | ||
673 | result = mPlugin->getCPUUsage(); | ||
674 | } | ||
675 | |||
676 | return result; | ||
677 | } | ||
678 | |||
679 | void LLPluginClassMedia::cut() | ||
680 | { | ||
681 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); | ||
682 | sendMessage(message); | ||
683 | } | ||
684 | |||
685 | void LLPluginClassMedia::copy() | ||
686 | { | ||
687 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy"); | ||
688 | sendMessage(message); | ||
689 | } | ||
690 | |||
691 | void LLPluginClassMedia::paste() | ||
692 | { | ||
693 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste"); | ||
694 | sendMessage(message); | ||
695 | } | ||
696 | |||
697 | void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path) | ||
698 | { | ||
699 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); | ||
700 | message.setValue("path", user_data_path); | ||
701 | sendMessage(message); | ||
702 | } | ||
703 | |||
704 | void LLPluginClassMedia::setLanguageCode(const std::string &language_code) | ||
705 | { | ||
706 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code"); | ||
707 | message.setValue("language", language_code); | ||
708 | sendMessage(message); | ||
709 | } | ||
710 | |||
711 | void LLPluginClassMedia::setPluginsEnabled(const bool enabled) | ||
712 | { | ||
713 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled"); | ||
714 | message.setValueBoolean("enable", enabled); | ||
715 | sendMessage(message); | ||
716 | } | ||
717 | |||
718 | void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) | ||
719 | { | ||
720 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled"); | ||
721 | message.setValueBoolean("enable", enabled); | ||
722 | sendMessage(message); | ||
723 | } | ||
724 | |||
725 | LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) | ||
726 | { | ||
727 | // convert a LinkTargetType value from llqtwebkit to an ETargetType | ||
728 | // so that we don't expose the llqtwebkit header in viewer code | ||
729 | switch (target_type) | ||
730 | { | ||
731 | case LLQtWebKit::LTT_TARGET_NONE: | ||
732 | return LLPluginClassMedia::TARGET_NONE; | ||
733 | |||
734 | case LLQtWebKit::LTT_TARGET_BLANK: | ||
735 | return LLPluginClassMedia::TARGET_BLANK; | ||
736 | |||
737 | case LLQtWebKit::LTT_TARGET_EXTERNAL: | ||
738 | return LLPluginClassMedia::TARGET_EXTERNAL; | ||
739 | |||
740 | default: | ||
741 | return LLPluginClassMedia::TARGET_OTHER; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | /* virtual */ | ||
746 | void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) | ||
747 | { | ||
748 | std::string message_class = message.getClass(); | ||
749 | |||
750 | if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) | ||
751 | { | ||
752 | std::string message_name = message.getName(); | ||
753 | if(message_name == "texture_params") | ||
754 | { | ||
755 | mRequestedTextureDepth = message.getValueS32("depth"); | ||
756 | mRequestedTextureInternalFormat = message.getValueU32("internalformat"); | ||
757 | mRequestedTextureFormat = message.getValueU32("format"); | ||
758 | mRequestedTextureType = message.getValueU32("type"); | ||
759 | mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes"); | ||
760 | mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl"); | ||
761 | |||
762 | // These two are optional, and will default to 0 if they're not specified. | ||
763 | mDefaultMediaWidth = message.getValueS32("default_width"); | ||
764 | mDefaultMediaHeight = message.getValueS32("default_height"); | ||
765 | |||
766 | mAllowDownsample = message.getValueBoolean("allow_downsample"); | ||
767 | mPadding = message.getValueS32("padding"); | ||
768 | |||
769 | setSizeInternal(); | ||
770 | |||
771 | mTextureParamsReceived = true; | ||
772 | } | ||
773 | else if(message_name == "updated") | ||
774 | { | ||
775 | if(message.hasValue("left")) | ||
776 | { | ||
777 | LLRect newDirtyRect; | ||
778 | newDirtyRect.mLeft = message.getValueS32("left"); | ||
779 | newDirtyRect.mTop = message.getValueS32("top"); | ||
780 | newDirtyRect.mRight = message.getValueS32("right"); | ||
781 | newDirtyRect.mBottom = message.getValueS32("bottom"); | ||
782 | |||
783 | // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion. | ||
784 | // If they're backwards, swap them. | ||
785 | if(newDirtyRect.mTop < newDirtyRect.mBottom) | ||
786 | { | ||
787 | S32 temp = newDirtyRect.mTop; | ||
788 | newDirtyRect.mTop = newDirtyRect.mBottom; | ||
789 | newDirtyRect.mBottom = temp; | ||
790 | } | ||
791 | |||
792 | if(mDirtyRect.isNull()) | ||
793 | { | ||
794 | mDirtyRect = newDirtyRect; | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | mDirtyRect.unionWith(newDirtyRect); | ||
799 | } | ||
800 | |||
801 | LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" | ||
802 | << newDirtyRect.mLeft << ", " | ||
803 | << newDirtyRect.mTop << ", " | ||
804 | << newDirtyRect.mRight << ", " | ||
805 | << newDirtyRect.mBottom << "), new dirty rect is: (" | ||
806 | << mDirtyRect.mLeft << ", " | ||
807 | << mDirtyRect.mTop << ", " | ||
808 | << mDirtyRect.mRight << ", " | ||
809 | << mDirtyRect.mBottom << ")" | ||
810 | << LL_ENDL; | ||
811 | |||
812 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED); | ||
813 | } | ||
814 | |||
815 | |||
816 | bool time_duration_updated = false; | ||
817 | int previous_percent = mProgressPercent; | ||
818 | |||
819 | if(message.hasValue("current_time")) | ||
820 | { | ||
821 | mCurrentTime = message.getValueReal("current_time"); | ||
822 | time_duration_updated = true; | ||
823 | } | ||
824 | if(message.hasValue("duration")) | ||
825 | { | ||
826 | mDuration = message.getValueReal("duration"); | ||
827 | time_duration_updated = true; | ||
828 | } | ||
829 | |||
830 | if(message.hasValue("current_rate")) | ||
831 | { | ||
832 | mCurrentRate = message.getValueReal("current_rate"); | ||
833 | } | ||
834 | |||
835 | if(message.hasValue("loaded_duration")) | ||
836 | { | ||
837 | mLoadedDuration = message.getValueReal("loaded_duration"); | ||
838 | time_duration_updated = true; | ||
839 | } | ||
840 | else | ||
841 | { | ||
842 | // If the message doesn't contain a loaded_duration param, assume it's equal to duration | ||
843 | mLoadedDuration = mDuration; | ||
844 | } | ||
845 | |||
846 | // Calculate a percentage based on the loaded duration and total duration. | ||
847 | if(mDuration != 0.0f) // Don't divide by zero. | ||
848 | { | ||
849 | mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration); | ||
850 | } | ||
851 | |||
852 | if(time_duration_updated) | ||
853 | { | ||
854 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED); | ||
855 | } | ||
856 | |||
857 | if(previous_percent != mProgressPercent) | ||
858 | { | ||
859 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); | ||
860 | } | ||
861 | } | ||
862 | else if(message_name == "media_status") | ||
863 | { | ||
864 | std::string status = message.getValue("status"); | ||
865 | |||
866 | LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL; | ||
867 | |||
868 | if(status == "loading") | ||
869 | { | ||
870 | mStatus = LLPluginClassMediaOwner::MEDIA_LOADING; | ||
871 | } | ||
872 | else if(status == "loaded") | ||
873 | { | ||
874 | mStatus = LLPluginClassMediaOwner::MEDIA_LOADED; | ||
875 | } | ||
876 | else if(status == "error") | ||
877 | { | ||
878 | mStatus = LLPluginClassMediaOwner::MEDIA_ERROR; | ||
879 | } | ||
880 | else if(status == "playing") | ||
881 | { | ||
882 | mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING; | ||
883 | } | ||
884 | else if(status == "paused") | ||
885 | { | ||
886 | mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED; | ||
887 | } | ||
888 | else if(status == "done") | ||
889 | { | ||
890 | mStatus = LLPluginClassMediaOwner::MEDIA_DONE; | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | // empty string or any unknown string | ||
895 | mStatus = LLPluginClassMediaOwner::MEDIA_NONE; | ||
896 | } | ||
897 | } | ||
898 | else if(message_name == "size_change_request") | ||
899 | { | ||
900 | S32 width = message.getValueS32("width"); | ||
901 | S32 height = message.getValueS32("height"); | ||
902 | std::string name = message.getValue("name"); | ||
903 | |||
904 | // TODO: check that name matches? | ||
905 | mNaturalMediaWidth = width; | ||
906 | mNaturalMediaHeight = height; | ||
907 | |||
908 | setSizeInternal(); | ||
909 | } | ||
910 | else if(message_name == "size_change_response") | ||
911 | { | ||
912 | std::string name = message.getValue("name"); | ||
913 | |||
914 | // TODO: check that name matches? | ||
915 | |||
916 | mTextureWidth = message.getValueS32("texture_width"); | ||
917 | mTextureHeight = message.getValueS32("texture_height"); | ||
918 | mMediaWidth = message.getValueS32("width"); | ||
919 | mMediaHeight = message.getValueS32("height"); | ||
920 | |||
921 | // This invalidates any existing dirty rect. | ||
922 | resetDirty(); | ||
923 | |||
924 | // TODO: should we verify that the plugin sent back the right values? | ||
925 | // Two size changes in a row may cause them to not match, due to queueing, etc. | ||
926 | |||
927 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED); | ||
928 | } | ||
929 | else if(message_name == "cursor_changed") | ||
930 | { | ||
931 | mCursorName = message.getValue("name"); | ||
932 | |||
933 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED); | ||
934 | } | ||
935 | else if(message_name == "edit_state") | ||
936 | { | ||
937 | if(message.hasValue("cut")) | ||
938 | { | ||
939 | mCanCut = message.getValueBoolean("cut"); | ||
940 | } | ||
941 | if(message.hasValue("copy")) | ||
942 | { | ||
943 | mCanCopy = message.getValueBoolean("copy"); | ||
944 | } | ||
945 | if(message.hasValue("paste")) | ||
946 | { | ||
947 | mCanPaste = message.getValueBoolean("paste"); | ||
948 | } | ||
949 | } | ||
950 | else if(message_name == "name_text") | ||
951 | { | ||
952 | mMediaName = message.getValue("name"); | ||
953 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); | ||
954 | } | ||
955 | else | ||
956 | { | ||
957 | LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; | ||
958 | } | ||
959 | } | ||
960 | else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) | ||
961 | { | ||
962 | std::string message_name = message.getName(); | ||
963 | if(message_name == "navigate_begin") | ||
964 | { | ||
965 | mNavigateURI = message.getValue("uri"); | ||
966 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN); | ||
967 | } | ||
968 | else if(message_name == "navigate_complete") | ||
969 | { | ||
970 | mNavigateURI = message.getValue("uri"); | ||
971 | mNavigateResultCode = message.getValueS32("result_code"); | ||
972 | mNavigateResultString = message.getValue("result_string"); | ||
973 | mHistoryBackAvailable = message.getValueBoolean("history_back_available"); | ||
974 | mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); | ||
975 | |||
976 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE); | ||
977 | } | ||
978 | else if(message_name == "progress") | ||
979 | { | ||
980 | mProgressPercent = message.getValueS32("percent"); | ||
981 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); | ||
982 | } | ||
983 | else if(message_name == "status_text") | ||
984 | { | ||
985 | mStatusText = message.getValue("status"); | ||
986 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED); | ||
987 | } | ||
988 | else if(message_name == "location_changed") | ||
989 | { | ||
990 | mLocation = message.getValue("uri"); | ||
991 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED); | ||
992 | } | ||
993 | else if(message_name == "click_href") | ||
994 | { | ||
995 | mClickURL = message.getValue("uri"); | ||
996 | mClickTarget = message.getValue("target"); | ||
997 | U32 target_type = message.getValueU32("target_type"); | ||
998 | mClickTargetType = ::getTargetTypeFromLLQtWebkit(target_type); | ||
999 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); | ||
1000 | } | ||
1001 | else if(message_name == "click_nofollow") | ||
1002 | { | ||
1003 | mClickURL = message.getValue("uri"); | ||
1004 | mClickTarget.clear(); | ||
1005 | mClickTargetType = TARGET_NONE; | ||
1006 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); | ||
1007 | } | ||
1008 | else if(message_name == "cookie_set") | ||
1009 | { | ||
1010 | if(mOwner) | ||
1011 | { | ||
1012 | mOwner->handleCookieSet(this, message.getValue("cookie")); | ||
1013 | } | ||
1014 | } | ||
1015 | else | ||
1016 | { | ||
1017 | LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; | ||
1018 | } | ||
1019 | } | ||
1020 | else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) | ||
1021 | { | ||
1022 | std::string message_name = message.getName(); | ||
1023 | |||
1024 | // This class hasn't defined any incoming messages yet. | ||
1025 | // if(message_name == "message_name") | ||
1026 | // { | ||
1027 | // } | ||
1028 | // else | ||
1029 | { | ||
1030 | LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | } | ||
1035 | |||
1036 | /* virtual */ | ||
1037 | void LLPluginClassMedia::pluginLaunchFailed() | ||
1038 | { | ||
1039 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH); | ||
1040 | } | ||
1041 | |||
1042 | /* virtual */ | ||
1043 | void LLPluginClassMedia::pluginDied() | ||
1044 | { | ||
1045 | mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED); | ||
1046 | } | ||
1047 | |||
1048 | void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event) | ||
1049 | { | ||
1050 | if(mOwner) | ||
1051 | { | ||
1052 | mOwner->handleMediaEvent(this, event); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | void LLPluginClassMedia::sendMessage(const LLPluginMessage &message) | ||
1057 | { | ||
1058 | if(mPlugin && mPlugin->isRunning()) | ||
1059 | { | ||
1060 | mPlugin->sendMessage(message); | ||
1061 | } | ||
1062 | else | ||
1063 | { | ||
1064 | // The plugin isn't set up yet -- queue this message to be sent after initialization. | ||
1065 | mSendQueue.push(message); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | //////////////////////////////////////////////////////////// | ||
1070 | // MARK: media_browser class functions | ||
1071 | bool LLPluginClassMedia::pluginSupportsMediaBrowser(void) | ||
1072 | { | ||
1073 | std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER); | ||
1074 | return !version.empty(); | ||
1075 | } | ||
1076 | |||
1077 | void LLPluginClassMedia::focus(bool focused) | ||
1078 | { | ||
1079 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus"); | ||
1080 | |||
1081 | message.setValueBoolean("focused", focused); | ||
1082 | |||
1083 | sendMessage(message); | ||
1084 | } | ||
1085 | |||
1086 | void LLPluginClassMedia::clear_cache() | ||
1087 | { | ||
1088 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache"); | ||
1089 | sendMessage(message); | ||
1090 | } | ||
1091 | |||
1092 | void LLPluginClassMedia::clear_cookies() | ||
1093 | { | ||
1094 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies"); | ||
1095 | sendMessage(message); | ||
1096 | } | ||
1097 | |||
1098 | void LLPluginClassMedia::set_cookies(const std::string &cookies) | ||
1099 | { | ||
1100 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); | ||
1101 | message.setValue("cookies", cookies); | ||
1102 | sendMessage(message); | ||
1103 | } | ||
1104 | |||
1105 | void LLPluginClassMedia::enable_cookies(bool enable) | ||
1106 | { | ||
1107 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); | ||
1108 | message.setValueBoolean("enable", enable); | ||
1109 | sendMessage(message); | ||
1110 | } | ||
1111 | |||
1112 | void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port) | ||
1113 | { | ||
1114 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup"); | ||
1115 | |||
1116 | message.setValueBoolean("enable", enable); | ||
1117 | message.setValue("host", host); | ||
1118 | message.setValueS32("port", port); | ||
1119 | |||
1120 | sendMessage(message); | ||
1121 | } | ||
1122 | |||
1123 | void LLPluginClassMedia::browse_stop() | ||
1124 | { | ||
1125 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop"); | ||
1126 | sendMessage(message); | ||
1127 | } | ||
1128 | |||
1129 | void LLPluginClassMedia::browse_reload(bool ignore_cache) | ||
1130 | { | ||
1131 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload"); | ||
1132 | |||
1133 | message.setValueBoolean("ignore_cache", ignore_cache); | ||
1134 | |||
1135 | sendMessage(message); | ||
1136 | } | ||
1137 | |||
1138 | void LLPluginClassMedia::browse_forward() | ||
1139 | { | ||
1140 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward"); | ||
1141 | sendMessage(message); | ||
1142 | } | ||
1143 | |||
1144 | void LLPluginClassMedia::browse_back() | ||
1145 | { | ||
1146 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back"); | ||
1147 | sendMessage(message); | ||
1148 | } | ||
1149 | |||
1150 | void LLPluginClassMedia::set_status_redirect(int code, const std::string &url) | ||
1151 | { | ||
1152 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect"); | ||
1153 | |||
1154 | message.setValueS32("code", code); | ||
1155 | message.setValue("url", url); | ||
1156 | |||
1157 | sendMessage(message); | ||
1158 | } | ||
1159 | |||
1160 | void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) | ||
1161 | { | ||
1162 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent"); | ||
1163 | |||
1164 | message.setValue("user_agent", user_agent); | ||
1165 | |||
1166 | sendMessage(message); | ||
1167 | } | ||
1168 | |||
1169 | void LLPluginClassMedia::crashPlugin() | ||
1170 | { | ||
1171 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); | ||
1172 | |||
1173 | sendMessage(message); | ||
1174 | } | ||
1175 | |||
1176 | void LLPluginClassMedia::hangPlugin() | ||
1177 | { | ||
1178 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang"); | ||
1179 | |||
1180 | sendMessage(message); | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | //////////////////////////////////////////////////////////// | ||
1185 | // MARK: media_time class functions | ||
1186 | bool LLPluginClassMedia::pluginSupportsMediaTime(void) | ||
1187 | { | ||
1188 | std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME); | ||
1189 | return !version.empty(); | ||
1190 | } | ||
1191 | |||
1192 | void LLPluginClassMedia::stop() | ||
1193 | { | ||
1194 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop"); | ||
1195 | sendMessage(message); | ||
1196 | } | ||
1197 | |||
1198 | void LLPluginClassMedia::start(float rate) | ||
1199 | { | ||
1200 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start"); | ||
1201 | |||
1202 | message.setValueReal("rate", rate); | ||
1203 | |||
1204 | sendMessage(message); | ||
1205 | } | ||
1206 | |||
1207 | void LLPluginClassMedia::pause() | ||
1208 | { | ||
1209 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause"); | ||
1210 | sendMessage(message); | ||
1211 | } | ||
1212 | |||
1213 | void LLPluginClassMedia::seek(float time) | ||
1214 | { | ||
1215 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek"); | ||
1216 | |||
1217 | message.setValueReal("time", time); | ||
1218 | |||
1219 | sendMessage(message); | ||
1220 | } | ||
1221 | |||
1222 | void LLPluginClassMedia::setLoop(bool loop) | ||
1223 | { | ||
1224 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop"); | ||
1225 | |||
1226 | message.setValueBoolean("loop", loop); | ||
1227 | |||
1228 | sendMessage(message); | ||
1229 | } | ||
1230 | |||
1231 | void LLPluginClassMedia::setVolume(float volume) | ||
1232 | { | ||
1233 | if(volume != mRequestedVolume) | ||
1234 | { | ||
1235 | mRequestedVolume = volume; | ||
1236 | |||
1237 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume"); | ||
1238 | |||
1239 | message.setValueReal("volume", volume); | ||
1240 | |||
1241 | sendMessage(message); | ||
1242 | } | ||
1243 | } | ||
1244 | |||
1245 | float LLPluginClassMedia::getVolume() | ||
1246 | { | ||
1247 | return mRequestedVolume; | ||
1248 | } | ||
1249 | |||
1250 | void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history) | ||
1251 | { | ||
1252 | // Send URL history to plugin | ||
1253 | LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history"); | ||
1254 | message.setValueLLSD("history", url_history); | ||
1255 | sendMessage(message); | ||
1256 | |||
1257 | LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL; | ||
1258 | } | ||
1259 | |||