llpluginclassmedia.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714
  1. /**
  2. * @file llpluginclassmedia.cpp
  3. * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
  4. *
  5. * $LicenseInfo:firstyear=2008&license=viewergpl$
  6. *
  7. * Copyright (c) 2008-2009, Linden Research, Inc.
  8. * Copyright (c) 2009-2024, Henri Beauchamp.
  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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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. #include "linden_common.h"
  34. #include "indra_constants.h"
  35. #include "llpluginclassmedia.h"
  36. #include "llpluginmessageclasses.h"
  37. // Instantiated in llwindow/llwindow.cpp
  38. extern bool gHiDPISupport;
  39. // Static members
  40. std::string LLPluginClassMedia::sOpenIdCookieURL;
  41. std::string LLPluginClassMedia::sOpenIdCookieHost;
  42. std::string LLPluginClassMedia::sOpenIdCookiePath;
  43. std::string LLPluginClassMedia::sOpenIdCookieName;
  44. std::string LLPluginClassMedia::sOpenIdCookieValue;
  45. static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
  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. return next_power_of_2;
  54. }
  55. LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner* owner)
  56. : mOwner(owner),
  57. mPlugin(NULL),
  58. mDeleteOK(true)
  59. {
  60. reset();
  61. }
  62. LLPluginClassMedia::~LLPluginClassMedia()
  63. {
  64. llassert_always(mDeleteOK);
  65. reset();
  66. }
  67. bool LLPluginClassMedia::init(const std::string& launcher_filename,
  68. const std::string& plugin_dir,
  69. const std::string& plugin_filename,
  70. bool debug)
  71. {
  72. LL_DEBUGS("Plugin") << "Launcher: " << launcher_filename
  73. << " - Plugin directory: " << plugin_dir
  74. << " - Plugin file name: " << plugin_filename
  75. << LL_ENDL;
  76. mPluginFileName = plugin_filename;
  77. mPlugin = LLPluginProcessParent::create(this);
  78. mPlugin->setSleepTime(mSleepTime);
  79. // Queue up the media init message; it will be sent after all the currently
  80. // queued messages.
  81. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
  82. message.setValue("target", mTarget);
  83. message.setValueReal("factor", mZoomFactor);
  84. sendMessage(message);
  85. llinfos << "Initializing: " << plugin_filename << llendl;
  86. mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
  87. return true;
  88. }
  89. void LLPluginClassMedia::reset()
  90. {
  91. if (mPlugin)
  92. {
  93. mPlugin->requestShutdown();
  94. mPlugin.reset();
  95. }
  96. mTextureParamsReceived = false;
  97. mRequestedTextureDepth = 0;
  98. mRequestedTextureInternalFormat = mRequestedTextureFormat = 0;
  99. mRequestedTextureType = 0;
  100. mRequestedTextureSwapBytes = mRequestedTextureCoordsOpenGL = false;
  101. mTextureSharedMemorySize = 0;
  102. mTextureSharedMemoryName.clear();
  103. mDefaultMediaWidth = mDefaultMediaHeight = 0;
  104. mNaturalMediaWidth = mNaturalMediaHeight = 0;
  105. mSetMediaWidth = mSetMediaHeight = -1;
  106. mRequestedMediaWidth = mRequestedMediaHeight = 0;
  107. mRequestedTextureWidth = mRequestedTextureHeight = 0;
  108. mFullMediaWidth = mFullMediaHeight = 0;
  109. mTextureWidth = mTextureHeight = 0;
  110. mMediaWidth = mMediaHeight = 0;
  111. mZoomFactor = 1.0;
  112. mDirtyRect = LLRect::null;
  113. mAutoScaleMedia = false;
  114. mRequestedVolume = 1.f;
  115. mPriority = PRIORITY_NORMAL;
  116. mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
  117. mAllowDownsample = false;
  118. mPadding = 0;
  119. mLastMouseX = mLastMouseY = 0;
  120. mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
  121. mSleepTime = 0.01f;
  122. mCanCut = mCanCopy = mCanPaste = false;
  123. mIsMultipleFilePick = false;
  124. mMediaName.clear();
  125. mArtist.clear();
  126. mBackgroundColor = LLColor4::white;
  127. // Media browser class
  128. mNavigateURI.clear();
  129. mNavigateResultCode = -1;
  130. mNavigateResultString.clear();
  131. mHistoryBackAvailable = mHistoryForwardAvailable = false;
  132. mStatusText.clear();
  133. mProgressPercent = 0;
  134. mClickURL.clear();
  135. mClickNavType.clear();
  136. mClickTarget.clear();
  137. mOverrideClickTarget.clear();
  138. mClickEnforceTarget = false;
  139. mClickUUID.clear();
  140. mStatusCode = 0;
  141. // Media time class
  142. mCurrentTime = mCurrentRate = mDuration = mLoadedDuration = 0.f;
  143. // Voice class
  144. mAudioLevel = 0.f;
  145. mDebugVoice = false;
  146. }
  147. void LLPluginClassMedia::idle()
  148. {
  149. if (mPlugin)
  150. {
  151. mPlugin->idle();
  152. }
  153. if (mOwner && mTextureParamsReceived && mMediaWidth != -1 &&
  154. mPlugin && !mPlugin->isBlocked() &&
  155. (mRequestedMediaWidth != mMediaWidth ||
  156. mRequestedMediaHeight != mMediaHeight))
  157. {
  158. // Calculate the correct size for the media texture
  159. mRequestedTextureHeight = mRequestedMediaHeight;
  160. if (mPadding < 0)
  161. {
  162. // Negative values indicate the plugin wants a power of 2
  163. mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
  164. }
  165. else
  166. {
  167. mRequestedTextureWidth = mRequestedMediaWidth;
  168. if (mPadding > 1)
  169. {
  170. // Pad up to a multiple of the specified number of bytes per
  171. // row
  172. int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
  173. int pad = rowbytes % mPadding;
  174. if (pad != 0)
  175. {
  176. rowbytes += mPadding - pad;
  177. }
  178. if (rowbytes % mRequestedTextureDepth == 0)
  179. {
  180. mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
  181. }
  182. else
  183. {
  184. llwarns << "Unable to pad texture width, padding size "
  185. << mPadding << " is not a multiple of pixel size "
  186. << mRequestedTextureDepth << llendl;
  187. }
  188. }
  189. }
  190. // Size change has been requested but not initiated yet.
  191. size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight *
  192. mRequestedTextureDepth;
  193. // Add an extra line for padding, just in case.
  194. newsize += mRequestedTextureWidth * mRequestedTextureDepth;
  195. if (newsize != mTextureSharedMemorySize)
  196. {
  197. if (!mTextureSharedMemoryName.empty())
  198. {
  199. // Tell the plugin to remove the old memory segment
  200. mPlugin->removeSharedMemory(mTextureSharedMemoryName);
  201. mTextureSharedMemoryName.clear();
  202. }
  203. mTextureSharedMemorySize = newsize;
  204. mTextureSharedMemoryName =
  205. mPlugin->addSharedMemory(mTextureSharedMemorySize);
  206. if (!mTextureSharedMemoryName.empty())
  207. {
  208. void* addr =
  209. mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
  210. if (addr)
  211. {
  212. // Clear texture memory to avoid random screen visual fuzz
  213. // from uninitialized texture data
  214. memset(addr, 0, newsize);
  215. }
  216. else
  217. {
  218. llwarns << "No texture memory found for: "
  219. << mTextureSharedMemoryName << llendl;
  220. }
  221. #if 0 // We could do this to force an update, but textureValid() will
  222. // still be returning false until the first roundtrip to the
  223. // plugin, so it may not be worthwhile.
  224. mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth,
  225. mRequestedMediaHeight);
  226. #endif
  227. }
  228. }
  229. // This is our local indicator that a change is in progress.
  230. mTextureWidth = mTextureHeight = mMediaWidth = mMediaHeight = -1;
  231. // This invalidates any existing dirty rect.
  232. resetDirty();
  233. // Send a size change message to the plugin
  234. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
  235. message.setValue("name", mTextureSharedMemoryName);
  236. message.setValueS32("width", mRequestedMediaWidth);
  237. message.setValueS32("height", mRequestedMediaHeight);
  238. message.setValueS32("texture_width", mRequestedTextureWidth);
  239. message.setValueS32("texture_height", mRequestedTextureHeight);
  240. message.setValueReal("background_r", mBackgroundColor.mV[VX]);
  241. message.setValueReal("background_g", mBackgroundColor.mV[VY]);
  242. message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
  243. message.setValueReal("background_a", mBackgroundColor.mV[VW]);
  244. // DO NOT just use sendMessage() here: we want this to jump ahead of
  245. // the queue.
  246. LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
  247. mPlugin->sendMessage(message);
  248. }
  249. if (mPlugin && mPlugin->isRunning())
  250. {
  251. // Send queued messages
  252. while (!mSendQueue.empty())
  253. {
  254. LLPluginMessage message = mSendQueue.front();
  255. mSendQueue.pop();
  256. mPlugin->sendMessage(message);
  257. }
  258. }
  259. }
  260. int LLPluginClassMedia::getTextureWidth() const
  261. {
  262. return nextPowerOf2(mTextureWidth);
  263. }
  264. int LLPluginClassMedia::getTextureHeight() const
  265. {
  266. return nextPowerOf2(mTextureHeight);
  267. }
  268. unsigned char* LLPluginClassMedia::getBitsData()
  269. {
  270. void* result = NULL;
  271. if (mPlugin && !mTextureSharedMemoryName.empty())
  272. {
  273. result = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
  274. }
  275. return (unsigned char*)result;
  276. }
  277. void LLPluginClassMedia::setSize(int width, int height)
  278. {
  279. if (width > 0 && height > 0)
  280. {
  281. mSetMediaWidth = width;
  282. mSetMediaHeight = height;
  283. }
  284. else
  285. {
  286. mSetMediaWidth = mSetMediaHeight = -1;
  287. }
  288. setSizeInternal();
  289. }
  290. void LLPluginClassMedia::setSizeInternal()
  291. {
  292. if (mSetMediaWidth > 0 && mSetMediaHeight > 0)
  293. {
  294. mRequestedMediaWidth = mSetMediaWidth;
  295. mRequestedMediaHeight = mSetMediaHeight;
  296. }
  297. else if (mNaturalMediaWidth > 0 && mNaturalMediaHeight > 0)
  298. {
  299. mRequestedMediaWidth = mNaturalMediaWidth;
  300. mRequestedMediaHeight = mNaturalMediaHeight;
  301. }
  302. else
  303. {
  304. mRequestedMediaWidth = mDefaultMediaWidth;
  305. mRequestedMediaHeight = mDefaultMediaHeight;
  306. }
  307. // Save these for size/interest calculations
  308. mFullMediaWidth = mRequestedMediaWidth;
  309. mFullMediaHeight = mRequestedMediaHeight;
  310. if (mAllowDownsample &&
  311. (mPriority == PRIORITY_SLIDESHOW || mPriority == PRIORITY_LOW))
  312. {
  313. // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
  314. while (mRequestedMediaWidth > mLowPrioritySizeLimit ||
  315. mRequestedMediaHeight > mLowPrioritySizeLimit)
  316. {
  317. mRequestedMediaWidth /= 2;
  318. mRequestedMediaHeight /= 2;
  319. }
  320. }
  321. if (mAutoScaleMedia)
  322. {
  323. mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
  324. mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
  325. }
  326. // X11 can be configured for virtual displays larger than monitor screen...
  327. #if !LL_LINUX
  328. if (!gHiDPISupport)
  329. {
  330. if (mRequestedMediaWidth > 4096)
  331. {
  332. mRequestedMediaWidth = 4096;
  333. }
  334. if (mRequestedMediaHeight > 4096)
  335. {
  336. mRequestedMediaHeight = 4096;
  337. }
  338. }
  339. #endif
  340. }
  341. void LLPluginClassMedia::setAutoScale(bool auto_scale)
  342. {
  343. if (auto_scale != mAutoScaleMedia)
  344. {
  345. mAutoScaleMedia = auto_scale;
  346. setSizeInternal();
  347. }
  348. }
  349. bool LLPluginClassMedia::textureValid()
  350. {
  351. return mTextureParamsReceived && mTextureWidth > 0 && mTextureHeight > 0 &&
  352. mMediaWidth > 0 && mMediaWidth == mRequestedMediaWidth &&
  353. mMediaHeight > 0 && mMediaHeight == mRequestedMediaHeight &&
  354. getBitsData() != NULL;
  355. }
  356. bool LLPluginClassMedia::getDirty(LLRect* dirty_rect)
  357. {
  358. bool result = !mDirtyRect.isEmpty();
  359. if (dirty_rect)
  360. {
  361. *dirty_rect = mDirtyRect;
  362. }
  363. return result;
  364. }
  365. void LLPluginClassMedia::resetDirty()
  366. {
  367. mDirtyRect = LLRect::null;
  368. }
  369. std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
  370. {
  371. std::string result;
  372. if (modifiers & MASK_CONTROL)
  373. {
  374. result += "control|";
  375. }
  376. if (modifiers & MASK_ALT)
  377. {
  378. result += "alt|";
  379. }
  380. if (modifiers & MASK_SHIFT)
  381. {
  382. result += "shift|";
  383. }
  384. // *TODO: should we deal with platform differences here or in callers ?
  385. // TODO: how do we deal with the Mac "command" key ?
  386. #if 0
  387. if (modifiers & MASK_SOMETHING)
  388. {
  389. result += "meta|";
  390. }
  391. #endif
  392. return result;
  393. }
  394. void LLPluginClassMedia::jsEnableObject(bool enable)
  395. {
  396. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  397. {
  398. return;
  399. }
  400. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
  401. message.setValueBoolean("enable", enable);
  402. sendMessage(message);
  403. }
  404. void LLPluginClassMedia::jsAgentLocationEvent(double x, double y, double z)
  405. {
  406. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  407. {
  408. return;
  409. }
  410. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  411. "js_agent_location");
  412. message.setValueReal("x", x);
  413. message.setValueReal("y", y);
  414. message.setValueReal("z", z);
  415. sendMessage(message);
  416. }
  417. void LLPluginClassMedia::jsAgentGlobalLocationEvent(double x, double y,
  418. double z)
  419. {
  420. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  421. {
  422. return;
  423. }
  424. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  425. "js_agent_global_location");
  426. message.setValueReal("x", x);
  427. message.setValueReal("y", y);
  428. message.setValueReal("z", z);
  429. sendMessage(message);
  430. }
  431. void LLPluginClassMedia::jsAgentOrientationEvent(double angle)
  432. {
  433. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  434. {
  435. return;
  436. }
  437. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  438. "js_agent_orientation");
  439. message.setValueReal("angle", angle);
  440. sendMessage(message);
  441. }
  442. void LLPluginClassMedia::jsAgentLanguageEvent(const std::string& language)
  443. {
  444. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  445. {
  446. return;
  447. }
  448. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
  449. message.setValue("language", language);
  450. sendMessage(message);
  451. }
  452. void LLPluginClassMedia::jsAgentRegionEvent(const std::string& region)
  453. {
  454. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  455. {
  456. return;
  457. }
  458. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
  459. message.setValue("region", region);
  460. sendMessage(message);
  461. }
  462. void LLPluginClassMedia::jsAgentMaturityEvent(const std::string& maturity)
  463. {
  464. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  465. {
  466. return;
  467. }
  468. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
  469. message.setValue("maturity", maturity);
  470. sendMessage(message);
  471. }
  472. void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button,
  473. int x, int y, MASK modifiers)
  474. {
  475. if (type == MOUSE_EVENT_MOVE)
  476. {
  477. if (!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
  478. {
  479. // Do not queue up mouse move events that cannot be delivered.
  480. return;
  481. }
  482. if (x == mLastMouseX && y == mLastMouseY)
  483. {
  484. // Do not spam unnecessary mouse move events.
  485. return;
  486. }
  487. mLastMouseX = x;
  488. mLastMouseY = y;
  489. }
  490. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
  491. std::string temp;
  492. switch (type)
  493. {
  494. case MOUSE_EVENT_DOWN: temp = "down"; break;
  495. case MOUSE_EVENT_UP: temp = "up"; break;
  496. case MOUSE_EVENT_MOVE: temp = "move"; break;
  497. case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click";
  498. }
  499. message.setValue("event", temp);
  500. message.setValueS32("button", button);
  501. message.setValueS32("x", x);
  502. // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip
  503. // them here if the plugin has requested it.
  504. if (!mRequestedTextureCoordsOpenGL)
  505. {
  506. // TODO: whould we use mMediaHeight or mRequestedMediaHeight here ?
  507. y = mMediaHeight - y;
  508. }
  509. message.setValueS32("y", y);
  510. message.setValue("modifiers", translateModifiers(modifiers));
  511. sendMessage(message);
  512. }
  513. bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code,
  514. MASK modifiers, LLSD native_key_data)
  515. {
  516. bool result = true;
  517. // FIXME:
  518. // HACK: we do not have an easy way to tell if the plugin is going to
  519. // handle a particular keycode. For now, return false for the ones the
  520. // CEF3 plugin won't handle properly.
  521. switch (key_code)
  522. {
  523. case KEY_BACKSPACE:
  524. case KEY_TAB:
  525. case KEY_RETURN:
  526. case KEY_PAD_RETURN:
  527. case KEY_SHIFT:
  528. case KEY_CONTROL:
  529. case KEY_ALT:
  530. case KEY_CAPSLOCK:
  531. case KEY_ESCAPE:
  532. case KEY_PAGE_UP:
  533. case KEY_PAGE_DOWN:
  534. case KEY_END:
  535. case KEY_HOME:
  536. case KEY_LEFT:
  537. case KEY_UP:
  538. case KEY_RIGHT:
  539. case KEY_DOWN:
  540. case KEY_INSERT:
  541. case KEY_DELETE:
  542. // These will be handled
  543. break;
  544. default:
  545. // Regular ASCII characters will also be handled
  546. if (key_code >= KEY_SPECIAL)
  547. {
  548. // Other "special" codes will not work properly.
  549. result = false;
  550. }
  551. }
  552. #if LL_DARWIN
  553. if (modifiers & MASK_ALT)
  554. {
  555. // Option-key modified characters should be handled by the unicode
  556. // input path instead of this one.
  557. result = false;
  558. }
  559. #endif
  560. if (result)
  561. {
  562. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
  563. std::string temp;
  564. switch (type)
  565. {
  566. case KEY_EVENT_DOWN: temp = "down"; break;
  567. case KEY_EVENT_UP: temp = "up"; break;
  568. case KEY_EVENT_REPEAT: temp = "repeat";
  569. }
  570. message.setValue("event", temp);
  571. message.setValueS32("key", key_code);
  572. message.setValue("modifiers", translateModifiers(modifiers));
  573. message.setValueLLSD("native_key_data", native_key_data);
  574. sendMessage(message);
  575. }
  576. return result;
  577. }
  578. void LLPluginClassMedia::scrollEvent(int x, int y, int clicks_x, int clicks_y,
  579. MASK modifiers)
  580. {
  581. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
  582. message.setValueS32("x", x);
  583. message.setValueS32("y", y);
  584. message.setValueS32("clicks_x", clicks_x);
  585. message.setValueS32("clicks_y", clicks_y);
  586. message.setValue("modifiers", translateModifiers(modifiers));
  587. sendMessage(message);
  588. }
  589. bool LLPluginClassMedia::textInput(const std::string& text, MASK modifiers,
  590. LLSD native_key_data)
  591. {
  592. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
  593. message.setValue("text", text);
  594. message.setValue("modifiers", translateModifiers(modifiers));
  595. message.setValueLLSD("native_key_data", native_key_data);
  596. sendMessage(message);
  597. return true;
  598. }
  599. void LLPluginClassMedia::setCookie(const std::string& uri,
  600. const std::string& name,
  601. const std::string& value,
  602. const std::string& domain,
  603. const std::string& path,
  604. bool httponly, bool secure)
  605. {
  606. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
  607. message.setValue("uri", uri);
  608. message.setValue("name", name);
  609. message.setValue("value", value);
  610. message.setValue("domain", domain);
  611. message.setValue("path", path);
  612. message.setValueBoolean("httponly", httponly);
  613. message.setValueBoolean("secure", secure);
  614. sendMessage(message);
  615. }
  616. void LLPluginClassMedia::injectOpenIdCookie()
  617. {
  618. if (!sOpenIdCookieURL.empty())
  619. {
  620. setCookie(sOpenIdCookieURL, sOpenIdCookieName, sOpenIdCookieValue,
  621. sOpenIdCookieHost, sOpenIdCookiePath, true, true);
  622. }
  623. }
  624. void LLPluginClassMedia::loadURI(const std::string& uri)
  625. {
  626. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
  627. message.setValue("uri", uri);
  628. sendMessage(message);
  629. }
  630. const char* LLPluginClassMedia::priorityToString(EPriority priority)
  631. {
  632. const char* result = "UNKNOWN";
  633. switch (priority)
  634. {
  635. case PRIORITY_UNLOADED: result = "unloaded"; break;
  636. case PRIORITY_STOPPED: result = "stopped"; break;
  637. case PRIORITY_HIDDEN: result = "hidden"; break;
  638. case PRIORITY_SLIDESHOW: result = "slideshow"; break;
  639. case PRIORITY_LOW: result = "low"; break;
  640. case PRIORITY_NORMAL: result = "normal"; break;
  641. case PRIORITY_HIGH: result = "high";
  642. }
  643. return result;
  644. }
  645. void LLPluginClassMedia::setPriority(EPriority priority)
  646. {
  647. if (mPriority != priority)
  648. {
  649. mPriority = priority;
  650. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
  651. std::string priority_string = priorityToString(priority);
  652. switch (priority)
  653. {
  654. case PRIORITY_UNLOADED:
  655. case PRIORITY_STOPPED:
  656. case PRIORITY_HIDDEN:
  657. case PRIORITY_SLIDESHOW:
  658. mSleepTime = 1.f;
  659. break;
  660. case PRIORITY_LOW:
  661. mSleepTime = 1.f / 25.f;
  662. break;
  663. case PRIORITY_NORMAL:
  664. mSleepTime = 1.f / 50.f;
  665. break;
  666. case PRIORITY_HIGH:
  667. mSleepTime = 1.f / 100.f;
  668. }
  669. message.setValue("priority", priority_string);
  670. sendMessage(message);
  671. if (mPlugin)
  672. {
  673. mPlugin->setSleepTime(mSleepTime);
  674. }
  675. LL_DEBUGS("PluginPriority") << this << ": setting priority to "
  676. << priority_string << LL_ENDL;
  677. // This may affect the calculated size, so recalculate it here.
  678. setSizeInternal();
  679. }
  680. }
  681. void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
  682. {
  683. int power = nextPowerOf2(size);
  684. if (mLowPrioritySizeLimit != power)
  685. {
  686. mLowPrioritySizeLimit = power;
  687. // This may affect the calculated size, so recalculate it here.
  688. setSizeInternal();
  689. }
  690. }
  691. F64 LLPluginClassMedia::getCPUUsage()
  692. {
  693. F64 result = 0.0;
  694. if (mPlugin)
  695. {
  696. result = mPlugin->getCPUUsage();
  697. }
  698. return result;
  699. }
  700. void LLPluginClassMedia::sendPickFileResponse(const std::string& file)
  701. {
  702. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  703. "pick_file_response");
  704. message.setValue("file", file);
  705. if (mPlugin && mPlugin->isBlocked())
  706. {
  707. // If the plugin sent a blocking pick-file request, the response
  708. // should unblock it.
  709. message.setValueBoolean("blocking_response", true);
  710. }
  711. sendMessage(message);
  712. }
  713. void LLPluginClassMedia::sendPickFileResponse(std::vector<std::string> files)
  714. {
  715. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  716. "pick_file_response");
  717. std::string file;
  718. if (!files.empty())
  719. {
  720. file = files[0];
  721. }
  722. message.setValue("file", file);
  723. if (mPlugin && mPlugin->isBlocked())
  724. {
  725. // If the plugin sent a blocking pick-file request, the response
  726. // should unblock it.
  727. message.setValueBoolean("blocking_response", true);
  728. }
  729. LLSD file_list = LLSD::emptyArray();
  730. for (S32 i = 0, count = files.size(); i < count; ++i)
  731. {
  732. file_list.append(LLSD::String(files[i]));
  733. }
  734. message.setValueLLSD("file_list", file_list);
  735. sendMessage(message);
  736. }
  737. void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string& username,
  738. const std::string& password)
  739. {
  740. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
  741. message.setValueBoolean("ok", ok);
  742. message.setValue("username", username);
  743. message.setValue("password", password);
  744. if (mPlugin && mPlugin->isBlocked())
  745. {
  746. // If the plugin sent a blocking pick-file request, the response should
  747. // unblock it.
  748. message.setValueBoolean("blocking_response", true);
  749. }
  750. sendMessage(message);
  751. }
  752. void LLPluginClassMedia::cut()
  753. {
  754. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
  755. sendMessage(message);
  756. }
  757. void LLPluginClassMedia::copy()
  758. {
  759. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
  760. sendMessage(message);
  761. }
  762. void LLPluginClassMedia::paste()
  763. {
  764. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
  765. sendMessage(message);
  766. }
  767. void LLPluginClassMedia::setUserDataPath(const std::string& user_data_path)
  768. {
  769. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  770. "set_user_data_path");
  771. message.setValue("path", user_data_path);
  772. sendMessage(message);
  773. }
  774. void LLPluginClassMedia::setLanguageCode(const std::string& language_code)
  775. {
  776. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
  777. message.setValue("language", language_code);
  778. sendMessage(message);
  779. }
  780. void LLPluginClassMedia::setPreferredFont(const std::string& family)
  781. {
  782. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  783. "preferred_font");
  784. message.setValue("font_family", family);
  785. sendMessage(message);
  786. }
  787. void LLPluginClassMedia::setMinimumFontSize(U32 size)
  788. {
  789. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  790. "minimum_font_size");
  791. message.setValueU32("size", size);
  792. sendMessage(message);
  793. }
  794. void LLPluginClassMedia::setDefaultFontSize(U32 size)
  795. {
  796. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  797. "default_font_size");
  798. message.setValueU32("size", size);
  799. sendMessage(message);
  800. }
  801. void LLPluginClassMedia::setRemoteFontsEnabled(bool enabled)
  802. {
  803. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  804. "remote_fonts");
  805. message.setValueBoolean("enable", enabled);
  806. sendMessage(message);
  807. }
  808. void LLPluginClassMedia::setPluginsEnabled(bool enabled)
  809. {
  810. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  811. "plugins_enabled");
  812. message.setValueBoolean("enable", enabled);
  813. sendMessage(message);
  814. }
  815. void LLPluginClassMedia::setJavascriptEnabled(bool enabled)
  816. {
  817. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  818. "javascript_enabled");
  819. message.setValueBoolean("enable", enabled);
  820. sendMessage(message);
  821. }
  822. void LLPluginClassMedia::enableMediaPluginDebugging(bool enable)
  823. {
  824. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA,
  825. "enable_media_plugin_debugging");
  826. message.setValueBoolean("enable", enable);
  827. sendMessage(message);
  828. }
  829. //virtual
  830. void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage& message)
  831. {
  832. std::string message_class = message.getClass();
  833. if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
  834. {
  835. std::string message_name = message.getName();
  836. if (message_name == "texture_params")
  837. {
  838. mRequestedTextureDepth = message.getValueS32("depth");
  839. mRequestedTextureInternalFormat =
  840. message.getValueU32("internalformat");
  841. mRequestedTextureFormat = message.getValueU32("format");
  842. mRequestedTextureType = message.getValueU32("type");
  843. mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
  844. mRequestedTextureCoordsOpenGL =
  845. message.getValueBoolean("coords_opengl");
  846. // These two are optional, and will default to 0 if they're not specified.
  847. mDefaultMediaWidth = message.getValueS32("default_width");
  848. mDefaultMediaHeight = message.getValueS32("default_height");
  849. mAllowDownsample = message.getValueBoolean("allow_downsample");
  850. mPadding = message.getValueS32("padding");
  851. setSizeInternal();
  852. mTextureParamsReceived = true;
  853. }
  854. else if (message_name == "updated")
  855. {
  856. if (message.hasValue("left"))
  857. {
  858. LLRect new_rect;
  859. new_rect.mLeft = message.getValueS32("left");
  860. new_rect.mTop = message.getValueS32("top");
  861. new_rect.mRight = message.getValueS32("right");
  862. new_rect.mBottom = message.getValueS32("bottom");
  863. // The plugin is likely to have top and bottom switched, due to
  864. // vertical flip and OpenGL coordinate confusion.
  865. // If they're backwards, swap them.
  866. if (new_rect.mTop < new_rect.mBottom)
  867. {
  868. S32 temp = new_rect.mTop;
  869. new_rect.mTop = new_rect.mBottom;
  870. new_rect.mBottom = temp;
  871. }
  872. if (mDirtyRect.isEmpty())
  873. {
  874. mDirtyRect = new_rect;
  875. }
  876. else
  877. {
  878. mDirtyRect.unionWith(new_rect);
  879. }
  880. #if 0 // Too spammy...
  881. LL_DEBUGS("PluginMessage") << "adjusted incoming rect is: ("
  882. << new_rect.mLeft << ", "
  883. << new_rect.mTop << ", "
  884. << new_rect.mRight << ", "
  885. << new_rect.mBottom
  886. << "), new dirty rect is: ("
  887. << mDirtyRect.mLeft << ", "
  888. << mDirtyRect.mTop << ", "
  889. << mDirtyRect.mRight << ", "
  890. << mDirtyRect.mBottom << ")"
  891. << LL_ENDL;
  892. #endif
  893. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
  894. }
  895. bool time_duration_updated = false;
  896. int previous_percent = mProgressPercent;
  897. if (message.hasValue("current_time"))
  898. {
  899. mCurrentTime = message.getValueReal("current_time");
  900. time_duration_updated = true;
  901. }
  902. if (message.hasValue("duration"))
  903. {
  904. mDuration = message.getValueReal("duration");
  905. time_duration_updated = true;
  906. }
  907. if (message.hasValue("current_rate"))
  908. {
  909. mCurrentRate = message.getValueReal("current_rate");
  910. }
  911. if (message.hasValue("loaded_duration"))
  912. {
  913. mLoadedDuration = message.getValueReal("loaded_duration");
  914. time_duration_updated = true;
  915. }
  916. else
  917. {
  918. // If the message doesn't contain a loaded_duration param,
  919. // assume it's equal to duration
  920. mLoadedDuration = mDuration;
  921. }
  922. // Calculate a percentage based on the loaded duration and total
  923. // duration.
  924. if (mDuration != 0.f) // Don't divide by zero.
  925. {
  926. mProgressPercent = (int)(mLoadedDuration * 100.f / mDuration);
  927. }
  928. if (time_duration_updated)
  929. {
  930. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
  931. }
  932. if (previous_percent != mProgressPercent)
  933. {
  934. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
  935. }
  936. }
  937. else if (message_name == "media_status")
  938. {
  939. std::string status = message.getValue("status");
  940. LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
  941. if (status == "loading")
  942. {
  943. mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
  944. }
  945. else if (status == "loaded")
  946. {
  947. mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
  948. }
  949. else if (status == "error")
  950. {
  951. mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
  952. }
  953. else if (status == "playing")
  954. {
  955. mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
  956. }
  957. else if (status == "paused")
  958. {
  959. mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
  960. }
  961. else if (status == "done")
  962. {
  963. mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
  964. }
  965. else
  966. {
  967. // empty string or any unknown string
  968. mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
  969. }
  970. }
  971. else if (message_name == "size_change_request")
  972. {
  973. #if 0 // *TODO: check that name matches ?
  974. std::string name = message.getValue("name");
  975. #endif
  976. mNaturalMediaWidth = message.getValueS32("width");
  977. mNaturalMediaHeight = message.getValueS32("height");
  978. setSizeInternal();
  979. }
  980. else if (message_name == "size_change_response")
  981. {
  982. #if 0 // *TODO: check that name matches ?
  983. std::string name = message.getValue("name");
  984. #endif
  985. mTextureWidth = message.getValueS32("texture_width");
  986. mTextureHeight = message.getValueS32("texture_height");
  987. mMediaWidth = message.getValueS32("width");
  988. mMediaHeight = message.getValueS32("height");
  989. // This invalidates any existing dirty rect.
  990. resetDirty();
  991. // *TODO: should we verify that the plugin sent back the right
  992. // values ? Two size changes in a row may cause them to not
  993. // match, due to queueing, etc.
  994. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
  995. }
  996. else if (message_name == "cursor_changed")
  997. {
  998. mCursorName = message.getValue("name");
  999. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
  1000. }
  1001. else if (message_name == "edit_state")
  1002. {
  1003. if (message.hasValue("cut"))
  1004. {
  1005. mCanCut = message.getValueBoolean("cut");
  1006. }
  1007. if (message.hasValue("copy"))
  1008. {
  1009. mCanCopy = message.getValueBoolean("copy");
  1010. }
  1011. if (message.hasValue("paste"))
  1012. {
  1013. mCanPaste = message.getValueBoolean("paste");
  1014. }
  1015. }
  1016. else if (message_name == "name_text")
  1017. {
  1018. // Streaming media name/artist:
  1019. mMediaName = message.getValue("name");
  1020. mArtist = message.getValue("artist");
  1021. // Dulahan history back/forward available event:
  1022. mHistoryBackAvailable =
  1023. message.getValueBoolean("history_back_available");
  1024. mHistoryForwardAvailable =
  1025. message.getValueBoolean("history_forward_available");
  1026. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
  1027. }
  1028. else if (message_name == "tooltip_text")
  1029. {
  1030. mHoverText = message.getValue("tooltip");
  1031. }
  1032. else if (message_name == "pick_file")
  1033. {
  1034. mIsMultipleFilePick = message.getValueBoolean("multiple_files");
  1035. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
  1036. }
  1037. else if (message_name == "auth_request")
  1038. {
  1039. mAuthURL = message.getValue("url");
  1040. mAuthRealm = message.getValue("realm");
  1041. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
  1042. }
  1043. else if (message_name == "file_download")
  1044. {
  1045. mFileDownloadFilename = message.getValue("filename");
  1046. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD);
  1047. }
  1048. else if(message_name == "debug_message")
  1049. {
  1050. mDebugMessageText = message.getValue("message_text");
  1051. mDebugMessageLevel = message.getValue("message_level");
  1052. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
  1053. }
  1054. else
  1055. {
  1056. llwarns << "Unknown " << message_name << " class message: "
  1057. << message_name << llendl;
  1058. }
  1059. }
  1060. else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
  1061. {
  1062. std::string message_name = message.getName();
  1063. if (message_name == "navigate_begin")
  1064. {
  1065. mNavigateURI = message.getValue("uri");
  1066. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
  1067. }
  1068. else if (message_name == "navigate_complete")
  1069. {
  1070. mNavigateURI = message.getValue("uri");
  1071. mNavigateResultCode = message.getValueS32("result_code");
  1072. mNavigateResultString = message.getValue("result_string");
  1073. mHistoryBackAvailable =
  1074. message.getValueBoolean("history_back_available");
  1075. mHistoryForwardAvailable =
  1076. message.getValueBoolean("history_forward_available");
  1077. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
  1078. }
  1079. else if (message_name == "progress")
  1080. {
  1081. mProgressPercent = message.getValueS32("percent");
  1082. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
  1083. }
  1084. else if (message_name == "status_text")
  1085. {
  1086. mStatusText = message.getValue("status");
  1087. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
  1088. }
  1089. else if (message_name == "location_changed")
  1090. {
  1091. mLocation = message.getValue("uri");
  1092. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
  1093. }
  1094. else if (message_name == "click_href")
  1095. {
  1096. mClickURL = message.getValue("uri");
  1097. mClickTarget = message.getValue("target");
  1098. mClickUUID = LLUUID::generateNewID().asString();
  1099. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
  1100. }
  1101. else if (message_name == "click_nofollow")
  1102. {
  1103. mClickURL = message.getValue("uri");
  1104. mClickNavType = message.getValue("nav_type");
  1105. mClickTarget.clear();
  1106. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
  1107. }
  1108. else if (message_name == "navigate_error_page")
  1109. {
  1110. mStatusCode = message.getValueS32("status_code");
  1111. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
  1112. }
  1113. else if (message_name == "close_request")
  1114. {
  1115. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
  1116. }
  1117. else if (message_name == "geometry_change")
  1118. {
  1119. mClickUUID = message.getValue("uuid");
  1120. mGeometryX = message.getValueS32("x");
  1121. mGeometryY = message.getValueS32("y");
  1122. mGeometryWidth = message.getValueS32("width");
  1123. mGeometryHeight = message.getValueS32("height");
  1124. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
  1125. }
  1126. else if (message_name == "link_hovered")
  1127. {
  1128. #if 0 // 'text' is not currently used -- the tooltip hover text is taken
  1129. // from the "title".
  1130. std::string text = message.getValue("text");
  1131. #endif
  1132. mHoverLink = message.getValue("link");
  1133. mHoverText = message.getValue("title");
  1134. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
  1135. }
  1136. else
  1137. {
  1138. llwarns << "Unknown " << message_name << " class message: "
  1139. << message_name << llendl;
  1140. }
  1141. }
  1142. else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
  1143. {
  1144. std::string message_name = message.getName();
  1145. #if 0 // This class has not defined any incoming messages yet.
  1146. if (message_name == "message_name")
  1147. {
  1148. return;
  1149. }
  1150. #endif
  1151. llwarns << "Unknown " << message_name << " class message: "
  1152. << message_name << llendl;
  1153. }
  1154. else if (message_class == LLPLUGIN_MESSAGE_CLASS_VOICE)
  1155. {
  1156. std::string message_name = message.getName();
  1157. if (message_name == "audio_level")
  1158. {
  1159. mAudioLevel = message.getValueReal("level");
  1160. }
  1161. else if (message_name == "audio_devices")
  1162. {
  1163. mWebRTCDataMutex.lock();
  1164. mCaptureDevices = message.getValueLLSD("capture");
  1165. mRenderDevices = message.getValueLLSD("render");
  1166. mWebRTCDataMutex.unlock();
  1167. }
  1168. else if (message_name == "webrtc_data")
  1169. {
  1170. LLUUID connection_id = message.getValueLLUUID("connection_id");
  1171. if (connection_id.notNull())
  1172. {
  1173. mWebRTCDataMutex.lock();
  1174. LLSD& data = getVoiceData(connection_id);
  1175. if (data.isUndefined())
  1176. {
  1177. data = LLSD::emptyArray();
  1178. }
  1179. // Append the full LLSD "params" block to the array. HB
  1180. data.append(message.getParams());
  1181. mWebRTCDataMutex.unlock();
  1182. }
  1183. }
  1184. }
  1185. }
  1186. LLSD& LLPluginClassMedia::getVoiceData(const LLUUID& connection_id)
  1187. {
  1188. std::map<LLUUID, LLSD>::iterator it = mWebRTCDataMap.find(connection_id);
  1189. if (it == mWebRTCDataMap.end())
  1190. {
  1191. auto result = mWebRTCDataMap.emplace(connection_id, LLSD());
  1192. it = result.first;
  1193. }
  1194. return it->second;
  1195. }
  1196. //virtual
  1197. void LLPluginClassMedia::pluginLaunchFailed()
  1198. {
  1199. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
  1200. }
  1201. //virtual
  1202. void LLPluginClassMedia::pluginDied()
  1203. {
  1204. mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
  1205. }
  1206. void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
  1207. {
  1208. if (mOwner)
  1209. {
  1210. mOwner->handleMediaEvent(this, event);
  1211. }
  1212. }
  1213. void LLPluginClassMedia::sendMessage(const LLPluginMessage& message)
  1214. {
  1215. if (mPlugin && mPlugin->isRunning())
  1216. {
  1217. mPlugin->sendMessage(message);
  1218. }
  1219. else
  1220. {
  1221. // The plugin is not set up yet: queue this message to be sent after
  1222. // initialization.
  1223. mSendQueue.emplace(message);
  1224. }
  1225. }
  1226. ////////////////////////////////////////////////////////////
  1227. // MARK: media_browser class functions
  1228. bool LLPluginClassMedia::pluginSupportsMediaBrowser()
  1229. {
  1230. std::string version =
  1231. mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
  1232. return !version.empty();
  1233. }
  1234. void LLPluginClassMedia::focus(bool focused)
  1235. {
  1236. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
  1237. message.setValueBoolean("focused", focused);
  1238. sendMessage(message);
  1239. }
  1240. void LLPluginClassMedia::set_page_zoom_factor(double factor)
  1241. {
  1242. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1243. "set_page_zoom_factor");
  1244. message.setValueReal("factor", factor);
  1245. sendMessage(message);
  1246. }
  1247. void LLPluginClassMedia::clear_cache()
  1248. {
  1249. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1250. "clear_cache");
  1251. sendMessage(message);
  1252. }
  1253. void LLPluginClassMedia::clear_cookies()
  1254. {
  1255. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1256. "clear_cookies");
  1257. sendMessage(message);
  1258. }
  1259. void LLPluginClassMedia::cookies_enabled(bool enable)
  1260. {
  1261. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1262. "cookies_enabled");
  1263. message.setValueBoolean("enable", enable);
  1264. sendMessage(message);
  1265. }
  1266. void LLPluginClassMedia::proxy_setup(bool enable, const std::string& host,
  1267. int port)
  1268. {
  1269. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1270. "proxy_setup");
  1271. message.setValueBoolean("enable", enable);
  1272. message.setValue("host", host);
  1273. message.setValueS32("port", port);
  1274. sendMessage(message);
  1275. }
  1276. void LLPluginClassMedia::browse_stop()
  1277. {
  1278. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1279. "browse_stop");
  1280. sendMessage(message);
  1281. }
  1282. void LLPluginClassMedia::browse_reload(bool ignore_cache)
  1283. {
  1284. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1285. "browse_reload");
  1286. message.setValueBoolean("ignore_cache", ignore_cache);
  1287. sendMessage(message);
  1288. }
  1289. void LLPluginClassMedia::browse_forward()
  1290. {
  1291. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1292. "browse_forward");
  1293. sendMessage(message);
  1294. }
  1295. void LLPluginClassMedia::browse_back()
  1296. {
  1297. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1298. "browse_back");
  1299. sendMessage(message);
  1300. }
  1301. void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
  1302. {
  1303. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1304. "set_user_agent");
  1305. message.setValue("user_agent", user_agent);
  1306. sendMessage(message);
  1307. }
  1308. void LLPluginClassMedia::showWebInspector(bool show)
  1309. {
  1310. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1311. "show_web_inspector");
  1312. // Only open for now: closed manually by user
  1313. message.setValueBoolean("show", true);
  1314. sendMessage(message);
  1315. }
  1316. void LLPluginClassMedia::proxyWindowOpened(const std::string& target,
  1317. const std::string& uuid)
  1318. {
  1319. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1320. "proxy_window_opened");
  1321. message.setValue("target", target);
  1322. message.setValue("uuid", uuid);
  1323. sendMessage(message);
  1324. }
  1325. void LLPluginClassMedia::proxyWindowClosed(const std::string& uuid)
  1326. {
  1327. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1328. "proxy_window_closed");
  1329. message.setValue("uuid", uuid);
  1330. sendMessage(message);
  1331. }
  1332. void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
  1333. {
  1334. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1335. "ignore_ssl_cert_errors");
  1336. message.setValueBoolean("ignore", ignore);
  1337. sendMessage(message);
  1338. }
  1339. void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
  1340. {
  1341. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1342. "add_certificate_file_path");
  1343. message.setValue("path", path);
  1344. sendMessage(message);
  1345. }
  1346. void LLPluginClassMedia::crashPlugin()
  1347. {
  1348. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
  1349. sendMessage(message);
  1350. }
  1351. void LLPluginClassMedia::hangPlugin()
  1352. {
  1353. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
  1354. sendMessage(message);
  1355. }
  1356. ////////////////////////////////////////////////////////////
  1357. // MARK: media_time class functions
  1358. bool LLPluginClassMedia::pluginSupportsMediaTime()
  1359. {
  1360. std::string version =
  1361. mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
  1362. return !version.empty();
  1363. }
  1364. void LLPluginClassMedia::stop()
  1365. {
  1366. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
  1367. sendMessage(message);
  1368. }
  1369. void LLPluginClassMedia::start(float rate)
  1370. {
  1371. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
  1372. message.setValueReal("rate", rate);
  1373. sendMessage(message);
  1374. }
  1375. void LLPluginClassMedia::pause()
  1376. {
  1377. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
  1378. sendMessage(message);
  1379. }
  1380. void LLPluginClassMedia::seek(float time)
  1381. {
  1382. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
  1383. message.setValueReal("time", time);
  1384. sendMessage(message);
  1385. }
  1386. void LLPluginClassMedia::setLoop(bool loop)
  1387. {
  1388. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
  1389. message.setValueBoolean("loop", loop);
  1390. sendMessage(message);
  1391. }
  1392. void LLPluginClassMedia::setVolume(float volume)
  1393. {
  1394. if (volume != mRequestedVolume)
  1395. {
  1396. mRequestedVolume = volume;
  1397. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME,
  1398. "set_volume");
  1399. message.setValueReal("volume", volume);
  1400. sendMessage(message);
  1401. }
  1402. }
  1403. void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
  1404. {
  1405. // Send URL history to plugin
  1406. LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
  1407. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER,
  1408. "init_history");
  1409. message.setValueLLSD("history", url_history);
  1410. sendMessage(message);
  1411. }
  1412. ////////////////////////////////////////////////////////////
  1413. // Voice related methods
  1414. void LLPluginClassMedia::refreshDevices()
  1415. {
  1416. mCaptureDevices.clear();
  1417. mRenderDevices.clear();
  1418. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "get_devices");
  1419. sendMessage(message);
  1420. }
  1421. void LLPluginClassMedia::setCaptureDevice(const std::string& device_id)
  1422. {
  1423. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "set_capture");
  1424. message.setValue("device_id", device_id);
  1425. sendMessage(message);
  1426. }
  1427. void LLPluginClassMedia::setRenderDevice(const std::string& device_id)
  1428. {
  1429. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "set_render");
  1430. message.setValue("device_id", device_id);
  1431. sendMessage(message);
  1432. }
  1433. void LLPluginClassMedia::setMicGain(F32 gain)
  1434. {
  1435. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "set_mic_gain");
  1436. message.setValueReal("gain", gain);
  1437. sendMessage(message);
  1438. }
  1439. void LLPluginClassMedia::setConfiguration(const LLSD& config)
  1440. {
  1441. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "configure");
  1442. message.setValueLLSD("config", config);
  1443. sendMessage(message);
  1444. }
  1445. void LLPluginClassMedia::setTuningMode(bool tuning_on)
  1446. {
  1447. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "tuning_mode");
  1448. message.setValueBoolean("enabled", tuning_on);
  1449. sendMessage(message);
  1450. }
  1451. void LLPluginClassMedia::sendVoiceCommand(const LLUUID& connection_id,
  1452. const std::string& command)
  1453. {
  1454. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, command);
  1455. message.setValueLLUUID("connection_id", connection_id);
  1456. sendMessage(message);
  1457. }
  1458. void LLPluginClassMedia::sendVoiceCmdWithBool(const LLUUID& connection_id,
  1459. const std::string& command,
  1460. const std::string& param_name,
  1461. bool param)
  1462. {
  1463. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, command);
  1464. message.setValueLLUUID("connection_id", connection_id);
  1465. message.setValueBoolean(param_name, param);
  1466. sendMessage(message);
  1467. }
  1468. void LLPluginClassMedia::sendVoiceCmdWithReal(const LLUUID& connection_id,
  1469. const std::string& command,
  1470. const std::string& param_name,
  1471. F64 param)
  1472. {
  1473. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, command);
  1474. message.setValueLLUUID("connection_id", connection_id);
  1475. message.setValueReal(param_name, param);
  1476. sendMessage(message);
  1477. }
  1478. void LLPluginClassMedia::sendVoiceCmdWithString(const LLUUID& connection_id,
  1479. const std::string& command,
  1480. const std::string& param_name,
  1481. const std::string& param)
  1482. {
  1483. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, command);
  1484. message.setValueLLUUID("connection_id", connection_id);
  1485. message.setValue(param_name, param);
  1486. sendMessage(message);
  1487. }
  1488. void LLPluginClassMedia::sendVoiceCmdWithLLSD(const LLUUID& connection_id,
  1489. const std::string& command,
  1490. const std::string& param_name,
  1491. const LLSD& param)
  1492. {
  1493. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, command);
  1494. message.setValueLLUUID("connection_id", connection_id);
  1495. message.setValueLLSD(param_name, param);
  1496. sendMessage(message);
  1497. }
  1498. void LLPluginClassMedia::setVoiceDebug(bool enable)
  1499. {
  1500. if (mDebugVoice != enable)
  1501. {
  1502. if (mPlugin && mPlugin->isRunning())
  1503. {
  1504. mDebugVoice = enable;
  1505. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_VOICE, "debug");
  1506. message.setValueBoolean("enabled", enable);
  1507. sendMessage(message);
  1508. }
  1509. }
  1510. }