summaryrefslogtreecommitdiff
path: root/indra/newview/llviewermedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r--indra/newview/llviewermedia.cpp635
1 files changed, 532 insertions, 103 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index b8e945a7b8..e89f17cf72 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -48,6 +48,8 @@
#include "llevent.h" // LLSimpleListener
#include "llnotifications.h"
#include "lluuid.h"
+#include "llkeyboard.h"
+#include "llmutelist.h"
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
@@ -154,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();
}
}
}
@@ -166,10 +168,10 @@ public:
viewer_media_t mMediaImpl;
bool mInitialized;
};
-typedef std::vector<LLViewerMediaImpl*> impl_list;
-static impl_list sViewerMediaImplList;
+static LLViewerMedia::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)
@@ -180,8 +182,8 @@ static void add_media_impl(LLViewerMediaImpl* media)
//////////////////////////////////////////////////////////////////////////////////////////
static void remove_media_impl(LLViewerMediaImpl* media)
{
- impl_list::iterator iter = sViewerMediaImplList.begin();
- impl_list::iterator end = sViewerMediaImplList.end();
+ LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
+ LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
for(; iter != end; iter++)
{
@@ -193,6 +195,15 @@ static void remove_media_impl(LLViewerMediaImpl* media)
}
}
+class LLViewerMediaMuteListObserver : public LLMuteListObserver
+{
+ /* virtual */ void onChange() { LLViewerMedia::muteListChanged();}
+};
+
+static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
+static bool sViewerMediaMuteListObserverInitialized = false;
+static bool sInWorldMediaDisabled = false;
+
//////////////////////////////////////////////////////////////////////////////////////////
// LLViewerMedia
@@ -250,16 +261,12 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
}
- if((was_loaded || media_entry->getAutoPlay()) && !update_from_self)
+ if((was_loaded || (media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))) && !update_from_self)
{
if(!media_entry->getCurrentURL().empty())
{
needs_navigate = (media_entry->getCurrentURL() != previous_url);
}
- else if(!media_entry->getHomeURL().empty())
- {
- needs_navigate = (media_entry->getHomeURL() != previous_url);
- }
}
}
else
@@ -273,7 +280,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->setHomeURL(media_entry->getHomeURL());
- if(media_entry->getAutoPlay())
+ if(media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))
{
needs_navigate = true;
}
@@ -282,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);
}
@@ -387,20 +392,75 @@ 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;
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
+{
+ sInWorldMediaDisabled = disabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::getInWorldMediaDisabled()
+{
+ return sInWorldMediaDisabled;
+}
+
+LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
+{
+ return sViewerMediaImplList;
+}
+
// This is the predicate function used to sort sViewerMediaImplList by priority.
-static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
{
- if(i1->hasFocus())
+ if(i1->isForcedUnloaded())
+ {
+ // Muted or failed items always go to the end of the list, period.
+ return false;
+ }
+ else if(i2->isForcedUnloaded())
+ {
+ // 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;
@@ -442,7 +502,7 @@ void LLViewerMedia::updateMedia()
}
// Sort the static instance list using our interest criteria
- std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest);
+ std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), priorityComparitor);
// Go through the list again and adjust according to priority.
iter = sViewerMediaImplList.begin();
@@ -452,6 +512,7 @@ void LLViewerMedia::updateMedia()
int impl_count_total = 0;
int impl_count_interest_low = 0;
int impl_count_interest_normal = 0;
+ int i = 0;
#if 0
LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl;
@@ -474,8 +535,9 @@ void LLViewerMedia::updateMedia()
LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
- if(impl_count_total > (int)max_instances)
+ if(pimpl->isForcedUnloaded() || (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;
}
@@ -535,7 +597,23 @@ void LLViewerMedia::updateMedia()
}
}
+ if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ impl_count_total++;
+ }
+
pimpl->setPriority(new_priority);
+
+ if(pimpl->getUsedInUI())
+ {
+ // Any impls used in the UI should not be in the proximity list.
+ pimpl->mProximity = -1;
+ }
+ else
+ {
+ // Other impls just get the same ordering as the priority list (for now).
+ pimpl->mProximity = i;
+ }
#if 0
LL_DEBUGS("PluginPriority") << " " << pimpl
@@ -548,7 +626,8 @@ void LLViewerMedia::updateMedia()
#endif
total_cpu += pimpl->getCPUUsage();
- impl_count_total++;
+
+ i++;
}
LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
@@ -587,10 +666,25 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mUsedInUI(false),
mHasFocus(false),
mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
- mDoNavigateOnLoad(false),
- mDoNavigateOnLoadServerRequest(false),
+ mNavigateRediscoverType(false),
+ mNavigateServerRequest(false),
+ mMediaSourceFailed(false),
+ mRequestedVolume(1.0f),
+ mIsMuted(false),
+ mNeedsMuteCheck(false),
+ mPreviousMediaState(MEDIA_NONE),
+ mPreviousMediaTime(0.0f),
+ mIsDisabled(false),
+ mProximity(-1),
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);
@@ -638,16 +732,20 @@ void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObser
//////////////////////////////////////////////////////////////////////////////////////////
bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
{
- if((mMediaSource == NULL) || (mMimeType != mime_type))
+ bool mimeTypeChanged = (mMimeType != mime_type);
+ bool pluginChanged = (LLMIMETypes::implType(mMimeType) != LLMIMETypes::implType(mime_type));
+
+ if(!mMediaSource || pluginChanged)
{
- if(! initializePlugin(mime_type))
- {
- // This may be the case where the plugin's priority is PRIORITY_UNLOADED
- return false;
- }
+ // We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
+ (void)initializePlugin(mime_type);
+ }
+ else if(mimeTypeChanged)
+ {
+ // The same plugin should be able to handle the new media -- just update the stored mime type.
+ mMimeType = mime_type;
}
- // play();
return (mMediaSource != NULL);
}
@@ -660,16 +758,13 @@ void LLViewerMediaImpl::createMediaSource()
return;
}
- if(mDoNavigateOnLoad)
+ if(! mMediaURL.empty())
{
- if(! mMediaURL.empty())
- {
- navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest);
- }
- else if(! mMimeType.empty())
- {
- initializeMedia(mMimeType);
- }
+ navigateInternal();
+ }
+ else if(! mMimeType.empty())
+ {
+ initializeMedia(mMimeType);
}
}
@@ -703,7 +798,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height)
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
-
+
if(plugin_basename.empty())
{
LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
@@ -774,6 +869,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
return false;
}
+ // If we got here, we want to ignore previous init failures.
+ mMediaSourceFailed = false;
+
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
if (media_source)
@@ -782,14 +880,61 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->setLoop(mMediaLoop);
media_source->setAutoScale(mMediaAutoScale);
media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+ 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.
+ 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;
@@ -803,24 +948,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();
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -828,7 +970,15 @@ void LLViewerMediaImpl::stop()
{
if(mMediaSource)
{
- mMediaSource->stop();
+ if(mMediaSource->pluginSupportsMediaBrowser())
+ {
+ mMediaSource->browse_stop();
+ }
+ else
+ {
+ mMediaSource->stop();
+ }
+
// destroyMediaSource();
}
}
@@ -863,13 +1013,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;
@@ -895,8 +1058,18 @@ bool LLViewerMediaImpl::hasFocus() const
return mHasFocus;
}
+std::string LLViewerMediaImpl::getCurrentMediaURL()
+{
+ if(!mCurrentMediaURL.empty())
+ {
+ return mCurrentMediaURL;
+ }
+
+ return mMediaURL;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
+void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -904,12 +1077,12 @@ void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
// llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
+void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -917,12 +1090,12 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
// llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
+void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -930,50 +1103,65 @@ void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
// llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
{
if(mMediaSource)
{
mouseDown(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask, button);
}
}
-void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
{
if(mMediaSource)
{
mouseUp(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask, button);
}
}
-void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
{
if(mMediaSource)
{
mouseMove(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y)
+void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
{
scaleMouse(&x, &y);
mLastMouseX = x;
mLastMouseY = y;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
+{
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+ if (mMediaSource)
+ {
+ mMediaSource->scrollEvent(x, y, mask);
}
}
@@ -982,7 +1170,7 @@ void LLViewerMediaImpl::onMouseCaptureLost()
{
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, mLastMouseX, mLastMouseY, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
}
}
@@ -1002,48 +1190,133 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateHome()
+void LLViewerMediaImpl::navigateBack()
{
- mMediaURL = mHomeURL;
- mDoNavigateOnLoad = !mMediaURL.empty();
- mDoNavigateOnLoadServerRequest = false;
-
- if(mMediaSource)
+ if (mMediaSource)
{
- mMediaSource->loadURI( mHomeURL );
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 step_scale = 0.02; // temp , can be changed
+ F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+ if(back_step < 0.0)
+ {
+ back_step = 0.0;
+ }
+ mMediaSource->seek(back_step);
+ //mMediaSource->start(-2.0);
+ }
+ else
+ {
+ mMediaSource->browse_back();
+ }
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
+void LLViewerMediaImpl::navigateForward()
{
- if(server_request)
+ if (mMediaSource)
{
- setNavState(MEDIANAVSTATE_SERVER_SENT);
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 step_scale = 0.02; // temp , can be changed
+ F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+ if(forward_step > mMediaSource->getDuration())
+ {
+ forward_step = mMediaSource->getDuration();
+ }
+ mMediaSource->seek(forward_step);
+ //mMediaSource->start(2.0);
+ }
+ else
+ {
+ mMediaSource->browse_forward();
+ }
}
- else
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
+{
+ navigateTo(getCurrentMediaURL(), "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateHome()
+{
+ navigateTo(mHomeURL, "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
+{
+ if(mMediaURL != url)
{
- setNavState(MEDIANAVSTATE_NONE);
+ // Don't carry media play state across distinct URLs.
+ resetPreviousMediaState();
}
- // Always set the current URL.
+ // Always set the current URL and MIME type.
mMediaURL = url;
+ mMimeType = mime_type;
+
+ // Clear the current media URL, since it will no longer be correct.
+ mCurrentMediaURL.clear();
+
+ // if mime type discovery was requested, we'll need to do it when the media loads
+ mNavigateRediscoverType = rediscover_type;
- // If the current URL is not null, make the instance do a navigate on load.
- mDoNavigateOnLoad = !mMediaURL.empty();
-
// 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;
}
- if(rediscover_type)
+ 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
+ // but the parcel owner has correctly set the MIME type in the parcel media settings.
+
+ if(!mMimeType.empty() && (mMimeType != "none/none"))
+ {
+ std::string plugin_basename = LLMIMETypes::implType(mMimeType);
+ if(!plugin_basename.empty())
+ {
+ // We have a plugin for this mime type
+ mNavigateRediscoverType = false;
+ }
+ }
+
+ if(mNavigateRediscoverType)
{
LLURI uri(mMediaURL);
@@ -1059,7 +1332,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
@@ -1067,24 +1340,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;
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1101,10 +1368,43 @@ void LLViewerMediaImpl::navigateStop()
bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
{
bool result = false;
+ // *NOTE:Mani - if this doesn't exist llmozlib goes crashy in the debug build.
+ // LLMozlib::init wants to write some files to <exe_dir>/components
+ std::string debug_init_component_dir( gDirUtilp->getExecutableDir() );
+ debug_init_component_dir += "/components";
+ LLAPRFile::makeDir(debug_init_component_dir.c_str());
if (mMediaSource)
{
- result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+ // FIXME: THIS IS SO WRONG.
+ // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
+ if( MASK_CONTROL & mask )
+ {
+ if( 'C' == key )
+ {
+ mMediaSource->copy();
+ result = true;
+ }
+ else
+ if( 'V' == key )
+ {
+ mMediaSource->paste();
+ result = true;
+ }
+ else
+ if( 'X' == key )
+ {
+ mMediaSource->cut();
+ result = true;
+ }
+ }
+
+ 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);
+ }
}
return result;
@@ -1117,7 +1417,12 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
if (mMediaSource)
{
- mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)));
+ // only accept 'printable' characters, sigh...
+ 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));
+ }
}
return result;
@@ -1175,6 +1480,7 @@ void LLViewerMediaImpl::update()
if(mMediaSource->isPluginExited())
{
+ resetPreviousMediaState();
destroyMediaSource();
return;
}
@@ -1291,7 +1597,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
//////////////////////////////////////////////////////////////////////////////////////////
-LLUUID LLViewerMediaImpl::getMediaTextureID()
+LLUUID LLViewerMediaImpl::getMediaTextureID() const
{
return mTextureId;
}
@@ -1371,12 +1677,63 @@ bool LLViewerMediaImpl::hasMedia()
}
//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+ mPreviousMediaState = MEDIA_NONE;
+ mPreviousMediaTime = 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isForcedUnloaded() const
+{
+ if(mIsMuted || mMediaSourceFailed || mIsDisabled)
+ {
+ return true;
+ }
+
+ if(sInWorldMediaDisabled)
+ {
+ // When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
+ if(!mUsedInUI)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
{
switch(event)
{
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ // The plugin failed to load properly. Make sure the timer doesn't retry.
+ // 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;
+ args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
+ LLNotifications::instance().add("MediaPluginFailed", args);
+ }
+ break;
+
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!
@@ -1423,7 +1780,21 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
- setNavState(MEDIANAVSTATE_NONE);
+
+ if(getNavState() == MEDIANAVSTATE_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getNavigateURI();
+ setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED);
+ }
+ else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getNavigateURI();
+ setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED);
+ }
+ else
+ {
+ // all other cases need to leave the state alone.
+ }
}
break;
@@ -1433,10 +1804,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
if(getNavState() == MEDIANAVSTATE_BEGUN)
{
+ mCurrentMediaURL = plugin->getLocation();
setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
}
else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
{
+ mCurrentMediaURL = plugin->getLocation();
setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
}
else
@@ -1536,10 +1909,35 @@ void LLViewerMediaImpl::calculateInterest()
}
else
{
- // I don't think this case should ever be hit.
- LL_WARNS("Plugin") << "no texture!" << LL_ENDL;
+ // 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()
@@ -1565,11 +1963,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();
@@ -1590,6 +1988,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)
@@ -1597,6 +2004,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();
}
}
@@ -1626,9 +2038,11 @@ void LLViewerMediaImpl::setNavState(EMediaNavState state)
case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
}
}
@@ -1645,11 +2059,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
@@ -1657,6 +2073,19 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
return &mObjectList ;
}
+LLVOVolume *LLViewerMediaImpl::getSomeObject()
+{
+ LLVOVolume *result = NULL;
+
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ if(iter != mObjectList.end())
+ {
+ result = *iter;
+ }
+
+ return result;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
//static
void LLViewerMedia::toggleMusicPlay(void*)