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.cpp282
1 files changed, 197 insertions, 85 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 69d4da373e..f2ddb0b1f1 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -32,6 +32,7 @@
#include "llviewerprecompiledheaders.h"
+#include "llagent.h"
#include "llviewermedia.h"
#include "llviewermediafocus.h"
#include "llmimetypes.h"
@@ -46,7 +47,7 @@
#include "llpluginclassmedia.h"
#include "llevent.h" // LLSimpleListener
-#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "lluuid.h"
#include "llkeyboard.h"
#include "llmutelist.h"
@@ -54,6 +55,8 @@
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
+/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "AutoPlayMedia";
+
// Move this to its own file.
LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
@@ -159,12 +162,27 @@ public:
virtual void error( U32 status, const std::string& reason )
{
- llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
- if(mMediaImpl)
+ if(status == 401)
+ {
+ // This is the "you need to authenticate" status.
+ // Treat this like an html page.
+ completeAny(status, "text/html");
+ }
+ else
+ if(status == 404)
{
- mMediaImpl->mMediaSourceFailed = true;
+ // Treat 404s like an html page.
+ completeAny(status, "text/html");
+ }
+ else
+ {
+ llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
+
+ if(mMediaImpl)
+ {
+ mMediaImpl->mMediaSourceFailed = true;
+ }
}
- // completeAny(status, "none/none");
}
void completeAny(U32 status, const std::string& mime_type)
@@ -266,7 +284,7 @@ viewer_media_t LLViewerMedia::newMediaImpl(
}
else
{
- media_impl->stop();
+ media_impl->unload();
media_impl->mTextureId = texture_id;
media_impl->mMediaWidth = media_width;
media_impl->mMediaHeight = media_height;
@@ -281,7 +299,12 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
{
// Try to find media with the same media ID
viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
-
+
+ lldebugs << "called, current URL is \"" << media_entry->getCurrentURL()
+ << "\", previous URL is \"" << previous_url
+ << "\", update_from_self is " << (update_from_self?"true":"false")
+ << llendl;
+
bool was_loaded = false;
bool needs_navigate = false;
@@ -302,21 +325,32 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
}
+ bool url_changed = (media_entry->getCurrentURL() != previous_url);
if(media_entry->getCurrentURL().empty())
{
- // The current media URL is now empty. Unload the media source.
- media_impl->unload();
+ if(url_changed)
+ {
+ // The current media URL is now empty. Unload the media source.
+ media_impl->unload();
+
+ lldebugs << "Unloading media instance (new current URL is empty)." << llendl;
+ }
}
else
{
// 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_entry->getAutoPlay() && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING));
- if((was_loaded || (media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))) && !update_from_self)
+ if((was_loaded || auto_play) && !update_from_self)
{
- needs_navigate = (media_entry->getCurrentURL() != previous_url);
+ needs_navigate = url_changed;
}
+
+ lldebugs << "was_loaded is " << (was_loaded?"true":"false")
+ << ", auto_play is " << (auto_play?"true":"false")
+ << ", needs_navigate is " << (needs_navigate?"true":"false") << llendl;
}
}
else
@@ -330,7 +364,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->setHomeURL(media_entry->getHomeURL());
- if(media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))
+ if(media_entry->getAutoPlay() && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING))
{
needs_navigate = true;
}
@@ -342,6 +376,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
if(needs_navigate)
{
media_impl->navigateTo(url, "", true, true);
+ lldebugs << "navigating to URL " << url << llendl;
}
else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != url))
{
@@ -350,6 +385,8 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
// If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast.
media_impl->mNavigateServerRequest = true;
+
+ lldebugs << "updating URL in the media impl to " << url << llendl;
}
}
@@ -530,6 +567,16 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView
// The item with user focus always comes to the front of the list, period.
return false;
}
+ else if(i1->isParcelMedia())
+ {
+ // The parcel media impl sorts above all other inworld media, unless one has focus.
+ return true;
+ }
+ else if(i2->isParcelMedia())
+ {
+ // The parcel media impl sorts above all other inworld media, unless one has focus.
+ return false;
+ }
else if(i1->getUsedInUI() && !i2->getUsedInUI())
{
// i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list.
@@ -540,16 +587,21 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView
// i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list.
return false;
}
- else if(i1->isParcelMedia())
+ else if(i1->isPlayable() && !i2->isPlayable())
{
- // The parcel media impl sorts above all other inworld media, unless one has focus.
+ // Playable items sort above ones that wouldn't play even if they got high enough priority
return true;
}
- else if(i2->isParcelMedia())
+ else if(!i1->isPlayable() && i2->isPlayable())
{
- // The parcel media impl sorts above all other inworld media, unless one has focus.
+ // Playable items sort above ones that wouldn't play even if they got high enough priority
return false;
}
+ else if(i1->getInterest() == i2->getInterest())
+ {
+ // Generally this will mean both objects have zero interest. In this case, sort on distance.
+ return (i1->getProximityDistance() < i2->getProximityDistance());
+ }
else
{
// The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
@@ -557,6 +609,11 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView
}
}
+static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+ return (i1->getProximityDistance() < i2->getProximityDistance());
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::updateMedia()
@@ -582,12 +639,9 @@ 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;
-#endif
-
+
+ std::vector<LLViewerMediaImpl*> proximity_order;
+
U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
@@ -618,10 +672,12 @@ void LLViewerMedia::updateMedia()
else if(pimpl->hasFocus())
{
new_priority = LLPluginClassMedia::PRIORITY_HIGH;
+ impl_count_interest_normal++; // count this against the count of "normal" instances for priority purposes
}
else if(pimpl->getUsedInUI())
{
new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ impl_count_interest_normal++;
}
else
{
@@ -629,7 +685,17 @@ void LLViewerMedia::updateMedia()
// Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
// turn it down to low instead of normal. This may downsample for plugins that support it.
- bool media_is_small = pimpl->getInterest() < (pimpl->getApproximateTextureInterest() / 4);
+ bool media_is_small = false;
+ F64 approximate_interest = pimpl->getApproximateTextureInterest();
+ if(approximate_interest == 0.0f)
+ {
+ // this media has no current size, which probably means it's not loaded.
+ media_is_small = true;
+ }
+ else if(pimpl->getInterest() < (approximate_interest / 4))
+ {
+ media_is_small = true;
+ }
if(pimpl->getInterest() == 0.0f)
{
@@ -667,7 +733,7 @@ void LLViewerMedia::updateMedia()
}
}
- if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)
+ if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
{
impl_count_total++;
}
@@ -681,23 +747,27 @@ void LLViewerMedia::updateMedia()
}
else
{
- // Other impls just get the same ordering as the priority list (for now).
- pimpl->mProximity = i;
+ proximity_order.push_back(pimpl);
}
-#if 0
- LL_DEBUGS("PluginPriority") << " " << pimpl
- << ", setting priority to " << new_priority
- << (pimpl->hasFocus()?", HAS FOCUS":"")
- << (pimpl->getUsedInUI()?", is UI":"")
- << ", cpu " << pimpl->getCPUUsage()
- << ", interest " << pimpl->getInterest()
- << ", media url " << pimpl->getMediaURL() << llendl;
-#endif
-
total_cpu += pimpl->getCPUUsage();
-
- i++;
+ }
+
+ if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
+ {
+ // Give impls the same ordering as the priority list
+ // they're already in the right order for this.
+ }
+ else
+ {
+ // Use a distance-based sort for proximity values.
+ std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
+ }
+
+ // Transfer the proximity order to the proximity fields in the objects.
+ for(int i = 0; i < (int)proximity_order.size(); i++)
+ {
+ proximity_order[i]->mProximity = i;
}
LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
@@ -749,6 +819,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mIsDisabled(false),
mIsParcelMedia(false),
mProximity(-1),
+ mProximityDistance(0.0f),
mMimeTypeProbe(NULL),
mIsUpdated(false)
{
@@ -916,7 +987,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
LLSD args;
args["MIME_TYPE"] = media_type;
- LLNotifications::instance().add("NoPlugin", args);
+ LLNotificationsUtil::add("NoPlugin", args);
return NULL;
}
@@ -1046,15 +1117,7 @@ void LLViewerMediaImpl::stop()
{
if(mMediaSource)
{
- if(mMediaSource->pluginSupportsMediaBrowser())
- {
- mMediaSource->browse_stop();
- }
- else
- {
- mMediaSource->stop();
- }
-
+ mMediaSource->stop();
// destroyMediaSource();
}
}
@@ -1087,6 +1150,40 @@ void LLViewerMediaImpl::seek(F32 time)
}
//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipBack(F32 step_scale)
+{
+ if(mMediaSource)
+ {
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+ if(back_step < 0.0)
+ {
+ back_step = 0.0;
+ }
+ mMediaSource->seek(back_step);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipForward(F32 step_scale)
+{
+ if(mMediaSource)
+ {
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+ if(forward_step > mMediaSource->getDuration())
+ {
+ forward_step = mMediaSource->getDuration();
+ }
+ mMediaSource->seek(forward_step);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::setVolume(F32 volume)
{
mRequestedVolume = volume;
@@ -1293,21 +1390,7 @@ void LLViewerMediaImpl::navigateBack()
{
if (mMediaSource)
{
- 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();
- }
+ mMediaSource->browse_back();
}
}
@@ -1316,21 +1399,7 @@ void LLViewerMediaImpl::navigateForward()
{
if (mMediaSource)
{
- 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();
- }
+ mMediaSource->browse_forward();
}
}
@@ -1479,7 +1548,6 @@ void LLViewerMediaImpl::navigateStop()
{
mMediaSource->browse_stop();
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1577,6 +1645,10 @@ void LLViewerMediaImpl::update()
{
// This media source should not be loaded.
}
+ else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW)
+ {
+ // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state.
+ }
else if(mMimeTypeProbe != NULL)
{
// this media source is doing a MIME type probe -- don't try loading it again.
@@ -1704,7 +1776,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
// MEDIAOPT: seems insane that we actually have to make an imageraw then
// immediately discard it
LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth);
- raw->clear(0x0f, 0x0f, 0x0f, 0xff);
+ raw->clear(0x00, 0x00, 0x00, 0xff);
int discard_level = 0;
// ask media source for correct GL image format constants
@@ -1805,7 +1877,7 @@ bool LLViewerMediaImpl::isMediaPaused()
//////////////////////////////////////////////////////////////////////////////////////////
//
-bool LLViewerMediaImpl::hasMedia()
+bool LLViewerMediaImpl::hasMedia() const
{
return mMediaSource != NULL;
}
@@ -1840,6 +1912,31 @@ bool LLViewerMediaImpl::isForcedUnloaded() const
}
//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isPlayable() const
+{
+ if(isForcedUnloaded())
+ {
+ // All of the forced-unloaded criteria also imply not playable.
+ return false;
+ }
+
+ if(hasMedia())
+ {
+ // Anything that's already playing is, by definition, playable.
+ return true;
+ }
+
+ if(!mMediaURL.empty())
+ {
+ // If something has navigated the instance, it's ready to be played.
+ return true;
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
{
switch(event)
@@ -1856,7 +1953,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// TODO: may want a different message for this case?
LLSD args;
args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
- LLNotifications::instance().add("MediaPluginFailed", args);
+ LLNotificationsUtil::add("MediaPluginFailed", args);
}
break;
@@ -1871,7 +1968,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
LLSD args;
args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
- //LLNotifications::instance().add("MediaPluginFailed", args);
+ //LLNotificationsUtil::add("MediaPluginFailed", args);
}
break;
@@ -2047,6 +2144,15 @@ void LLViewerMediaImpl::calculateInterest()
mInterest = 0.0f;
}
+ // Calculate distance from the avatar, for use in the proximity calculation.
+ mProximityDistance = 0.0f;
+ if(!mObjectList.empty())
+ {
+ // Just use the first object in the list. We could go through the list and find the closest object, but this should work well enough.
+ LLVector3d global_delta = gAgent.getPositionGlobal() - (*mObjectList.begin())->getPositionGlobal();
+ mProximityDistance = global_delta.magVecSquared(); // use distance-squared because it's cheaper and sorts the same.
+ }
+
if(mNeedsMuteCheck)
{
// Check all objects this instance is associated with, and those objects' owners, against the mute list
@@ -2083,7 +2189,13 @@ F64 LLViewerMediaImpl::getApproximateTextureInterest()
result = mMediaSource->getFullWidth();
result *= mMediaSource->getFullHeight();
}
-
+ else
+ {
+ // No media source is loaded -- all we have to go on is the texture size that has been set on the impl, if any.
+ result = mMediaWidth;
+ result *= mMediaHeight;
+ }
+
return result;
}
@@ -2124,7 +2236,7 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
{
if(mPriority != priority)
{
- LL_INFOS("PluginPriority")
+ LL_DEBUGS("PluginPriority")
<< "changing priority of media id " << mTextureId
<< " from " << LLPluginClassMedia::priorityToString(mPriority)
<< " to " << LLPluginClassMedia::priorityToString(priority)