PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llviewerparcelmedia.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 631 lines | 429 code | 81 blank | 121 comment | 70 complexity | 398201500a2c0e86b52bec0bd210c614 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llviewerparcelmedia.cpp
  3. * @brief Handlers for multimedia on a per-parcel basis
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llviewerparcelmedia.h"
  28. #include "llagent.h"
  29. #include "llaudioengine.h"
  30. #include "llmimetypes.h"
  31. #include "llviewercontrol.h"
  32. #include "llviewermedia.h"
  33. #include "llviewerregion.h"
  34. #include "llparcel.h"
  35. #include "llviewerparcelmgr.h"
  36. #include "lluuid.h"
  37. #include "message.h"
  38. #include "llviewermediafocus.h"
  39. #include "llviewerparcelmediaautoplay.h"
  40. #include "llnotificationsutil.h"
  41. //#include "llfirstuse.h"
  42. #include "llpluginclassmedia.h"
  43. #include "llviewertexture.h"
  44. // Static Variables
  45. S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
  46. LLUUID LLViewerParcelMedia::sMediaRegionID;
  47. viewer_media_t LLViewerParcelMedia::sMediaImpl;
  48. // static
  49. void LLViewerParcelMedia::initClass()
  50. {
  51. LLMessageSystem* msg = gMessageSystem;
  52. msg->setHandlerFunc("ParcelMediaCommandMessage", processParcelMediaCommandMessage );
  53. msg->setHandlerFunc("ParcelMediaUpdate", processParcelMediaUpdate );
  54. LLViewerParcelMediaAutoPlay::initClass();
  55. }
  56. //static
  57. void LLViewerParcelMedia::cleanupClass()
  58. {
  59. // This needs to be destroyed before global destructor time.
  60. sMediaImpl = NULL;
  61. }
  62. //////////////////////////////////////////////////////////////////////////////////////////
  63. // static
  64. void LLViewerParcelMedia::update(LLParcel* parcel)
  65. {
  66. if (/*LLViewerMedia::hasMedia()*/ true)
  67. {
  68. // we have a player
  69. if (parcel)
  70. {
  71. if(!gAgent.getRegion())
  72. {
  73. sMediaRegionID = LLUUID() ;
  74. stop() ;
  75. LL_DEBUGS("Media") << "no agent region, bailing out." << LL_ENDL;
  76. return ;
  77. }
  78. // we're in a parcel
  79. bool new_parcel = false;
  80. S32 parcelid = parcel->getLocalID();
  81. LLUUID regionid = gAgent.getRegion()->getRegionID();
  82. if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID)
  83. {
  84. LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL;
  85. sMediaParcelLocalID = parcelid;
  86. sMediaRegionID = regionid;
  87. new_parcel = true;
  88. }
  89. std::string mediaUrl = std::string ( parcel->getMediaURL () );
  90. std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL());
  91. // if we have a current (link sharing) url, use it instead
  92. if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html")
  93. {
  94. mediaUrl = mediaCurrentUrl;
  95. }
  96. LLStringUtil::trim(mediaUrl);
  97. // If no parcel media is playing, nothing left to do
  98. if(sMediaImpl.isNull())
  99. {
  100. return;
  101. }
  102. // Media is playing...has something changed?
  103. else if (( sMediaImpl->getMediaURL() != mediaUrl )
  104. || ( sMediaImpl->getMediaTextureID() != parcel->getMediaID() )
  105. || ( sMediaImpl->getMimeType() != parcel->getMediaType() ))
  106. {
  107. // Only play if the media types are the same.
  108. if(sMediaImpl->getMimeType() == parcel->getMediaType())
  109. {
  110. play(parcel);
  111. }
  112. else
  113. {
  114. stop();
  115. }
  116. }
  117. }
  118. else
  119. {
  120. stop();
  121. }
  122. }
  123. /*
  124. else
  125. {
  126. // no audio player, do a first use dialog if there is media here
  127. if (parcel)
  128. {
  129. std::string mediaUrl = std::string ( parcel->getMediaURL () );
  130. if (!mediaUrl.empty ())
  131. {
  132. if (gWarningSettings.getBOOL("QuickTimeInstalled"))
  133. {
  134. gWarningSettings.setBOOL("QuickTimeInstalled", FALSE);
  135. LLNotificationsUtil::add("NoQuickTime" );
  136. };
  137. }
  138. }
  139. }
  140. */
  141. }
  142. // static
  143. void LLViewerParcelMedia::play(LLParcel* parcel)
  144. {
  145. lldebugs << "LLViewerParcelMedia::play" << llendl;
  146. if (!parcel) return;
  147. if (!gSavedSettings.getBOOL("AudioStreamingMedia"))
  148. return;
  149. std::string media_url = parcel->getMediaURL();
  150. std::string media_current_url = parcel->getMediaCurrentURL();
  151. std::string mime_type = parcel->getMediaType();
  152. LLUUID placeholder_texture_id = parcel->getMediaID();
  153. U8 media_auto_scale = parcel->getMediaAutoScale();
  154. U8 media_loop = parcel->getMediaLoop();
  155. S32 media_width = parcel->getMediaWidth();
  156. S32 media_height = parcel->getMediaHeight();
  157. if(sMediaImpl)
  158. {
  159. // If the url and mime type are the same, call play again
  160. if(sMediaImpl->getMediaURL() == media_url
  161. && sMediaImpl->getMimeType() == mime_type
  162. && sMediaImpl->getMediaTextureID() == placeholder_texture_id)
  163. {
  164. LL_DEBUGS("Media") << "playing with existing url " << media_url << LL_ENDL;
  165. sMediaImpl->play();
  166. }
  167. // Else if the texture id's are the same, navigate and rediscover type
  168. // MBW -- This causes other state from the previous parcel (texture size, autoscale, and looping) to get re-used incorrectly.
  169. // It's also not really necessary -- just creating a new instance is fine.
  170. // else if(sMediaImpl->getMediaTextureID() == placeholder_texture_id)
  171. // {
  172. // sMediaImpl->navigateTo(media_url, mime_type, true);
  173. // }
  174. else
  175. {
  176. // Since the texture id is different, we need to generate a new impl
  177. // Delete the old one first so they don't fight over the texture.
  178. sMediaImpl = NULL;
  179. // A new impl will be created below.
  180. }
  181. }
  182. // Don't ever try to play if the media type is set to "none/none"
  183. if(stricmp(mime_type.c_str(), LLMIMETypes::getDefaultMimeType().c_str()) != 0)
  184. {
  185. if(!sMediaImpl)
  186. {
  187. LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
  188. // There is no media impl, make a new one
  189. sMediaImpl = LLViewerMedia::newMediaImpl(
  190. placeholder_texture_id,
  191. media_width,
  192. media_height,
  193. media_auto_scale,
  194. media_loop);
  195. sMediaImpl->setIsParcelMedia(true);
  196. sMediaImpl->navigateTo(media_url, mime_type, true);
  197. }
  198. //LLFirstUse::useMedia();
  199. LLViewerParcelMediaAutoPlay::playStarted();
  200. }
  201. }
  202. // static
  203. void LLViewerParcelMedia::stop()
  204. {
  205. if(sMediaImpl.isNull())
  206. {
  207. return;
  208. }
  209. // We need to remove the media HUD if it is up.
  210. LLViewerMediaFocus::getInstance()->clearFocus();
  211. // This will unload & kill the media instance.
  212. sMediaImpl = NULL;
  213. }
  214. // static
  215. void LLViewerParcelMedia::pause()
  216. {
  217. if(sMediaImpl.isNull())
  218. {
  219. return;
  220. }
  221. sMediaImpl->pause();
  222. }
  223. // static
  224. void LLViewerParcelMedia::start()
  225. {
  226. if(sMediaImpl.isNull())
  227. {
  228. return;
  229. }
  230. sMediaImpl->start();
  231. //LLFirstUse::useMedia();
  232. LLViewerParcelMediaAutoPlay::playStarted();
  233. }
  234. // static
  235. void LLViewerParcelMedia::seek(F32 time)
  236. {
  237. if(sMediaImpl.isNull())
  238. {
  239. return;
  240. }
  241. sMediaImpl->seek(time);
  242. }
  243. // static
  244. void LLViewerParcelMedia::focus(bool focus)
  245. {
  246. sMediaImpl->focus(focus);
  247. }
  248. // static
  249. LLPluginClassMediaOwner::EMediaStatus LLViewerParcelMedia::getStatus()
  250. {
  251. LLPluginClassMediaOwner::EMediaStatus result = LLPluginClassMediaOwner::MEDIA_NONE;
  252. if(sMediaImpl.notNull() && sMediaImpl->hasMedia())
  253. {
  254. result = sMediaImpl->getMediaPlugin()->getStatus();
  255. }
  256. return result;
  257. }
  258. // static
  259. std::string LLViewerParcelMedia::getMimeType()
  260. {
  261. return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : LLMIMETypes::getDefaultMimeType();
  262. }
  263. //static
  264. std::string LLViewerParcelMedia::getURL()
  265. {
  266. std::string url;
  267. if(sMediaImpl.notNull())
  268. url = sMediaImpl->getMediaURL();
  269. if(stricmp(LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaType().c_str(), LLMIMETypes::getDefaultMimeType().c_str()) != 0)
  270. {
  271. if (url.empty())
  272. url = LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaCurrentURL();
  273. if (url.empty())
  274. url = LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaURL();
  275. }
  276. return url;
  277. }
  278. //static
  279. std::string LLViewerParcelMedia::getName()
  280. {
  281. if(sMediaImpl.notNull())
  282. return sMediaImpl->getName();
  283. return "";
  284. }
  285. viewer_media_t LLViewerParcelMedia::getParcelMedia()
  286. {
  287. return sMediaImpl;
  288. }
  289. //////////////////////////////////////////////////////////////////////////////////////////
  290. // static
  291. void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** )
  292. {
  293. // extract the agent id
  294. // LLUUID agent_id;
  295. // msg->getUUID( agent_id );
  296. U32 flags;
  297. U32 command;
  298. F32 time;
  299. msg->getU32( "CommandBlock", "Flags", flags );
  300. msg->getU32( "CommandBlock", "Command", command);
  301. msg->getF32( "CommandBlock", "Time", time );
  302. if (flags &( (1<<PARCEL_MEDIA_COMMAND_STOP)
  303. | (1<<PARCEL_MEDIA_COMMAND_PAUSE)
  304. | (1<<PARCEL_MEDIA_COMMAND_PLAY)
  305. | (1<<PARCEL_MEDIA_COMMAND_LOOP)
  306. | (1<<PARCEL_MEDIA_COMMAND_UNLOAD) ))
  307. {
  308. // stop
  309. if( command == PARCEL_MEDIA_COMMAND_STOP )
  310. {
  311. stop();
  312. }
  313. else
  314. // pause
  315. if( command == PARCEL_MEDIA_COMMAND_PAUSE )
  316. {
  317. pause();
  318. }
  319. else
  320. // play
  321. if(( command == PARCEL_MEDIA_COMMAND_PLAY ) ||
  322. ( command == PARCEL_MEDIA_COMMAND_LOOP ))
  323. {
  324. if (getStatus() == LLViewerMediaImpl::MEDIA_PAUSED)
  325. {
  326. start();
  327. }
  328. else
  329. {
  330. LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  331. play(parcel);
  332. }
  333. }
  334. else
  335. // unload
  336. if( command == PARCEL_MEDIA_COMMAND_UNLOAD )
  337. {
  338. stop();
  339. }
  340. }
  341. if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME))
  342. {
  343. if(sMediaImpl.isNull())
  344. {
  345. LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  346. play(parcel);
  347. }
  348. seek(time);
  349. }
  350. }
  351. //////////////////////////////////////////////////////////////////////////////////////////
  352. // static
  353. void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void ** )
  354. {
  355. LLUUID media_id;
  356. std::string media_url;
  357. std::string media_type;
  358. S32 media_width = 0;
  359. S32 media_height = 0;
  360. U8 media_auto_scale = FALSE;
  361. U8 media_loop = FALSE;
  362. msg->getUUID( "DataBlock", "MediaID", media_id );
  363. char media_url_buffer[257];
  364. msg->getString( "DataBlock", "MediaURL", 255, media_url_buffer );
  365. media_url = media_url_buffer;
  366. msg->getU8("DataBlock", "MediaAutoScale", media_auto_scale);
  367. if (msg->has("DataBlockExtended")) // do we have the extended data?
  368. {
  369. char media_type_buffer[257];
  370. msg->getString("DataBlockExtended", "MediaType", 255, media_type_buffer);
  371. media_type = media_type_buffer;
  372. msg->getU8("DataBlockExtended", "MediaLoop", media_loop);
  373. msg->getS32("DataBlockExtended", "MediaWidth", media_width);
  374. msg->getS32("DataBlockExtended", "MediaHeight", media_height);
  375. }
  376. LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  377. BOOL same = FALSE;
  378. if (parcel)
  379. {
  380. same = ((parcel->getMediaURL() == media_url) &&
  381. (parcel->getMediaType() == media_type) &&
  382. (parcel->getMediaID() == media_id) &&
  383. (parcel->getMediaWidth() == media_width) &&
  384. (parcel->getMediaHeight() == media_height) &&
  385. (parcel->getMediaAutoScale() == media_auto_scale) &&
  386. (parcel->getMediaLoop() == media_loop));
  387. if (!same)
  388. {
  389. // temporarily store these new values in the parcel
  390. parcel->setMediaURL(media_url);
  391. parcel->setMediaType(media_type);
  392. parcel->setMediaID(media_id);
  393. parcel->setMediaWidth(media_width);
  394. parcel->setMediaHeight(media_height);
  395. parcel->setMediaAutoScale(media_auto_scale);
  396. parcel->setMediaLoop(media_loop);
  397. play(parcel);
  398. }
  399. }
  400. }
  401. // Static
  402. /////////////////////////////////////////////////////////////////////////////////////////
  403. void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
  404. {
  405. std::string region_url = gAgent.getRegion()->getCapability("ParcelNavigateMedia");
  406. if (!region_url.empty())
  407. {
  408. // send navigate event to sim for link sharing
  409. LLSD body;
  410. body["agent-id"] = gAgent.getID();
  411. body["local-id"] = LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
  412. body["url"] = url;
  413. LLHTTPClient::post(region_url, body, new LLHTTPClient::Responder);
  414. }
  415. else
  416. {
  417. llwarns << "can't get ParcelNavigateMedia capability" << llendl;
  418. }
  419. }
  420. /////////////////////////////////////////////////////////////////////////////////////////
  421. // inherited from LLViewerMediaObserver
  422. // virtual
  423. void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
  424. {
  425. switch(event)
  426. {
  427. case MEDIA_EVENT_DEBUG_MESSAGE:
  428. {
  429. // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_DEBUG_MESSAGE " << LL_ENDL;
  430. };
  431. break;
  432. case MEDIA_EVENT_CONTENT_UPDATED:
  433. {
  434. // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
  435. };
  436. break;
  437. case MEDIA_EVENT_TIME_DURATION_UPDATED:
  438. {
  439. // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
  440. };
  441. break;
  442. case MEDIA_EVENT_SIZE_CHANGED:
  443. {
  444. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
  445. };
  446. break;
  447. case MEDIA_EVENT_CURSOR_CHANGED:
  448. {
  449. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
  450. };
  451. break;
  452. case MEDIA_EVENT_NAVIGATE_BEGIN:
  453. {
  454. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << LL_ENDL;
  455. };
  456. break;
  457. case MEDIA_EVENT_NAVIGATE_COMPLETE:
  458. {
  459. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
  460. };
  461. break;
  462. case MEDIA_EVENT_PROGRESS_UPDATED:
  463. {
  464. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
  465. };
  466. break;
  467. case MEDIA_EVENT_STATUS_TEXT_CHANGED:
  468. {
  469. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
  470. };
  471. break;
  472. case MEDIA_EVENT_LOCATION_CHANGED:
  473. {
  474. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
  475. };
  476. break;
  477. case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
  478. {
  479. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
  480. };
  481. break;
  482. case MEDIA_EVENT_CLICK_LINK_HREF:
  483. {
  484. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
  485. };
  486. break;
  487. case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
  488. {
  489. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
  490. };
  491. break;
  492. case MEDIA_EVENT_PLUGIN_FAILED:
  493. {
  494. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
  495. };
  496. break;
  497. case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
  498. {
  499. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
  500. };
  501. break;
  502. case MEDIA_EVENT_NAME_CHANGED:
  503. {
  504. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
  505. };
  506. break;
  507. case MEDIA_EVENT_CLOSE_REQUEST:
  508. {
  509. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
  510. }
  511. break;
  512. case MEDIA_EVENT_PICK_FILE_REQUEST:
  513. {
  514. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
  515. }
  516. break;
  517. case MEDIA_EVENT_GEOMETRY_CHANGE:
  518. {
  519. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
  520. }
  521. break;
  522. case MEDIA_EVENT_AUTH_REQUEST:
  523. {
  524. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL;
  525. }
  526. break;
  527. case MEDIA_EVENT_LINK_HOVERED:
  528. {
  529. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
  530. };
  531. break;
  532. };
  533. }
  534. // TODO: observer
  535. /*
  536. void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in )
  537. {
  538. std::string url = event_in.getStringValue();
  539. if (mCurrentURL != url && ! mFromMessage)
  540. {
  541. LLViewerParcelMedia::sendMediaNavigateMessage(url);
  542. }
  543. mCurrentURL = url;
  544. mFromMessage = false;
  545. }
  546. */