diff options
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r-- | indra/newview/llviewermedia.cpp | 346 |
1 files changed, 286 insertions, 60 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 9ced0194a2..86336e353c 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -50,6 +50,9 @@ #include "llcallbacklist.h" #include "llparcel.h" #include "llaudioengine.h" // for gAudiop +#include "llvoavatar.h" +#include "llvoavatarself.h" +#include "llviewerregion.h" #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" @@ -57,11 +60,16 @@ #include "llkeyboard.h" #include "llmutelist.h" //#include "llfirstuse.h" +#include "llwindow.h" #include <boost/bind.hpp> // for SkinFolder listener #include <boost/signals2.hpp> /*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable"; +/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers"; +/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel"; +/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel"; + // Move this to its own file. @@ -253,6 +261,8 @@ static LLTimer sMediaCreateTimer; static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f; static F32 sGlobalVolume = 1.0f; static F64 sLowestLoadableImplInterest = 0.0f; +static bool sAnyMediaShowing = false; +static boost::signals2::connection sTeleportFinishConnection; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -365,8 +375,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s // The current media URL is not empty. // If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent, // do a navigate. - bool auto_play = (media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING)); - + bool auto_play = media_impl->isAutoPlayable(); if((was_loaded || auto_play) && !update_from_self) { needs_navigate = url_changed; @@ -390,7 +399,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s media_impl->mMediaAutoPlay = media_entry->getAutoPlay(); media_impl->mMediaEntryURL = media_entry->getCurrentURL(); - if(media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING)) + if(media_impl->isAutoPlayable()) { needs_navigate = true; } @@ -687,6 +696,7 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi // static void LLViewerMedia::updateMedia(void *dummy_arg) { + sAnyMediaShowing = false; impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); @@ -712,7 +722,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) std::vector<LLViewerMediaImpl*> proximity_order; bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); - bool needs_first_run = LLViewerMedia::needsMediaFirstRun(); + bool inworld_audio_enabled = gSavedSettings.getBOOL("AudioStreamingMusic"); U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); @@ -818,7 +828,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) impl_count_total++; } - + // Overrides if the window is minimized or we lost focus (taking care // not to accidentally "raise" the priority either) if (!gViewerWindow->getActive() /* viewer window minimized? */ @@ -838,15 +848,16 @@ void LLViewerMedia::updateMedia(void *dummy_arg) if(!pimpl->getUsedInUI()) { new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; - if(needs_first_run) - { - // Don't do this more than once in this loop. - needs_first_run = false; - LLViewerMedia::displayMediaFirstRun(); - } } } - + // update the audio stream here as well + if(!inworld_media_enabled || !inworld_audio_enabled) + { + if(LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio()) + { + gAudiop->stopInternetStream(); + } + } pimpl->setPriority(new_priority); if(pimpl->getUsedInUI()) @@ -860,6 +871,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg) } total_cpu += pimpl->getCPUUsage(); + + if (!pimpl->getUsedInUI() && pimpl->hasMedia()) + { + sAnyMediaShowing = true; + } + } // Re-calculate this every time. @@ -901,70 +918,132 @@ void LLViewerMedia::updateMedia(void *dummy_arg) ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::initClass() +bool LLViewerMedia::isAnyMediaShowing() { - gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + return sAnyMediaShowing; } ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::cleanupClass() +void LLViewerMedia::setAllMediaEnabled(bool val) { - gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); + // Set "tentative" autoplay first. We need to do this here or else + // re-enabling won't start up the media below. + gSavedSettings.setBOOL("MediaTentativeAutoPlay", val); + + // Then + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + if (!pimpl->getUsedInUI()) + { + pimpl->setDisabled(!val); + } + } + + // Also do Parcel Media and Parcel Audio + if (val) + { + if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia()) + { + LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + } + + if (gSavedSettings.getBOOL("AudioStreamingMusic") && + !LLViewerMedia::isParcelAudioPlaying() && + gAudiop && + LLViewerMedia::hasParcelAudio()) + { + gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL()); + } + } + else { + // This actually unloads the impl, as opposed to "stop"ping the media + LLViewerParcelMedia::stop(); + if (gAudiop) gAudiop->stopInternetStream(); + } } +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::isParcelMediaPlaying() +{ + return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia()); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::isParcelAudioPlaying() +{ + return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying()); +} + +bool LLViewerMedia::hasInWorldMedia() +{ + if (sInWorldMediaDisabled) return false; + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + // This should be quick, because there should be very few non-in-world-media impls + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + if (!pimpl->getUsedInUI() && !pimpl->isParcelMedia()) + { + // Found an in-world media impl + return true; + } + } + return false; +} ////////////////////////////////////////////////////////////////////////////////////////// // static -bool LLViewerMedia::needsMediaFirstRun() +bool LLViewerMedia::hasParcelMedia() { - return gWarningSettings.getBOOL("FirstStreamingMedia"); + return !LLViewerParcelMedia::getURL().empty(); } ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::displayMediaFirstRun() +bool LLViewerMedia::hasParcelAudio() { - gWarningSettings.setBOOL("FirstStreamingMedia", FALSE); + return !LLViewerMedia::getParcelAudioURL().empty(); +} - LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(firstRunCallback, _1, _2)); +////////////////////////////////////////////////////////////////////////////////////////// +// static +std::string LLViewerMedia::getParcelAudioURL() +{ + return LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL(); } ////////////////////////////////////////////////////////////////////////////////////////// // static -bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& response) +void LLViewerMedia::initClass() { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - // user has elected to automatically play media. - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); - gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); - gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); + gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> + setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); +} - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - - if (parcel) - { - // play media right now, if available - LLViewerParcelMedia::play(parcel); - - // play music right now, if available - std::string music_url = parcel->getMusicURL(); - if (gAudiop && !music_url.empty()) - gAudiop->startInternetStream(music_url); - } - } - else - { - gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE); - gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); - gSavedSettings.setBOOL("AudioStreamingMusic", FALSE); - } - return false; +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::cleanupClass() +{ + gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); + sTeleportFinishConnection.disconnect(); } +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::onTeleportFinished() +{ + // On teleport, clear this setting (i.e. set it to true) + gSavedSettings.setBOOL("MediaTentativeAutoPlay", true); +} ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl @@ -1249,6 +1328,9 @@ void LLViewerMediaImpl::loadURI() { if(mMediaSource) { + // trim whitespace from front and back of URL - fixes EXT-5363 + LLStringUtil::trim( mMediaURL ); + // *HACK: we don't know if the URI coming in is properly escaped // (the contract doesn't specify whether it is escaped or not. // but LLQtWebKit expects it to be, so we do our best to encode @@ -1839,9 +1921,12 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if(!result) { - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); // 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); + (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); } } @@ -1859,7 +1944,9 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) if (uni_char >= 32 // discard 'control' characters && uni_char != 127) // SDL thinks this is 'delete' - yuck. { - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE)); + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + + mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); } } @@ -2111,6 +2198,21 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y) #endif } + + +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::isMediaTimeBased() +{ + bool result = false; + + if(mMediaSource) + { + result = mMediaSource->pluginSupportsMediaTime(); + } + + return result; +} + ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::isMediaPlaying() { @@ -2157,7 +2259,7 @@ void LLViewerMediaImpl::resetPreviousMediaState() ////////////////////////////////////////////////////////////////////////////////////////// // -void LLViewerMediaImpl::setDisabled(bool disabled) +void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable) { if(mIsDisabled != disabled) { @@ -2172,7 +2274,7 @@ void LLViewerMediaImpl::setDisabled(bool disabled) else { // We just (re)enabled this media. Do a navigate if auto-play is in order. - if(mMediaAutoPlay && gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)) + if(isAutoPlayable() || forcePlayOnEnable) { navigateTo(mMediaEntryURL, "", true, true); } @@ -2199,6 +2301,12 @@ bool LLViewerMediaImpl::isForcedUnloaded() const } } + // If this media's class is not supposed to be shown, unload + if (!shouldShowBasedOnClass()) + { + return true; + } + return false; } @@ -2453,16 +2561,25 @@ void LLViewerMediaImpl::calculateInterest() for(; iter != mObjectList.end() ; ++iter) { LLVOVolume *obj = *iter; - if(LLMuteList::getInstance()->isMuted(obj->getID())) + llassert(obj); + if (!obj) continue; + if(LLMuteList::getInstance() && + 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 (LLSelectMgr::getInstance()) { - if(LLMuteList::getInstance()->isMuted(obj_perm->getOwner())) - mIsMuted = true; + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj); + if(obj_perm) + { + if(LLMuteList::getInstance() && + LLMuteList::getInstance()->isMuted(obj_perm->getOwner())) + mIsMuted = true; + } } } } @@ -2684,3 +2801,112 @@ void LLViewerMediaImpl::setTextureID(LLUUID id) } } +////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::isAutoPlayable() const +{ + return (mMediaAutoPlay && + gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) && + gSavedSettings.getBOOL("MediaTentativeAutoPlay")); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::shouldShowBasedOnClass() const +{ + // If this is parcel media or in the UI, return true always + if (getUsedInUI() || isParcelMedia()) return true; + + bool attached_to_another_avatar = isAttachedToAnotherAvatar(); + bool inside_parcel = isInAgentParcel(); + + // llinfos << " hasFocus = " << hasFocus() << + // " others = " << (attached_to_another_avatar && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING)) << + // " within = " << (inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING)) << + // " outside = " << (!inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING)) << llendl; + + // If it has focus, we should show it + if (hasFocus()) + return true; + + // If it is attached to an avatar and the pref is off, we shouldn't show it + if (attached_to_another_avatar) + return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); + + if (inside_parcel) + return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); + else + return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const +{ + bool result = false; + + std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin(); + std::list< LLVOVolume* >::const_iterator end = mObjectList.end(); + for ( ; iter != end; iter++) + { + if (isObjectAttachedToAnotherAvatar(*iter)) + { + result = true; + break; + } + } + return result; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +//static +bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj) +{ + bool result = false; + LLXform *xform = obj; + // Walk up parent chain + while (NULL != xform) + { + LLViewerObject *object = dynamic_cast<LLViewerObject*> (xform); + if (NULL != object) + { + LLVOAvatar *avatar = object->asAvatar(); + if (NULL != avatar && avatar != gAgent.getAvatarObject()) + { + result = true; + break; + } + } + xform = xform->getParent(); + } + return result; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::isInAgentParcel() const +{ + bool result = false; + + std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin(); + std::list< LLVOVolume* >::const_iterator end = mObjectList.end(); + for ( ; iter != end; iter++) + { + LLVOVolume *object = *iter; + if (LLViewerMediaImpl::isObjectInAgentParcel(object)) + { + result = true; + break; + } + } + return result; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +// static +bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj) +{ + return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal())); +} |