diff options
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r-- | indra/newview/llviewermedia.cpp | 319 |
1 files changed, 248 insertions, 71 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 464ba4a5b1..8bd74dcb04 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -49,6 +49,7 @@ #include "llnotifications.h" #include "lluuid.h" #include "llkeyboard.h" +#include "llmutelist.h" #include <boost/bind.hpp> // for SkinFolder listener #include <boost/signals2.hpp> @@ -155,10 +156,10 @@ public: { if(!mInitialized && ! mime_type.empty()) { - if (mMediaImpl->initializeMedia(mime_type)) + if(mMediaImpl->initializeMedia(mime_type)) { mInitialized = true; - mMediaImpl->play(); + mMediaImpl->loadURI(); } } } @@ -171,6 +172,7 @@ typedef std::vector<LLViewerMediaImpl*> impl_list; static impl_list sViewerMediaImplList; static LLTimer sMediaCreateTimer; static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f; +static F32 sGlobalVolume = 1.0f; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -194,6 +196,14 @@ static void remove_media_impl(LLViewerMediaImpl* media) } } +class LLViewerMediaMuteListObserver : public LLMuteListObserver +{ + /* virtual */ void onChange() { LLViewerMedia::muteListChanged();} +}; + +static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver; +static bool sViewerMediaMuteListObserverInitialized = false; + ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMedia @@ -257,10 +267,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s { needs_navigate = (media_entry->getCurrentURL() != previous_url); } - else if(!media_entry->getHomeURL().empty()) - { - needs_navigate = (media_entry->getHomeURL() != previous_url); - } } } else @@ -283,8 +289,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s if(media_impl && needs_navigate) { std::string url = media_entry->getCurrentURL(); - if(url.empty()) - url = media_entry->getHomeURL(); media_impl->navigateTo(url, "", true, true); } @@ -388,20 +392,56 @@ bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id) // static void LLViewerMedia::setVolume(F32 volume) { + if(volume != sGlobalVolume) + { + sGlobalVolume = volume; + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + pimpl->updateVolume(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +F32 LLViewerMedia::getVolume() +{ + return sGlobalVolume; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::muteListChanged() +{ + // When the mute list changes, we need to check mute status on all impls. impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); for(; iter != end; iter++) { LLViewerMediaImpl* pimpl = *iter; - pimpl->setVolume(volume); + pimpl->mNeedsMuteCheck = true; } } // This is the predicate function used to sort sViewerMediaImplList by priority. static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2) { - if(i1->hasFocus()) + if(i1->mIsMuted || i1->mMediaSourceFailed) + { + // Muted or failed items always go to the end of the list, period. + return false; + } + else if(i2->mIsMuted || i2->mMediaSourceFailed) + { + // Muted or failed items always go to the end of the list, period. + return true; + } + else if(i1->hasFocus()) { // The item with user focus always comes to the front of the list, period. return true; @@ -475,8 +515,9 @@ void LLViewerMedia::updateMedia() LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL; - if(impl_count_total > (int)max_instances) + if(pimpl->mIsMuted || pimpl->mMediaSourceFailed || (impl_count_total > (int)max_instances)) { + // Never load muted or failed impls. // Hard limit on the number of instances that will be loaded at one time new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; } @@ -536,6 +577,11 @@ void LLViewerMedia::updateMedia() } } + if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED) + { + impl_count_total++; + } + pimpl->setPriority(new_priority); #if 0 @@ -549,7 +595,6 @@ void LLViewerMedia::updateMedia() #endif total_cpu += pimpl->getCPUUsage(); - impl_count_total++; } LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl; @@ -588,12 +633,23 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mUsedInUI(false), mHasFocus(false), mPriority(LLPluginClassMedia::PRIORITY_UNLOADED), - mDoNavigateOnLoad(false), - mDoNavigateOnLoadRediscoverType(false), - mDoNavigateOnLoadServerRequest(false), - mMediaSourceFailedInit(false), + mNavigateRediscoverType(false), + mNavigateServerRequest(false), + mMediaSourceFailed(false), + mRequestedVolume(1.0f), + mIsMuted(false), + mNeedsMuteCheck(false), + mPreviousMediaState(MEDIA_NONE), + mPreviousMediaTime(0.0f), mIsUpdated(false) { + + // Set up the mute list observer if it hasn't been set up already. + if(!sViewerMediaMuteListObserverInitialized) + { + LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver); + sViewerMediaMuteListObserverInitialized = true; + } add_media_impl(this); @@ -655,7 +711,6 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) mMimeType = mime_type; } - // play(); return (mMediaSource != NULL); } @@ -668,16 +723,13 @@ void LLViewerMediaImpl::createMediaSource() return; } - if(mDoNavigateOnLoad) + if(! mMediaURL.empty()) { - if(! mMediaURL.empty()) - { - navigateTo(mMediaURL, mMimeType, mDoNavigateOnLoadRediscoverType, mDoNavigateOnLoadServerRequest); - } - else if(! mMimeType.empty()) - { - initializeMedia(mMimeType); - } + navigateInternal(); + } + else if(! mMimeType.empty()) + { + initializeMedia(mMimeType); } } @@ -783,7 +835,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) } // If we got here, we want to ignore previous init failures. - mMediaSourceFailedInit = false; + mMediaSourceFailed = false; LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight); @@ -796,15 +848,58 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->focus(mHasFocus); mMediaSource = media_source; + + updateVolume(); + return true; } // Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes. - mMediaSourceFailedInit = true; + mMediaSourceFailed = true; return false; } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::loadURI() +{ + if(mMediaSource) + { + mMediaSource->loadURI( mMediaURL ); + + if(mPreviousMediaState == MEDIA_PLAYING) + { + // This media was playing before this instance was unloaded. + + if(mPreviousMediaTime != 0.0f) + { + // Seek back to where we left off, if possible. + seek(mPreviousMediaTime); + } + + start(); + } + else if(mPreviousMediaState == MEDIA_PAUSED) + { + // This media was paused before this instance was unloaded. + + if(mPreviousMediaTime != 0.0f) + { + // Seek back to where we left off, if possible. + seek(mPreviousMediaTime); + } + + pause(); + } + else + { + // No relevant previous media play state -- if we're loading the URL, we want to start playing. + start(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setSize(int width, int height) { mMediaWidth = width; @@ -818,24 +913,21 @@ void LLViewerMediaImpl::setSize(int width, int height) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::play() { - // first stop any previously playing media - // stop(); - - // mMediaSource->addObserver( this ); + // If the media source isn't there, try to initialize it and load an URL. if(mMediaSource == NULL) { - if(!initializePlugin(mMimeType)) + if(!initializeMedia(mMimeType)) { // This may be the case where the plugin's priority is PRIORITY_UNLOADED return; } + + // Only do this if the media source was just loaded. + loadURI(); } - mMediaSource->loadURI( mMediaURL ); - if(/*mMediaSource->pluginSupportsMediaTime()*/ true) - { - start(); - } + // always start the media + start(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -886,13 +978,26 @@ void LLViewerMediaImpl::seek(F32 time) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setVolume(F32 volume) { + mRequestedVolume = volume; + updateVolume(); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::updateVolume() +{ if(mMediaSource) { - mMediaSource->setVolume(volume); + mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume()); } } ////////////////////////////////////////////////////////////////////////////////////////// +F32 LLViewerMediaImpl::getVolume() +{ + return mRequestedVolume; +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::focus(bool focus) { mHasFocus = focus; @@ -1088,39 +1193,54 @@ void LLViewerMediaImpl::navigateHome() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) { - // Helpful to have media urls in log file. Shouldn't be spammy. - llinfos << "url=" << url << " mime_type=" << mime_type << llendl; - - if(server_request) - { - setNavState(MEDIANAVSTATE_SERVER_SENT); - } - else + if(mMediaURL != url) { - setNavState(MEDIANAVSTATE_NONE); + // Don't carry media play state across distinct URLs. + resetPreviousMediaState(); } // Always set the current URL and MIME type. mMediaURL = url; mMimeType = mime_type; - // If the current URL is not null, make the instance do a navigate on load. - mDoNavigateOnLoad = !mMediaURL.empty(); - // if mime type discovery was requested, we'll need to do it when the media loads - mDoNavigateOnLoadRediscoverType = rediscover_type; + mNavigateRediscoverType = rediscover_type; // and if this was a server request, the navigate on load will also need to be one. - mDoNavigateOnLoadServerRequest = server_request; + mNavigateServerRequest = server_request; + + // An explicit navigate resets the "failed" flag. + mMediaSourceFailed = false; if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) { + // Helpful to have media urls in log file. Shouldn't be spammy. + llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl; + // This impl should not be loaded at this time. LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL; return; } - + + navigateInternal(); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateInternal() +{ + // Helpful to have media urls in log file. Shouldn't be spammy. + llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl; + + if(mNavigateServerRequest) + { + setNavState(MEDIANAVSTATE_SERVER_SENT); + } + else + { + setNavState(MEDIANAVSTATE_NONE); + } + // If the caller has specified a non-empty MIME type, look that up in our MIME types list. // If we have a plugin for that MIME type, use that instead of attempting auto-discovery. // This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type @@ -1132,11 +1252,11 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi if(!plugin_basename.empty()) { // We have a plugin for this mime type - rediscover_type = false; + mNavigateRediscoverType = false; } } - if(rediscover_type) + if(mNavigateRediscoverType) { LLURI uri(mMediaURL); @@ -1152,7 +1272,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // We use "data" internally for a text/html url for loading the login screen if(initializeMedia("text/html")) { - mMediaSource->loadURI( mMediaURL ); + loadURI(); } } else @@ -1160,24 +1280,18 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // This catches 'rtsp://' urls if(initializeMedia(scheme)) { - mMediaSource->loadURI( mMediaURL ); + loadURI(); } } } - else if (mMediaSource) + else if(initializeMedia(mMimeType)) { - mMediaSource->loadURI( mMediaURL ); - } - else if(initializeMedia(mime_type) && mMediaSource) - { - mMediaSource->loadURI( mMediaURL ); + loadURI(); } else { - LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL; - return; + LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL; } - } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1228,6 +1342,8 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if(!result) { result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. + (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask); } } @@ -1277,7 +1393,7 @@ bool LLViewerMediaImpl::canNavigateBack() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::update() { - if(mMediaSource == NULL && !mMediaSourceFailedInit) + if(mMediaSource == NULL) { if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED) { @@ -1304,6 +1420,7 @@ void LLViewerMediaImpl::update() if(mMediaSource->isPluginExited()) { + resetPreviousMediaState(); destroyMediaSource(); return; } @@ -1500,6 +1617,14 @@ bool LLViewerMediaImpl::hasMedia() } ////////////////////////////////////////////////////////////////////////////////////////// +// +void LLViewerMediaImpl::resetPreviousMediaState() +{ + mPreviousMediaState = MEDIA_NONE; + mPreviousMediaTime = 0.0f; +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event) { switch(event) @@ -1507,7 +1632,11 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: { // The plugin failed to load properly. Make sure the timer doesn't retry. - mMediaSourceFailedInit = true; + // TODO: maybe mark this plugin as not loadable somehow? + mMediaSourceFailed = true; + + // Reset the last known state of the media to defaults. + resetPreviousMediaState(); // TODO: may want a different message for this case? LLSD args; @@ -1518,6 +1647,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case MEDIA_EVENT_PLUGIN_FAILED: { + // The plugin crashed. + mMediaSourceFailed = true; + + // Reset the last known state of the media to defaults. + resetPreviousMediaState(); + LLSD args; args["PLUGIN"] = LLMIMETypes::implType(mMimeType); // SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert! @@ -1692,6 +1827,32 @@ void LLViewerMediaImpl::calculateInterest() // This will be a relatively common case now, since it will always be true for unloaded media. mInterest = 0.0f; } + + if(mNeedsMuteCheck) + { + // Check all objects this instance is associated with, and those objects' owners, against the mute list + mIsMuted = false; + + std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; + for(; iter != mObjectList.end() ; ++iter) + { + LLVOVolume *obj = *iter; + if(LLMuteList::getInstance()->isMuted(obj->getID())) + mIsMuted = true; + else + { + // We won't have full permissions data for all objects. Attempt to mute objects when we can tell their owners are muted. + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj); + if(obj_perm) + { + if(LLMuteList::getInstance()->isMuted(obj_perm->getOwner())) + mIsMuted = true; + } + } + } + + mNeedsMuteCheck = false; + } } F64 LLViewerMediaImpl::getApproximateTextureInterest() @@ -1717,11 +1878,11 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui) { if(getVisible()) { - mPriority = LLPluginClassMedia::PRIORITY_NORMAL; + setPriority(LLPluginClassMedia::PRIORITY_NORMAL); } else { - mPriority = LLPluginClassMedia::PRIORITY_HIDDEN; + setPriority(LLPluginClassMedia::PRIORITY_HIDDEN); } createMediaSource(); @@ -1742,6 +1903,15 @@ F64 LLViewerMediaImpl::getCPUUsage() const void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority) { + if(mPriority != priority) + { + LL_INFOS("PluginPriority") + << "changing priority of media id " << mTextureId + << " from " << LLPluginClassMedia::priorityToString(mPriority) + << " to " << LLPluginClassMedia::priorityToString(priority) + << LL_ENDL; + } + mPriority = priority; if(priority == LLPluginClassMedia::PRIORITY_UNLOADED) @@ -1749,6 +1919,11 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority) if(mMediaSource) { // Need to unload the media source + + // First, save off previous media state + mPreviousMediaState = mMediaSource->getStatus(); + mPreviousMediaTime = mMediaSource->getCurrentTime(); + destroyMediaSource(); } } @@ -1799,11 +1974,13 @@ void LLViewerMediaImpl::addObject(LLVOVolume* obj) } mObjectList.push_back(obj) ; + mNeedsMuteCheck = true; } void LLViewerMediaImpl::removeObject(LLVOVolume* obj) { mObjectList.remove(obj) ; + mNeedsMuteCheck = true; } const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const |