llviewerparcelmedia.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

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