PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llplugin/llpluginclassmedia.cpp

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