PageRenderTime 48ms CodeModel.GetById 11ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

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