aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llplugin/llpluginclassmedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xlinden/indra/llplugin/llpluginclassmedia.cpp1259
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
44static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
45
46static 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
57LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
58{
59 mOwner = owner;
60 mPlugin = NULL;
61 reset();
62
63 //debug use
64 mDeleteOK = true ;
65}
66
67
68LLPluginClassMedia::~LLPluginClassMedia()
69{
70 llassert_always(mDeleteOK) ;
71 reset();
72}
73
74bool 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
92void 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
162void 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
277int LLPluginClassMedia::getTextureWidth() const
278{
279 return nextPowerOf2(mTextureWidth);
280}
281
282int LLPluginClassMedia::getTextureHeight() const
283{
284 return nextPowerOf2(mTextureHeight);
285}
286
287unsigned 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
297void 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
313void 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
368void LLPluginClassMedia::setAutoScale(bool auto_scale)
369{
370 if(auto_scale != mAutoScaleMedia)
371 {
372 mAutoScaleMedia = auto_scale;
373 setSizeInternal();
374 }
375}
376
377bool 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
394bool 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
406void LLPluginClassMedia::resetDirty(void)
407{
408 mDirtyRect = LLRect::null;
409}
410
411std::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
442void 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
490bool 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
555void 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
566bool 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
579void 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
588const 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
605void 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
655void 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
667F64 LLPluginClassMedia::getCPUUsage()
668{
669 F64 result = 0.0f;
670
671 if(mPlugin)
672 {
673 result = mPlugin->getCPUUsage();
674 }
675
676 return result;
677}
678
679void LLPluginClassMedia::cut()
680{
681 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
682 sendMessage(message);
683}
684
685void LLPluginClassMedia::copy()
686{
687 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
688 sendMessage(message);
689}
690
691void LLPluginClassMedia::paste()
692{
693 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
694 sendMessage(message);
695}
696
697void 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
704void 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
711void 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
718void 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
725LLPluginClassMedia::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 */
746void 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 */
1037void LLPluginClassMedia::pluginLaunchFailed()
1038{
1039 mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
1040}
1041
1042/* virtual */
1043void LLPluginClassMedia::pluginDied()
1044{
1045 mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
1046}
1047
1048void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
1049{
1050 if(mOwner)
1051 {
1052 mOwner->handleMediaEvent(this, event);
1053 }
1054}
1055
1056void 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
1071bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
1072{
1073 std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
1074 return !version.empty();
1075}
1076
1077void 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
1086void LLPluginClassMedia::clear_cache()
1087{
1088 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
1089 sendMessage(message);
1090}
1091
1092void LLPluginClassMedia::clear_cookies()
1093{
1094 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
1095 sendMessage(message);
1096}
1097
1098void 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
1105void 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
1112void 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
1123void LLPluginClassMedia::browse_stop()
1124{
1125 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
1126 sendMessage(message);
1127}
1128
1129void 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
1138void LLPluginClassMedia::browse_forward()
1139{
1140 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
1141 sendMessage(message);
1142}
1143
1144void LLPluginClassMedia::browse_back()
1145{
1146 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
1147 sendMessage(message);
1148}
1149
1150void 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
1160void 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
1169void LLPluginClassMedia::crashPlugin()
1170{
1171 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
1172
1173 sendMessage(message);
1174}
1175
1176void 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
1186bool LLPluginClassMedia::pluginSupportsMediaTime(void)
1187{
1188 std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
1189 return !version.empty();
1190}
1191
1192void LLPluginClassMedia::stop()
1193{
1194 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
1195 sendMessage(message);
1196}
1197
1198void 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
1207void LLPluginClassMedia::pause()
1208{
1209 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
1210 sendMessage(message);
1211}
1212
1213void 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
1222void 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
1231void 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
1245float LLPluginClassMedia::getVolume()
1246{
1247 return mRequestedVolume;
1248}
1249
1250void 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