aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerparcelmedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llviewerparcelmedia.cpp')
-rw-r--r--linden/indra/newview/llviewerparcelmedia.cpp353
1 files changed, 270 insertions, 83 deletions
diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp
index b98f418..d4ebbd9 100644
--- a/linden/indra/newview/llviewerparcelmedia.cpp
+++ b/linden/indra/newview/llviewerparcelmedia.cpp
@@ -41,47 +41,22 @@
41#include "llviewerparcelmgr.h" 41#include "llviewerparcelmgr.h"
42#include "lluuid.h" 42#include "lluuid.h"
43#include "message.h" 43#include "message.h"
44#include "llviewermediafocus.h"
44#include "llviewerparcelmediaautoplay.h" 45#include "llviewerparcelmediaautoplay.h"
45#include "llviewerwindow.h" 46#include "llviewerwindow.h"
46#include "llfirstuse.h" 47#include "llfirstuse.h"
48#include "llpluginclassmedia.h"
47 49
48// Static Variables 50// Static Variables
49 51
50S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; 52S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
51LLUUID LLViewerParcelMedia::sMediaRegionID; 53LLUUID LLViewerParcelMedia::sMediaRegionID;
54viewer_media_t LLViewerParcelMedia::sMediaImpl;
55
52 56
53// Local functions 57// Local functions
54bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); 58bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
55 59
56// Move this to its own file.
57// helper class that tries to download a URL from a web site and calls a method
58// on the Panel Land Media and to discover the MIME type
59class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
60{
61public:
62 LLMimeDiscoveryResponder( )
63 {}
64
65
66
67 virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
68 {
69 std::string media_type = content["content-type"].asString();
70 std::string::size_type idx1 = media_type.find_first_of(";");
71 std::string mime_type = media_type.substr(0, idx1);
72 completeAny(status, mime_type);
73 }
74
75 virtual void error( U32 status, const std::string& reason )
76 {
77 completeAny(status, "none/none");
78 }
79
80 void completeAny(U32 status, const std::string& mime_type)
81 {
82 LLViewerMedia::setMimeType(mime_type);
83 }
84};
85 60
86// static 61// static
87void LLViewerParcelMedia::initClass() 62void LLViewerParcelMedia::initClass()
@@ -92,6 +67,13 @@ void LLViewerParcelMedia::initClass()
92 LLViewerParcelMediaAutoPlay::initClass(); 67 LLViewerParcelMediaAutoPlay::initClass();
93} 68}
94 69
70//static
71void LLViewerParcelMedia::cleanupClass()
72{
73 // This needs to be destroyed before global destructor time.
74 sMediaImpl = NULL;
75}
76
95////////////////////////////////////////////////////////////////////////////////////////// 77//////////////////////////////////////////////////////////////////////////////////////////
96// static 78// static
97void LLViewerParcelMedia::update(LLParcel* parcel) 79void LLViewerParcelMedia::update(LLParcel* parcel)
@@ -105,6 +87,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
105 { 87 {
106 sMediaRegionID = LLUUID() ; 88 sMediaRegionID = LLUUID() ;
107 stop() ; 89 stop() ;
90 LL_DEBUGS("Media") << "no agent region, bailing out." << LL_ENDL;
108 return ; 91 return ;
109 } 92 }
110 93
@@ -115,64 +98,54 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
115 LLUUID regionid = gAgent.getRegion()->getRegionID(); 98 LLUUID regionid = gAgent.getRegion()->getRegionID();
116 if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID) 99 if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID)
117 { 100 {
101 LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL;
118 sMediaParcelLocalID = parcelid; 102 sMediaParcelLocalID = parcelid;
119 sMediaRegionID = regionid; 103 sMediaRegionID = regionid;
120 new_parcel = true; 104 new_parcel = true;
121 } 105 }
122 106
123 std::string mediaUrl = std::string ( parcel->getMediaURL () ); 107 std::string mediaUrl = std::string ( parcel->getMediaURL () );
108 std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL());
109
110 // First use warning
111 if( ! mediaUrl.empty() && gSavedSettings.getWarning("FirstStreamingVideo") )
112 {
113 LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(),
114 boost::bind(callback_play_media, _1, _2, parcel));
115 return;
116
117 }
118
119 // if we have a current (link sharing) url, use it instead
120 if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html")
121 {
122 mediaUrl = mediaCurrentUrl;
123 }
124
124 LLStringUtil::trim(mediaUrl); 125 LLStringUtil::trim(mediaUrl);
126
127 // If no parcel media is playing, nothing left to do
128 if(sMediaImpl.isNull())
125 129
126 // has something changed?
127 if ( ( LLViewerMedia::getMediaURL() != mediaUrl )
128 || ( LLViewerMedia::getMediaTextureID() != parcel->getMediaID () ) )
129 { 130 {
130 bool video_was_playing = FALSE; 131 return;
131 bool same_media_id = LLViewerMedia::getMediaTextureID() == parcel->getMediaID (); 132 }
132 133
133 if (LLViewerMedia::isMediaPlaying()) 134 // Media is playing...has something changed?
135 else if (( sMediaImpl->getMediaURL() != mediaUrl )
136 || ( sMediaImpl->getMediaTextureID() != parcel->getMediaID() )
137 || ( sMediaImpl->getMimeType() != parcel->getMediaType() ))
138 {
139 // Only play if the media types are the same.
140 if(sMediaImpl->getMimeType() == parcel->getMediaType())
134 { 141 {
135 video_was_playing = TRUE; 142 play(parcel);
136 } 143 }
137 144
138 if ( !mediaUrl.empty() && same_media_id && ! new_parcel)
139 {
140 // Someone has "changed the channel", changing the URL of a video
141 // you were already watching. Automatically play provided the texture ID is the same
142 if (video_was_playing)
143 {
144 // Poke the mime type in before calling play.
145 // This is necessary because in this instance we are not waiting
146 // for the results of a header curl. In order to change the channel
147 // a mime type MUST be provided.
148 LLViewerMedia::setMimeType(parcel->getMediaType());
149 play(parcel);
150 }
151 }
152 else 145 else
153 { 146 {
154 stop(); 147 stop();
155 } 148 }
156
157 // Discover the MIME type
158 // Disabled for the time being. Get the mime type from the parcel.
159 if(gSavedSettings.getBOOL("AutoMimeDiscovery"))
160 {
161 LLHTTPClient::getHeaderOnly( mediaUrl, new LLMimeDiscoveryResponder());
162 }
163 else
164 {
165 LLViewerMedia::setMimeType(parcel->getMediaType());
166 }
167
168 // First use warning
169 if( gSavedSettings.getWarning("FirstStreamingVideo") )
170 {
171 LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(),
172 boost::bind(callback_play_media, _1, _2, parcel));
173
174 }
175
176 } 149 }
177 } 150 }
178 else 151 else
@@ -183,7 +156,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
183 /* 156 /*
184 else 157 else
185 { 158 {
186 // no audio player, do a first use dialog if their is media here 159 // no audio player, do a first use dialog if there is media here
187 if (parcel) 160 if (parcel)
188 { 161 {
189 std::string mediaUrl = std::string ( parcel->getMediaURL () ); 162 std::string mediaUrl = std::string ( parcel->getMediaURL () );
@@ -212,15 +185,57 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
212 return; 185 return;
213 186
214 std::string media_url = parcel->getMediaURL(); 187 std::string media_url = parcel->getMediaURL();
188 std::string media_current_url = parcel->getMediaCurrentURL();
215 std::string mime_type = parcel->getMediaType(); 189 std::string mime_type = parcel->getMediaType();
216 LLUUID placeholder_texture_id = parcel->getMediaID(); 190 LLUUID placeholder_texture_id = parcel->getMediaID();
217 U8 media_auto_scale = parcel->getMediaAutoScale(); 191 U8 media_auto_scale = parcel->getMediaAutoScale();
218 U8 media_loop = parcel->getMediaLoop(); 192 U8 media_loop = parcel->getMediaLoop();
219 S32 media_width = parcel->getMediaWidth(); 193 S32 media_width = parcel->getMediaWidth();
220 S32 media_height = parcel->getMediaHeight(); 194 S32 media_height = parcel->getMediaHeight();
221 LLViewerMedia::play(media_url, mime_type, placeholder_texture_id, 195
222 media_width, media_height, media_auto_scale, 196 // Debug print
223 media_loop); 197 // LL_DEBUGS("Media") << "Play media type : " << mime_type << ", url : " << media_url << LL_ENDL;
198
199 if(sMediaImpl)
200 {
201 // If the url and mime type are the same, call play again
202 if(sMediaImpl->getMediaURL() == media_url
203 && sMediaImpl->getMimeType() == mime_type
204 && sMediaImpl->getMediaTextureID() == placeholder_texture_id)
205 {
206 LL_DEBUGS("Media") << "playing with existing url " << media_url << LL_ENDL;
207
208 sMediaImpl->play();
209 }
210 // Else if the texture id's are the same, navigate and rediscover type
211 // MBW -- This causes other state from the previous parcel (texture size, autoscale, and looping) to get re-used incorrectly.
212 // It's also not really necessary -- just creating a new instance is fine.
213// else if(sMediaImpl->getMediaTextureID() == placeholder_texture_id)
214// {
215// sMediaImpl->navigateTo(media_url, mime_type, true);
216// }
217 else
218 {
219 // Since the texture id is different, we need to generate a new impl
220 LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
221
222 // Delete the old one first so they don't fight over the texture.
223 sMediaImpl->stop();
224
225 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
226 media_width, media_height, media_auto_scale,
227 media_loop, mime_type);
228 }
229 }
230 else
231 {
232 // There is no media impl, make a new one
233 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
234 media_width, media_height, media_auto_scale,
235 media_loop, mime_type);
236 }
237
238
224 LLFirstUse::useMedia(); 239 LLFirstUse::useMedia();
225 240
226 LLViewerParcelMediaAutoPlay::playStarted(); 241 LLViewerParcelMediaAutoPlay::playStarted();
@@ -229,20 +244,38 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
229// static 244// static
230void LLViewerParcelMedia::stop() 245void LLViewerParcelMedia::stop()
231{ 246{
247 if(sMediaImpl.isNull())
248 {
249 return;
250 }
251
252 // We need to remove the media HUD if it is up.
253 LLViewerMediaFocus::getInstance()->clearFocus();
232 254
233 LLViewerMedia::stop(); 255 // This will kill the media instance.
256 sMediaImpl->stop();
257 sMediaImpl = NULL;
234} 258}
235 259
236// static 260// static
237void LLViewerParcelMedia::pause() 261void LLViewerParcelMedia::pause()
238{ 262{
239 LLViewerMedia::pause(); 263 if(sMediaImpl.isNull())
264 {
265 return;
266 }
267 sMediaImpl->pause();
240} 268}
241 269
242// static 270// static
243void LLViewerParcelMedia::start() 271void LLViewerParcelMedia::start()
244{ 272{
245 LLViewerMedia::start(); 273 if(sMediaImpl.isNull())
274 {
275 return;
276 }
277 sMediaImpl->start();
278
246 LLFirstUse::useMedia(); 279 LLFirstUse::useMedia();
247 280
248 LLViewerParcelMediaAutoPlay::playStarted(); 281 LLViewerParcelMediaAutoPlay::playStarted();
@@ -251,16 +284,41 @@ void LLViewerParcelMedia::start()
251// static 284// static
252void LLViewerParcelMedia::seek(F32 time) 285void LLViewerParcelMedia::seek(F32 time)
253{ 286{
254 LLViewerMedia::seek(time); 287 if(sMediaImpl.isNull())
288 {
289 return;
290 }
291 sMediaImpl->seek(time);
255} 292}
256 293
257
258// static 294// static
259LLMediaBase::EStatus LLViewerParcelMedia::getStatus() 295void LLViewerParcelMedia::focus(bool focus)
260{ 296{
261 return LLViewerMedia::getStatus(); 297 sMediaImpl->focus(focus);
262} 298}
263 299
300// static
301LLViewerMediaImpl::EMediaStatus LLViewerParcelMedia::getStatus()
302{
303 LLViewerMediaImpl::EMediaStatus result = LLViewerMediaImpl::MEDIA_NONE;
304
305 if(sMediaImpl.notNull() && sMediaImpl->hasMedia())
306 {
307 result = sMediaImpl->getMediaPlugin()->getStatus();
308 }
309
310 return result;
311}
312
313// static
314std::string LLViewerParcelMedia::getMimeType()
315{
316 return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : "none/none";
317}
318viewer_media_t LLViewerParcelMedia::getParcelMedia()
319{
320 return sMediaImpl;
321}
264////////////////////////////////////////////////////////////////////////////////////////// 322//////////////////////////////////////////////////////////////////////////////////////////
265// static 323// static
266void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ) 324void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** )
@@ -298,7 +356,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
298 if(( command == PARCEL_MEDIA_COMMAND_PLAY ) || 356 if(( command == PARCEL_MEDIA_COMMAND_PLAY ) ||
299 ( command == PARCEL_MEDIA_COMMAND_LOOP )) 357 ( command == PARCEL_MEDIA_COMMAND_LOOP ))
300 { 358 {
301 if (LLViewerMedia::isMediaPaused()) 359 if (getStatus() == LLViewerMediaImpl::MEDIA_PAUSED)
302 { 360 {
303 start(); 361 start();
304 } 362 }
@@ -318,7 +376,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
318 376
319 if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME)) 377 if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME))
320 { 378 {
321 if(! LLViewerMedia::hasMedia()) 379 if(sMediaImpl.isNull())
322 { 380 {
323 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); 381 LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
324 play(parcel); 382 play(parcel);
@@ -382,6 +440,119 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
382 } 440 }
383 } 441 }
384} 442}
443// Static
444/////////////////////////////////////////////////////////////////////////////////////////
445void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
446{
447 std::string region_url = gAgent.getRegion()->getCapability("ParcelNavigateMedia");
448 if (!region_url.empty())
449 {
450 // send navigate event to sim for link sharing
451 LLSD body;
452 body["agent-id"] = gAgent.getID();
453 body["local-id"] = LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
454 body["url"] = url;
455 LLHTTPClient::post(region_url, body, new LLHTTPClient::Responder);
456 }
457 else
458 {
459 llwarns << "can't get ParcelNavigateMedia capability" << llendl;
460 }
461
462}
463
464/////////////////////////////////////////////////////////////////////////////////////////
465// inherited from LLViewerMediaObserver
466// virtual
467void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
468{
469 switch(event)
470 {
471 case MEDIA_EVENT_CONTENT_UPDATED:
472 {
473 // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
474 };
475 break;
476
477 case MEDIA_EVENT_TIME_DURATION_UPDATED:
478 {
479 // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
480 };
481 break;
482
483 case MEDIA_EVENT_SIZE_CHANGED:
484 {
485 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
486 };
487 break;
488
489 case MEDIA_EVENT_CURSOR_CHANGED:
490 {
491 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
492 };
493 break;
494
495 case MEDIA_EVENT_NAVIGATE_BEGIN:
496 {
497 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << LL_ENDL;
498 };
499 break;
500
501 case MEDIA_EVENT_NAVIGATE_COMPLETE:
502 {
503 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
504 };
505 break;
506
507 case MEDIA_EVENT_PROGRESS_UPDATED:
508 {
509 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
510 };
511 break;
512
513 case MEDIA_EVENT_STATUS_TEXT_CHANGED:
514 {
515 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
516 };
517 break;
518
519 case MEDIA_EVENT_LOCATION_CHANGED:
520 {
521 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
522 };
523 break;
524
525 case MEDIA_EVENT_CLICK_LINK_HREF:
526 {
527 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
528 };
529 break;
530
531 case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
532 {
533 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
534 };
535 break;
536
537 case MEDIA_EVENT_PLUGIN_FAILED:
538 {
539 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
540 };
541 break;
542
543 case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
544 {
545 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
546 };
547 break;
548
549 case MEDIA_EVENT_NAME_CHANGED:
550 {
551 LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
552 };
553 break;
554 };
555}
385 556
386bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) 557bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel)
387{ 558{
@@ -399,3 +570,19 @@ bool callback_play_media(const LLSD& notification, const LLSD& response, LLParce
399 return false; 570 return false;
400} 571}
401 572
573// TODO: observer
574/*
575void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in )
576{
577 std::string url = event_in.getStringValue();
578
579 if (mCurrentURL != url && ! mFromMessage)
580 {
581 LLViewerParcelMedia::sendMediaNavigateMessage(url);
582 }
583
584 mCurrentURL = url;
585 mFromMessage = false;
586
587}
588*/