diff options
Diffstat (limited to 'indra')
20 files changed, 1909 insertions, 498 deletions
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp index 3c69a69d28..9c18b410c7 100644 --- a/indra/llplugin/llpluginsharedmemory.cpp +++ b/indra/llplugin/llpluginsharedmemory.cpp @@ -1,6 +1,6 @@  /**    * @file llpluginsharedmemory.cpp - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.   *   * @cond   * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -96,6 +96,10 @@ std::string LLPluginSharedMemory::createName(void)  	return newname.str();  } +/** + * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious. + * + */  class LLPluginSharedMemoryPlatformImpl  {  public: @@ -112,6 +116,9 @@ public:  }; +/** + * Constructor. Creates a shared memory segment. + */  LLPluginSharedMemory::LLPluginSharedMemory()  {  	mSize = 0; @@ -121,6 +128,9 @@ LLPluginSharedMemory::LLPluginSharedMemory()  	mImpl = new LLPluginSharedMemoryPlatformImpl;  } +/** + * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up. + */  LLPluginSharedMemory::~LLPluginSharedMemory()  {  	if(mNeedsDestroy) diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h index 4014620c52..00c54ef08c 100644 --- a/indra/llplugin/llpluginsharedmemory.h +++ b/indra/llplugin/llpluginsharedmemory.h @@ -1,6 +1,5 @@  /**    * @file llpluginsharedmemory.h - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.   *   * @cond   * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -36,6 +35,10 @@  class LLPluginSharedMemoryPlatformImpl; +/** + * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * + */  class LLPluginSharedMemory  {  	LOG_CLASS(LLPluginSharedMemory); @@ -46,16 +49,62 @@ public:  	// Parent will use create/destroy, child will use attach/detach.  	// Message transactions will ensure child attaches after parent creates and detaches before parent destroys. -	// create() implicitly creates a name for the segment which is guaranteed to be unique on the host at the current time. +   /**  +    * Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent. +    * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. +    * +    * @param[in] size Shared memory size in TODO:DOC units = bytes?. +    * +    * @return False for failure, true for success. +    */  	bool create(size_t size); +   /**  +    * Destroys a shared memory segment. Used by parent. +    * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. +    * +    * @return True. TODO:DOC - always returns true. Is this the intended behavior? +    */  	bool destroy(void); +   /**  +    * Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()? +    * +    * @param[in] name Name to attach to memory segment +    * @param[in] size Size of memory segment TODO:DOC in bytes? +    * +    * @return False on failure, true otherwise. +    */  	bool attach(const std::string &name, size_t size); +   /**  +    * Detaches shared memory segment. +    * +    * @return False on failure, true otherwise. +    */  	bool detach(void); +   /**  +    * Checks if shared memory is mapped to a non-null address. +    * +    * @return True if memory address is non-null, false otherwise. +    */  	bool isMapped(void) const { return (mMappedAddress != NULL); }; +   /**  +    * Get pointer to shared memory. +    * +    * @return Pointer to shared memory. +    */  	void *getMappedAddress(void) const { return mMappedAddress; }; +   /**  +    * Get size of shared memory. +    * +    * @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit? +    */  	size_t getSize(void) const { return mSize; }; +   /**  +    * Get name of shared memory. +    * +    * @return Name of shared memory. +    */  	std::string getName() const { return mName; };  private: diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 289e900eaf..eed84671c1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5515,6 +5515,28 @@        <key>Value</key>        <real>5.0</real>      </map> +	<key>PrimMediaMaxSortedQueueSize</key> +    <map> +      <key>Comment</key> +      <string>Maximum number of objects the viewer will load media for initially</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>100000</integer> +    </map> +	<key>PrimMediaMaxRoundRobinQueueSize</key> +    <map> +      <key>Comment</key> +      <string>Maximum number of objects the viewer will continuously update media for</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>100000</integer> +    </map>      <key>ProbeHardwareOnStartup</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9a1b749ba7..3250343b25 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -746,7 +746,15 @@ bool LLAppViewer::init()  	LLViewerJointMesh::updateVectorize();  	// load MIME type -> media impl mappings -	LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") );  +	std::string mime_types_name; +#if LL_DARWIN +	mime_types_name = "mime_types_mac.xml"; +#elif LL_LINUX +	mime_types_name = "mime_types_linux.xml"; +#else +	mime_types_name = "mime_types.xml"; +#endif +	LLMIMETypes::parseMIMETypes( mime_types_name );   	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers  	settings_to_globals(); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 6ba032c152..317399ad8b 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1080,7 +1080,7 @@ void LLFloaterTools::getMediaState()  {  	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();  	LLViewerObject* first_object = selected_objects->getFirstObject(); -	LLLineEditor* media_info = getChild<LLLineEditor>("media_info"); +	LLTextBox* media_info = getChild<LLTextBox>("media_info");  	if( !(first_object   		  && first_object->getPCode() == LL_PCODE_VOLUME @@ -1088,12 +1088,6 @@ void LLFloaterTools::getMediaState()  	      ))  	{  		childSetEnabled("Add_Media",  FALSE); -/*		childSetEnabled("media_tex", FALSE); -		childSetEnabled("add_media", FALSE); -		childSetEnabled("delete_media", FALSE); -		childSetEnabled("edit_media", FALSE); -		childSetEnabled("media_info", FALSE); -		media_info->setEnabled(FALSE);*/  		media_info->clear();  		clearMediaSettings();  		return; @@ -1105,13 +1099,6 @@ void LLFloaterTools::getMediaState()  	if(!has_media_capability)  	{  		childSetEnabled("Add_Media",  FALSE); -	/*	childSetEnabled("media_tex", FALSE); -		childSetEnabled("add_media", FALSE); -		childSetEnabled("delete_media", FALSE); -		childSetEnabled("edit_media", FALSE); -		childSetEnabled("media_info", FALSE); -		media_info->setEnabled(FALSE); -		media_info->clear();*/  		LL_WARNS("LLFloaterTools: media") << "Media not enabled (no capability) in this region!" << LL_ENDL;  		clearMediaSettings();  		return; @@ -1233,7 +1220,6 @@ void LLFloaterTools::getMediaState()  		childSetEnabled( "edit_media", bool_has_media & editable );  		childSetEnabled( "delete_media", bool_has_media & editable );  		childSetEnabled( "add_media", ( ! bool_has_media ) & editable ); -		media_info->setEnabled(false);  			// TODO: display a list of all media on the face - use 'identical' flag  	}  	else // not all face has media but at least one does. @@ -1260,8 +1246,6 @@ void LLFloaterTools::getMediaState()  			}  		} -		media_info->setEnabled(false); -		media_info->setTentative(true);  		childSetEnabled("media_tex",  TRUE);  		childSetEnabled( "edit_media", TRUE);  		childSetEnabled( "delete_media", TRUE); @@ -1392,7 +1376,7 @@ void LLFloaterTools::updateMediaTitle()  		if ( ! media_title.empty() )  		{  			// update the UI widget -			LLLineEditor* media_title_field = getChild<LLLineEditor>("media_info"); +			LLTextBox* media_title_field = getChild<LLTextBox>("media_info");  			if ( media_title_field )  			{  				media_title_field->setText( media_title ); diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 3c337961e1..0a20a4a1c9 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -61,248 +61,332 @@  const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s)  const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs  const U32 LLMediaDataClient::MAX_RETRIES = 4; +const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 10000; +const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;  //////////////////////////////////////////////////////////////////////////////////////  // -// LLMediaDataClient::Request +// LLMediaDataClient  //  ////////////////////////////////////////////////////////////////////////////////////// -/*static*/U32 LLMediaDataClient::Request::sNum = 0; -LLMediaDataClient::Request::Request(const std::string &cap_name,  -									const LLSD& sd_payload, -									LLMediaDataClientObject *obj,  -									LLMediaDataClient *mdc) -	: mCapName(cap_name),  -	  mPayload(sd_payload),  -	  mObject(obj), -	  mNum(++sNum),  -	  mRetryCount(0), -	  mMDC(mdc) +LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, +									 F32 retry_timer_delay, +									 U32 max_retries, +									 U32 max_sorted_queue_size, +									 U32 max_round_robin_queue_size) +	: mQueueTimerDelay(queue_timer_delay), +	  mRetryTimerDelay(retry_timer_delay), +	  mMaxNumRetries(max_retries), +	  mMaxSortedQueueSize(max_sorted_queue_size), +	  mMaxRoundRobinQueueSize(max_round_robin_queue_size), +	  mQueueTimerIsRunning(false), +	  mCurrentQueueIsTheSortedQueue(true)  {  } -LLMediaDataClient::Request::~Request() +LLMediaDataClient::~LLMediaDataClient()  { -	LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL; -	mMDC = NULL; -	mObject = NULL; -} +	stopQueueTimer(); -													   -std::string LLMediaDataClient::Request::getCapability() const -{ -	return getObject()->getCapabilityUrl(getCapName()); +	// This should clear the queue, and hopefully call all the destructors. +	LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<  +		(isEmpty() ? "<empty> " : "<not empty> ") << LL_ENDL; +	 +	mSortedQueue.clear(); +	mRoundRobinQueue.clear();  } -// Helper function to get the "type" of request, which just pokes around to -// discover it. -LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const +bool LLMediaDataClient::isEmpty() const  { -	if (mCapName == "ObjectMediaNavigate") -	{ -		return NAVIGATE; -	} -	else if (mCapName == "ObjectMedia") -	{ -		const std::string &verb = mPayload["verb"]; -		if (verb == "GET") -		{ -			return GET; -		} -		else if (verb == "UPDATE") -		{ -			return UPDATE; -		} -	} -	llassert(false); -	return GET; +	return mSortedQueue.empty() && mRoundRobinQueue.empty();  } -const char *LLMediaDataClient::Request::getTypeAsString() const +bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)  { -	Type t = getType(); -	switch (t) -	{ -		case GET: -			return "GET"; -			break; -		case UPDATE: -			return "UPDATE"; -			break; -		case NAVIGATE: -			return "NAVIGATE"; -			break; -	} -	return ""; +	return (LLMediaDataClient::findOrRemove(mSortedQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull() +		|| (LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()));  } -	 -void LLMediaDataClient::Request::reEnqueue() const +bool LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)  { -	// I sure hope this doesn't deref a bad pointer: -	mMDC->enqueue(this); +	bool removedFromSortedQueue = LLMediaDataClient::findOrRemove(mSortedQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull(); +	bool removedFromRoundRobinQueue = LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull(); +	return removedFromSortedQueue || removedFromRoundRobinQueue;  } -F32 LLMediaDataClient::Request::getRetryTimerDelay() const +//static +LLMediaDataClient::request_ptr_t LLMediaDataClient::findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, LLMediaDataClient::Request::Type type)  { -	return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY : -		mMDC->mRetryTimerDelay;  +	request_ptr_t result; +	request_queue_t::iterator iter = queue.begin(); +	request_queue_t::iterator end = queue.end(); +	while (iter != end) +	{ +		if (obj->getID() == (*iter)->getObject()->getID() && (type == LLMediaDataClient::Request::ANY || type == (*iter)->getType())) +		{ +			result = *iter; +			if (remove) queue.erase(iter); +			break; +		} +		iter++; +	} +	return result;  } -U32 LLMediaDataClient::Request::getMaxNumRetries() const +void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)  { -	return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries; +	if (object.isNull() || ! object->hasMedia()) return;  +	 +	// Push the object on the queue +	enqueue(new Request(getCapabilityName(), payload, object, this));  } -std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) +void LLMediaDataClient::enqueue(const Request *request)  { -	s << "<request>"  -	  << "<num>" << r.getNum() << "</num>" -	  << "<type>" << r.getTypeAsString() << "</type>" -	  << "<object_id>" << r.getObject()->getID() << "</object_id>" -	  << "<num_retries>" << r.getRetryCount() << "</num_retries>" -	  << "</request> "; -	return s; +	if (request->isNew()) +	{		 +		// Add to sorted queue +		if (LLMediaDataClient::findOrRemove(mSortedQueue, request->getObject(), true/*remove*/, request->getType()).notNull()) +		{ +			LL_DEBUGS("LLMediaDataClient") << "REMOVING OLD request for " << *request << " ALREADY THERE!" << LL_ENDL; +		} +		 +		LL_DEBUGS("LLMediaDataClient") << "Queuing SORTED request for " << *request << LL_ENDL; +		 +		// Sadly, we have to const-cast because items put into the queue are not const +		mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request)); +		 +		LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL; +	} +	else { +		if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize)  +		{ +			LL_INFOS_ONCE("LLMediaDataClient") << "RR QUEUE MAXED OUT!!!" << LL_ENDL; +			LL_DEBUGS("LLMediaDataClient") << "Not queuing " << *request << LL_ENDL; +			return; +		} +				 +		// ROUND ROBIN: if it is there, and it is a GET request, leave it.  If not, put at front!		 +		request_ptr_t existing_request; +		if (request->getType() == Request::GET) +		{ +			existing_request = LLMediaDataClient::findOrRemove(mRoundRobinQueue, request->getObject(), false/*remove*/, request->getType()); +		} +		if (existing_request.isNull()) +		{ +			LL_DEBUGS("LLMediaDataClient") << "Queuing RR request for " << *request << LL_ENDL; +			// Push the request on the pending queue +			// Sadly, we have to const-cast because items put into the queue are not const +			mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request)); +			 +			LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL;			 +		} +		else +		{ +			LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL; +						 +			existing_request->markSent(false); +		} +	}	 +	// Start the timer if not already running +	startQueueTimer();  } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Responder::RetryTimer -// -////////////////////////////////////////////////////////////////////////////////////// - -LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) -	: LLEventTimer(time), mResponder(mdr) +void LLMediaDataClient::startQueueTimer()   { +	if (! mQueueTimerIsRunning) +	{ +		LL_DEBUGS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL; +		// LLEventTimer automagically takes care of the lifetime of this object +		new QueueTimer(mQueueTimerDelay, this); +	} +	else {  +		LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL; +	}  } -// virtual  -LLMediaDataClient::Responder::RetryTimer::~RetryTimer()  +void LLMediaDataClient::stopQueueTimer()  { -	LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL; - -	// XXX This is weird: Instead of doing the work in tick()  (which re-schedules -	// a timer, which might be risky), do it here, in the destructor.  Yes, it is very odd. -	// Instead of retrying, we just put the request back onto the queue -	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL; -	mResponder->getRequest()->reEnqueue(); - -	// Release the ref to the responder. -	mResponder = NULL; +	mQueueTimerIsRunning = false;  } -// virtual -BOOL LLMediaDataClient::Responder::RetryTimer::tick() +bool LLMediaDataClient::processQueueTimer()  { -	// Don't fire again -	return TRUE; +	sortQueue(); +	 +	if(!isEmpty()) +	{ +		LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is:	  " << mSortedQueue.size()  +			<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL; +		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is:	  " << mSortedQueue << LL_ENDL; +		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is:	  " << mRoundRobinQueue << LL_ENDL; +	} +	 +	serviceQueue(); +	 +	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is:	  " << mSortedQueue.size()  +		<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL; +	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is:	  " << mSortedQueue << LL_ENDL; +	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is:	  " << mRoundRobinQueue << LL_ENDL; +	 +	return isEmpty();  } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Responder -// -////////////////////////////////////////////////////////////////////////////////////// - -LLMediaDataClient::Responder::Responder(const request_ptr_t &request) -	: mRequest(request) +void LLMediaDataClient::sortQueue()  { +	if(!mSortedQueue.empty()) +	{ +		// Score all items first +		request_queue_t::iterator iter = mSortedQueue.begin(); +		request_queue_t::iterator end = mSortedQueue.end(); +		while (iter != end) +		{ +			(*iter)->updateScore(); +			iter++; +		} +		 +		// Re-sort the list... +		// NOTE: should this be a stable_sort?  If so we need to change to using a vector. +		mSortedQueue.sort(LLMediaDataClient::compareRequests); +		 +		// ...then cull items over the max +		U32 size = mSortedQueue.size(); +		if (size > mMaxSortedQueueSize)  +		{ +			U32 num_to_cull = (size - mMaxSortedQueueSize); +			LL_INFOS("LLMediaDataClient") << "sorted queue MAXED OUT!  Culling "  +				<< num_to_cull << " items" << LL_ENDL; +			while (num_to_cull-- > 0) +			{ +				mSortedQueue.pop_back(); +			} +		} +	}  } -LLMediaDataClient::Responder::~Responder() +// static +bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)  { -	LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL; -	mRequest = NULL; +	if (o2.isNull()) return true; +	if (o1.isNull()) return false; +	return ( o1->getScore() > o2->getScore() );  } -/*virtual*/ -void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) -{ -	if (status == HTTP_SERVICE_UNAVAILABLE) +void LLMediaDataClient::serviceQueue() +{	 +	request_queue_t *queue_p = getCurrentQueue(); +	 +	// quick retry loop for cases where we shouldn't wait for the next timer tick +	while(true)  	{ -		F32 retry_timeout = mRequest->getRetryTimerDelay(); - -		mRequest->incRetryCount(); +		if (queue_p->empty()) +		{ +			LL_DEBUGS("LLMediaDataClient") << "queue empty: " << (*queue_p) << LL_ENDL; +			break; +		} -		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries())  +		// Peel one off of the items from the queue, and execute request +		request_ptr_t request = queue_p->front(); +		llassert(!request.isNull()); +		const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject(); +		llassert(NULL != object); +		 +		// Check for conditions that would make us just pop and rapidly loop through +		// the queue. +		if(request.isNull() || +		   request->isMarkedSent() || +		   NULL == object || +		   object->isDead() || +		   !object->hasMedia())  		{ -			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; +			if (request.isNull())  +			{ +				LL_INFOS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL; +			} +			else { +				LL_INFOS("LLMediaDataClient") << "Skipping : " << *request << " "  +				<< ((request->isMarkedSent()) ? " request is marked sent" : +					((NULL == object) ? " object is NULL " : +					 ((object->isDead()) ? "object is dead" :  +					  ((!object->hasMedia()) ? "object has no media!" : "BADNESS!")))) << LL_ENDL; +			} +			queue_p->pop_front(); +			continue;	// jump back to the start of the quick retry loop +		} +		 +		// Next, ask if this is "interesting enough" to fetch.  If not, just stop +		// and wait for the next timer go-round.  Only do this for the sorted  +		// queue. +		if (mCurrentQueueIsTheSortedQueue && !object->isInterestingEnough()) +		{ +			LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL; +			break; +		} +		 +		// Finally, try to send the HTTP message to the cap url +		std::string url = request->getCapability(); +		bool maybe_retry = false; +		if (!url.empty()) +		{ +			const LLSD &sd_payload = request->getPayload(); +			LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; +			 +			// Call the subclass for creating the responder +			LLHTTPClient::post(url, sd_payload, createResponder(request)); +		} +		else { +			LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; +			maybe_retry = true; +		} -			// Start timer (instances are automagically tracked by -			// InstanceTracker<> and LLEventTimer) -			new RetryTimer(F32(retry_timeout/*secs*/), this); +		bool exceeded_retries = request->getRetryCount() > mMaxNumRetries; +		if (maybe_retry && ! exceeded_retries) // Try N times before giving up  +		{ +			// We got an empty cap, but in that case we will retry again next +			// timer fire. +			request->incRetryCount();  		}  		else { -			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " <<  -				mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; +			if (exceeded_retries) +			{ +				LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "  +					<< mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;  +				// XXX Should we bring up a warning dialog?? +			} +			 +			queue_p->pop_front(); +			 +			if (! mCurrentQueueIsTheSortedQueue) { +				// Round robin +				request->markSent(true); +				mRoundRobinQueue.push_back(request);				 +			}  		} +		 + 		// end of quick loop -- any cases where we want to loop will use 'continue' to jump back to the start. + 		break;  	} -	else { -		std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; -		LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; -	} +	 +	swapCurrentQueue();  } - -/*virtual*/ -void LLMediaDataClient::Responder::result(const LLSD& content) +void LLMediaDataClient::swapCurrentQueue()  { -	LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL; +	// Swap +	mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; +	// If its empty, swap back +	if (getCurrentQueue()->empty())  +	{ +		mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; +	}  } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Comparator -// -////////////////////////////////////////////////////////////////////////////////////// - -// static -bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2) +LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue()  { -	if (o2.isNull()) return true; -	if (o1.isNull()) return false; - -	// The score is intended to be a measure of how close an object is or -	// how much screen real estate (interest) it takes up -	// Further away = lower score. -	// Lesser interest = lower score -	// For instance, here are some cases: -	// 1: Two items with no impl, closest one wins -	// 2: Two items with an impl: interest should rule, but distance is -	// still taken into account (i.e. something really close might take -	// precedence over a large item far away) -	// 3: One item with an impl, another without: item with impl wins  -	//	  (XXX is that what we want?)		  -	// Calculate the scores for each.   -	F64 o1_score = getObjectScore(o1->getObject()); -	F64 o2_score = getObjectScore(o2->getObject()); -	return ( o1_score > o2_score ); -} - -// static -F64 LLMediaDataClient::getObjectScore(const LLMediaDataClientObject::ptr_t &obj) -{ -	// *TODO: make this less expensive? -	F64 dist = obj->getDistanceFromAvatar() + 0.1;	 // avoids div by 0 -	// square the distance so that they are in the same "unit magnitude" as -	// the interest (which is an area)  -	dist *= dist; -	F64 interest = obj->getTotalMediaInterest() + 1.0; -		 -	return interest/dist;	    +	return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue;  } -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::PriorityQueue -// Queue of LLMediaDataClientObject smart pointers to request media for. -// -////////////////////////////////////////////////////////////////////////////////////// -  // dump the queue  std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q)  { @@ -318,22 +402,6 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue  	return s;  } -// find the given object in the queue. -bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const -{ -	request_queue_t::const_iterator iter = pRequestQueue->begin(); -	request_queue_t::const_iterator end = pRequestQueue->end(); -	while (iter != end) -	{ -		if (obj->getID() == (*iter)->getObject()->getID()) -		{ -			return true; -		} -		iter++; -	} -	return false; -} -  //////////////////////////////////////////////////////////////////////////////////////  //  // LLMediaDataClient::QueueTimer @@ -342,7 +410,7 @@ bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const  //////////////////////////////////////////////////////////////////////////////////////  LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc) -	: LLEventTimer(time), mMDC(mdc) +: LLEventTimer(time), mMDC(mdc)  {  	mMDC->setIsRunning(true);  } @@ -357,177 +425,224 @@ LLMediaDataClient::QueueTimer::~QueueTimer()  // virtual  BOOL LLMediaDataClient::QueueTimer::tick()  { -	if (NULL == mMDC->pRequestQueue) -	{ -		// Shutting down?  stop. -		LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL; -		return TRUE; -	} -	 -	request_queue_t &queue = *(mMDC->pRequestQueue); +	if (mMDC.isNull()) return TRUE; +	return mMDC->processQueueTimer(); +} -	if(!queue.empty()) -	{ -		LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is:	  " << queue << LL_ENDL; -		// Re-sort the list every time... -		// XXX Is this really what we want? -		queue.sort(LLMediaDataClient::compareRequests); -	} +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Responder::RetryTimer +// +////////////////////////////////////////////////////////////////////////////////////// + +LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) +: LLEventTimer(time), mResponder(mdr) +{ +} + +// virtual  +LLMediaDataClient::Responder::RetryTimer::~RetryTimer()  +{ +	LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL; -	// quick retry loop for cases where we shouldn't wait for the next timer tick -	while(true) -	{ -		if (queue.empty()) -		{ -			LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL; -			return TRUE; -		} +	// XXX This is weird: Instead of doing the work in tick()  (which re-schedules +	// a timer, which might be risky), do it here, in the destructor.  Yes, it is very odd. +	// Instead of retrying, we just put the request back onto the queue +	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << " retrying" << LL_ENDL; +	mResponder->getRequest()->reEnqueue(); -		// Peel one off of the items from the queue, and execute request -		request_ptr_t request = queue.front(); -		llassert(!request.isNull()); -		const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject(); -		bool performed_request = false; -		bool error = false; -		llassert(NULL != object); +	// Release the ref to the responder. +	mResponder = NULL; +} -		if(object->isDead()) -		{ -			// This object has been marked dead.  Pop it and move on to the next item in the queue immediately. -			LL_INFOS("LLMediaDataClient") << "Skipping " << *request << ": object is dead!" << LL_ENDL; -			queue.pop_front(); -			continue;	// jump back to the start of the quick retry loop -		} +// virtual +BOOL LLMediaDataClient::Responder::RetryTimer::tick() +{ +	// Don't fire again +	return TRUE; +} -		if (NULL != object && object->hasMedia()) -		{ -			std::string url = request->getCapability(); -			if (!url.empty()) -			{ -				const LLSD &sd_payload = request->getPayload(); -				LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; -				// Call the subclass for creating the responder -				LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request)); -				performed_request = true; -			} -			else { -				LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; -			} -		} -		else { -			if (request.isNull())  -			{ -				LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL; -			} -			else if (NULL == object)  -			{ -				LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL; -			} -			else if (!object->hasMedia()) -			{ -				LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; -			} -			error = true; -		} -		bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries; -		if (performed_request || exceeded_retries || error) // Try N times before giving up  -		{ -			if (exceeded_retries) -			{ -				LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "  -											  << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;  -				// XXX Should we bring up a warning dialog?? -			} -			queue.pop_front(); -		} -		else { -			request->incRetryCount(); -		} -		 - 		// end of quick retry loop -- any cases where we want to loop will use 'continue' to jump back to the start. - 		break; -	}   +////////////////////////////////////////////////////////////////////////////////////// +// +// LLMediaDataClient::Request +// +////////////////////////////////////////////////////////////////////////////////////// +/*static*/U32 LLMediaDataClient::Request::sNum = 0; -	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL; +LLMediaDataClient::Request::Request(const char *cap_name,  +									const LLSD& sd_payload, +									LLMediaDataClientObject *obj,  +									LLMediaDataClient *mdc) +: mCapName(cap_name),  +  mPayload(sd_payload),  +  mObject(obj), +  mNum(++sNum),  +  mRetryCount(0), +  mMDC(mdc), +  mMarkedSent(false), +  mScore((F64)0.0) +{ +} -	return queue.empty(); +LLMediaDataClient::Request::~Request() +{ +	LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL; +	mMDC = NULL; +	mObject = NULL;  } -	 -void LLMediaDataClient::startQueueTimer()  + + +std::string LLMediaDataClient::Request::getCapability() const  { -	if (! mQueueTimerIsRunning) +	return getObject()->getCapabilityUrl(getCapName()); +} + +// Helper function to get the "type" of request, which just pokes around to +// discover it. +LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const +{ +	if (0 == strcmp(mCapName, "ObjectMediaNavigate"))  	{ -		LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL; -		// LLEventTimer automagically takes care of the lifetime of this object -		new QueueTimer(mQueueTimerDelay, this); +		return NAVIGATE;  	} -	else {  -		LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL; +	else if (0 == strcmp(mCapName, "ObjectMedia")) +	{ +		const std::string &verb = mPayload["verb"]; +		if (verb == "GET") +		{ +			return GET; +		} +		else if (verb == "UPDATE") +		{ +			return UPDATE; +		}  	} +	llassert(false); +	return GET;  } -	 -void LLMediaDataClient::stopQueueTimer() + +const char *LLMediaDataClient::Request::getTypeAsString() const  { -	mQueueTimerIsRunning = false; +	Type t = getType(); +	switch (t) +	{ +		case GET: +			return "GET"; +			break; +		case UPDATE: +			return "UPDATE"; +			break; +		case NAVIGATE: +			return "NAVIGATE"; +			break; +		case ANY: +			return "ANY"; +			break; +	} +	return "";  } -	 -void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload) + + +void LLMediaDataClient::Request::reEnqueue() const  { -	if (object.isNull() || ! object->hasMedia()) return;  +	// I sure hope this doesn't deref a bad pointer: +	mMDC->enqueue(this); +} -	// Push the object on the priority queue -	enqueue(new Request(getCapabilityName(), payload, object, this)); +F32 LLMediaDataClient::Request::getRetryTimerDelay() const +{ +	return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY : +	mMDC->mRetryTimerDelay;   } -void LLMediaDataClient::enqueue(const Request *request) +U32 LLMediaDataClient::Request::getMaxNumRetries() const  { -	LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL; -	// Push the request on the priority queue -	// Sadly, we have to const-cast because items put into the queue are not const -	pRequestQueue->push_back(const_cast<LLMediaDataClient::Request*>(request)); -	LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL; -	// Start the timer if not already running -	startQueueTimer(); +	return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries; +} + +void LLMediaDataClient::Request::markSent(bool flag) +{ +	 if (mMarkedSent != flag) +	 { +		 mMarkedSent = flag; +		 if (!mMarkedSent) +		 { +			 mNum = ++sNum; +		 } +	 } +} +		    +void LLMediaDataClient::Request::updateScore() +{				 +	F64 tmp = mObject->getMediaInterest(); +	if (tmp != mScore) +	{ +		LL_DEBUGS("LLMediaDataClient") << "Score for " << mObject->getID() << " changed from " << mScore << " to " << tmp << LL_ENDL;  +		mScore = tmp; +	} +} +		    +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) +{ +	s << "request: num=" << r.getNum()  +	<< " type=" << r.getTypeAsString()  +	<< " ID=" << r.getObject()->getID()  +	<< " #retries=" << r.getRetryCount(); +	return s;  } +			  //////////////////////////////////////////////////////////////////////////////////////  // -// LLMediaDataClient +// LLMediaDataClient::Responder  //  ////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, -									 F32 retry_timer_delay, -									 U32 max_retries) -	: mQueueTimerDelay(queue_timer_delay), -	  mRetryTimerDelay(retry_timer_delay), -	  mMaxNumRetries(max_retries), -	  mQueueTimerIsRunning(false) +LLMediaDataClient::Responder::Responder(const request_ptr_t &request) +: mRequest(request)  { -	pRequestQueue = new request_queue_t();  } -LLMediaDataClient::~LLMediaDataClient() +LLMediaDataClient::Responder::~Responder()  { -	stopQueueTimer(); - -	// This should clear the queue, and hopefully call all the destructors. -	LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<  -		(pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL; -	delete pRequestQueue; -	pRequestQueue = NULL; +	LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL; +	mRequest = NULL;  } -bool LLMediaDataClient::isEmpty() const +/*virtual*/ +void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)  { -	return (NULL == pRequestQueue) ? true : pRequestQueue->empty(); +	if (status == HTTP_SERVICE_UNAVAILABLE) +	{ +		F32 retry_timeout = mRequest->getRetryTimerDelay(); +		 +		mRequest->incRetryCount(); +		 +		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries())  +		{ +			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; +			 +			// Start timer (instances are automagically tracked by +			// InstanceTracker<> and LLEventTimer) +			new RetryTimer(F32(retry_timeout/*secs*/), this); +		} +		else { +			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " <<  +			mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; +		} +	} +	else { +		std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; +		LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; +	}  } -bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) const +/*virtual*/ +void LLMediaDataClient::Responder::result(const LLSD& content)  { -	return (NULL == pRequestQueue) ? false : find(object); +	LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;  }  ////////////////////////////////////////////////////////////////////////////////////// @@ -569,7 +684,7 @@ void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)  	}  	sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; -	LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL; +	LL_DEBUGS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;  	request(object, sd_payload);  } @@ -581,7 +696,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)  	llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)  	if (type == LLMediaDataClient::Request::GET)  	{ -		LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL; +		LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;  		// Look for an error  		if (content.has("error")) @@ -598,12 +713,13 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)  			if (object_id != getRequest()->getObject()->getID())   			{  				// NOT good, wrong object id!! -				LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; +				LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;  				return;  			}  			// Otherwise, update with object media data -			getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]); +			getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY], +															 content[LLTextureEntry::MEDIA_VERSION_KEY]);  		}  	}  	else if (type == LLMediaDataClient::Request::UPDATE) diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index 812e9cbdec..75d32e707b 100755 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -55,15 +55,19 @@ public:  	// Does this object have media?  	virtual bool hasMedia() const = 0;  	// Update the object's media data to the given array -	virtual void updateObjectMediaData(LLSD const &media_data_array) = 0; -	// Return the distance from the object to the avatar -	virtual F64 getDistanceFromAvatar() const = 0; +	virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;  	// Return the total "interest" of the media (on-screen area) -	virtual F64 getTotalMediaInterest() const = 0; +	virtual F64 getMediaInterest() const = 0;  	// Return the given cap url  	virtual std::string getCapabilityUrl(const std::string &name) const = 0;  	// Return whether the object has been marked dead  	virtual bool isDead() const = 0; +	// Returns a media version number for the object +	virtual U32 getMediaVersion() const = 0; +	// Returns whether the object is "interesting enough" to fetch +	virtual bool isInterestingEnough() const = 0; +	// Returns whether we've seen this object yet or not +	virtual bool isNew() const = 0;  	// smart pointer  	typedef LLPointer<LLMediaDataClientObject> ptr_t; @@ -79,11 +83,15 @@ public:      const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)  	const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs  	const static U32 MAX_RETRIES;// = 4; +	const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000; +	const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;  	// Constructor  	LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,  					  F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, -		              U32 max_retries = MAX_RETRIES); +		              U32 max_retries = MAX_RETRIES, +					  U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, +					  U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);  	// Make the request  	void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload); @@ -94,7 +102,13 @@ public:  	bool isEmpty() const;  	// Returns true iff the given object is in the queue -	bool isInQueue(const LLMediaDataClientObject::ptr_t &object) const; +	bool isInQueue(const LLMediaDataClientObject::ptr_t &object); +	 +	// Remove the given object from the queue. Returns true iff the given object is removed. +	bool removeFromQueue(const LLMediaDataClientObject::ptr_t &object); +	 +	// Called only by the Queue timer and tests (potentially) +	bool processQueueTimer();  protected:  	// Destructor @@ -107,11 +121,12 @@ protected:          enum Type {              GET,              UPDATE, -            NAVIGATE +            NAVIGATE, +			ANY          }; -		Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc); -		const std::string &getCapName() const { return mCapName; } +		Request(const char *cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc); +		const char *getCapName() const { return mCapName; }  		const LLSD &getPayload() const { return mPayload; }  		LLMediaDataClientObject *getObject() const { return mObject; } @@ -132,6 +147,12 @@ protected:  		F32 getRetryTimerDelay() const;  		U32 getMaxNumRetries() const; +		bool isNew() const { return mObject.notNull() ? mObject->isNew() : false; } +		void markSent(bool flag); +		bool isMarkedSent() const { return mMarkedSent; } +		void updateScore(); +		F64 getScore() const { return mScore; } +		  	public:  		friend std::ostream& operator<<(std::ostream &s, const Request &q); @@ -139,14 +160,16 @@ protected:          virtual ~Request(); // use unref();  	private: -		std::string mCapName; +		const char *mCapName;  		LLSD mPayload;  		LLMediaDataClientObject::ptr_t mObject;  		// Simple tracking -		const U32 mNum; +		U32 mNum;  		static U32 sNum;          U32 mRetryCount; -		 +		F64 mScore; +		bool mMarkedSent; +  		// Back pointer to the MDC...not a ref!  		LLMediaDataClient *mMDC;  	}; @@ -184,18 +207,23 @@ protected:  	};  protected: -	 -	void enqueue(const Request*); -	 +  	// Subclasses must override this factory method to return a new responder  	virtual Responder *createResponder(const request_ptr_t &request) const = 0;  	// Subclasses must override to return a cap name  	virtual const char *getCapabilityName() const = 0; -private: +	virtual void sortQueue(); +	virtual void serviceQueue(); +private:  	typedef std::list<request_ptr_t> request_queue_t; +		 +	void enqueue(const Request*); +	 +	// Return whether the given object is/was in the queue +	static LLMediaDataClient::request_ptr_t findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, Request::Type type);  	// Comparator for sorting  	static bool compareRequests(const request_ptr_t &o1, const request_ptr_t &o2); @@ -215,34 +243,40 @@ private:  		// back-pointer  		LLPointer<LLMediaDataClient> mMDC;  	}; - -	// Return whether the given object is in the queue -	bool find(const LLMediaDataClientObject::ptr_t &obj) const;  	void startQueueTimer();  	void stopQueueTimer();  	void setIsRunning(bool val) { mQueueTimerIsRunning = val; } - +	 +	void swapCurrentQueue(); +	request_queue_t *getCurrentQueue(); +	  	const F32 mQueueTimerDelay;  	const F32 mRetryTimerDelay;  	const U32 mMaxNumRetries; +	const U32 mMaxSortedQueueSize; +	const U32 mMaxRoundRobinQueueSize;  	bool mQueueTimerIsRunning; -	request_queue_t *pRequestQueue; +	request_queue_t mSortedQueue; +	request_queue_t mRoundRobinQueue; +	bool mCurrentQueueIsTheSortedQueue;  }; -// MediaDataResponder specific for the ObjectMedia cap +// MediaDataClient specific for the ObjectMedia cap  class LLObjectMediaDataClient : public LLMediaDataClient  {  public:      LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,  							F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, -							U32 max_retries = MAX_RETRIES) +							U32 max_retries = MAX_RETRIES, +							U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, +							U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)  		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)  		{} -    ~LLObjectMediaDataClient() {} +    virtual ~LLObjectMediaDataClient() {}  	void fetchMedia(LLMediaDataClientObject *object);       void updateMedia(LLMediaDataClientObject *object); @@ -264,7 +298,7 @@ protected:  }; -// MediaDataResponder specific for the ObjectMediaNavigate cap +// MediaDataClient specific for the ObjectMediaNavigate cap  class LLObjectMediaNavigateClient : public LLMediaDataClient  {  public: @@ -273,10 +307,12 @@ public:      LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,  								F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, -								U32 max_retries = MAX_RETRIES) +								U32 max_retries = MAX_RETRIES, +								U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, +								U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)  		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)  		{} -    ~LLObjectMediaNavigateClient() {} +    virtual ~LLObjectMediaNavigateClient() {}      void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url); diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 3fa0e7bf8f..88eba14553 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -94,7 +94,7 @@ BOOL LLPanelMediaSettingsGeneral::postBuild()  	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );  	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );  	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); -	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); +	mCurrentURL = getChild< LLTextBox >( LLMediaEntry::CURRENT_URL_KEY );  	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );  	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );  	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); @@ -284,7 +284,7 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_  		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" },  		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" },  		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" }, -		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" }, +		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLTextBox" },  		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" },  		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" },  		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" }, @@ -518,4 +518,9 @@ void LLPanelMediaSettingsGeneral::updateCurrentUrl()  	bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_current_url, value_str );  	mCurrentURL->setText(value_str);  	mCurrentURL->setTentative(identical); + +	if ( LLPanelMediaSettingsGeneral::isMultiple() ) +	{ +		mCurrentURL->setText(LLTrans::getString("Multiple Media")); +	}  }	 diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index 7782b25d63..c6895b1dc9 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -99,7 +99,7 @@ private:  	LLSpinCtrl* mWidthPixels;  	LLSpinCtrl* mHeightPixels;  	LLLineEditor* mHomeURL; -	LLLineEditor* mCurrentURL; +	LLTextBox* mCurrentURL;  	LLMediaCtrl* mPreviewMedia;  	LLTextBox* mFailWhiteListText;  }; diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index d87c7608d5..aea6b0aa3b 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -167,6 +167,9 @@ void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media  			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );  		};  	}; + +	// initial update - hides/shows status messages etc. +	self->updateWhitelistEnableStatus();  }  //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1f24a68253..57e4ed0c1e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -630,7 +630,22 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView  static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)  { -	return (i1->getProximityDistance() < i2->getProximityDistance()); +	if(i1->getProximityDistance() < i2->getProximityDistance()) +	{ +		return true; +	} +	else if(i1->getProximityDistance() > i2->getProximityDistance()) +	{ +		return false; +	} +	else +	{ +		// Both objects have the same distance.  This most likely means they're two faces of the same object. +		// They may also be faces on different objects with exactly the same distance (like HUD objects). +		// We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media. +		// Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable. +		return (i1 < i2); +	}  }  ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cf61994fea..b92d024ac9 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -92,7 +92,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");  class LLMediaDataClientObjectImpl : public LLMediaDataClientObject  {  public: -	LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {} +	LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) {}  	LLMediaDataClientObjectImpl() { mObject = NULL; }  	virtual U8 getMediaDataCount() const  @@ -128,14 +128,19 @@ public:  	virtual bool hasMedia() const  		{ return mObject->hasMedia(); } -	virtual void updateObjectMediaData(LLSD const &data)  -		{ mObject->updateObjectMediaData(data); } - -	virtual F64 getDistanceFromAvatar() const -		{ return mObject->getRenderPosition().length(); } +	virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string)  +		{ mObject->updateObjectMediaData(data, version_string); } -	virtual F64 getTotalMediaInterest() const  -		{ return mObject->getTotalMediaInterest(); } +	virtual F64 getMediaInterest() const  +		{  +			F64 tmp = mObject->getTotalMediaInterest();   +			return (tmp < 0.0) ? mObject->getPixelArea() : tmp;  +		} +	virtual bool isInterestingEnough() const +		{ +			// TODO: use performance manager to control this +			return true; +		}  	virtual std::string getCapabilityUrl(const std::string &name) const  		{ return mObject->getRegion()->getCapability(name); } @@ -143,8 +148,15 @@ public:  	virtual bool isDead() const  		{ return mObject->isDead(); } +	virtual U32 getMediaVersion() const +		{ return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } +	 +	virtual bool isNew() const +		{ return mNew; } +  private:  	LLPointer<LLVOVolume> mObject; +	bool mNew;  }; @@ -165,6 +177,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re  	mSpotLightPriority = 0.f;  	mMediaImplList.resize(getNumTEs()); +	mLastFetchedMediaVersion = -1;  }  LLVOVolume::~LLVOVolume() @@ -190,7 +203,9 @@ void LLVOVolume::markDead()  {  	if (!mDead)  	{ -		// TODO: tell LLMediaDataClient to remove this object from its queue +		LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); +		sObjectMediaClient->removeFromQueue(obj); +		sObjectMediaNavigateClient->removeFromQueue(obj);  		// Detach all media impls from this object  		for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -210,8 +225,12 @@ void LLVOVolume::initClass()  	const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");  	const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");  	const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); -    sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries); -    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries); +	const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); +	const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); +    sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries,  +													 max_sorted_queue_size, max_round_robin_queue_size); +    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay,  +																 max_retries, max_sorted_queue_size, max_round_robin_queue_size);  }  // static @@ -406,7 +425,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  			// If the media changed at all, request new media data  			LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<                  ((mMedia) ?  mMedia->mMediaURL : std::string("")) << LL_ENDL; -			requestMediaDataUpdate(); +			requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);  		}          else {              LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << @@ -1698,16 +1717,16 @@ LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)  	return result;  } -void LLVOVolume::requestMediaDataUpdate() +void LLVOVolume::requestMediaDataUpdate(bool isNew)  { -    sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this)); +    sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));  }  bool LLVOVolume::isMediaDataBeingFetched() const  {  	// I know what I'm doing by const_casting this away: this is just   	// a wrapper class that is only going to do a lookup. -	return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this))); +	return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false));  }  void LLVOVolume::cleanUpMediaImpls() @@ -1725,18 +1744,25 @@ void LLVOVolume::cleanUpMediaImpls()  	}  } -void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array) +void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)  {  	// media_data_array is an array of media entry maps +	// media_version is the version string in the response. +	U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); -	//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; - -	LLSD::array_const_iterator iter = media_data_array.beginArray(); -	LLSD::array_const_iterator end = media_data_array.endArray(); -	U8 texture_index = 0; -	for (; iter != end; ++iter, ++texture_index) +	// Only update it if it is newer! +	if ( (S32)fetched_version > mLastFetchedMediaVersion)  	{ -		syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); +		mLastFetchedMediaVersion = fetched_version; +		//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; +		 +		LLSD::array_const_iterator iter = media_data_array.beginArray(); +		LLSD::array_const_iterator end = media_data_array.endArray(); +		U8 texture_index = 0; +		for (; iter != end; ++iter, ++texture_index) +		{ +			syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); +		}  	}  } @@ -1904,7 +1930,7 @@ void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plu  		llinfos << "broadcasting navigate with URI " << new_location << llendl; -		sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location); +		sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location);  	}  } @@ -1968,7 +1994,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,  void LLVOVolume::sendMediaDataUpdate()  { -    sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this)); +    sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false));  }  void LLVOVolume::removeMediaImpl(S32 texture_index) @@ -2063,7 +2089,7 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const  F64 LLVOVolume::getTotalMediaInterest() const  { -	F64 interest = (F64)0.0; +	F64 interest = (F64)-1.0;  // means not interested;      int i = 0;  	const int end = getNumTEs();  	for ( ; i < end; ++i) @@ -2071,6 +2097,7 @@ F64 LLVOVolume::getTotalMediaInterest() const  		const viewer_media_t &impl = getMediaImpl(i);  		if (!impl.isNull())  		{ +			if (interest == (F64)-1.0) interest = (F64)0.0;  			interest += impl->getInterest();  		}  	} diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 06e214b41e..0655c13d5a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -238,7 +238,7 @@ public:      // Update this object's media data with the given media data array      // (typically this is only called upon a response from a server request) -	void updateObjectMediaData(const LLSD &media_data_array); +	void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version);      // Bounce back media at the given index to its current URL (or home URL, if current URL is empty)  	void mediaNavigateBounceBack(U8 texture_index); @@ -270,13 +270,16 @@ public:  	// Returns 'true' iff the media data for this object is in flight  	bool isMediaDataBeingFetched() const; +	// Returns the "last fetched" media version, or -1 if not fetched yet +	S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; } +	  protected:  	S32	computeLODDetail(F32	distance, F32 radius);  	BOOL calcLOD();  	LLFace* addFace(S32 face_index);  	void updateTEData(); -	void requestMediaDataUpdate(); +	void requestMediaDataUpdate(bool isNew);  	void cleanUpMediaImpls();  	void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;  	void removeMediaImpl(S32 texture_index) ; @@ -300,6 +303,7 @@ private:  	LLPointer<LLViewerFetchedTexture> mSculptTexture;  	LLPointer<LLViewerFetchedTexture> mLightTexture;  	media_list_t mMediaImplList; +	S32			mLastFetchedMediaVersion; // as fetched from the server, starts as -1  	// statics  public: diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index e3851de8e7..5e68850e30 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2669,16 +2669,15 @@ even though the user gets a free copy.               top_pad="5"               name="media_tex"               width="260"> -              Media URL +              Media  			</text> -			<line_editor +			<text  			 follows="left|top|right"  			 height="18"  			 layout="topleft"  			 left="10"  			 read_only="true"  			 name="media_info" -			 select_on_focus="true"  			 width="180" />  			<button  			 follows="top|left" diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml new file mode 100644 index 0000000000..05cd850725 --- /dev/null +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -0,0 +1,442 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> +	<defaultlabel> +		(Unknown) +	</defaultlabel> +	<defaultwidget> +		none +	</defaultwidget> +	<defaultimpl> +		media_plugin_webkit +	</defaultimpl> +	<widgetset name="web"> +		<label name="web_label"> +			Web Content +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			text/html +		</default_type> +		<tooltip name="web_tooltip"> +			This location has Web content +		</tooltip> +		<playtip name="web_playtip"> +			Show Web content +		</playtip> +		<allow_resize> +			true +		</allow_resize> +		<allow_looping> +			false +		</allow_looping> +	</widgetset> +	<widgetset name="movie"> +		<label name="movie_label"> +			Movie +		</label> +		<default_type> +			video/* +		</default_type> +		<icon> +			icn_media_movie.tga +		</icon> +		<tooltip name="movie_tooltip"> +			There is a movie to play here +		</tooltip> +		<playtip name="movie_playtip"> +			Play movie +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			true +		</allow_looping> +	</widgetset> +	<widgetset name="image"> +		<label name="image_label"> +			Image +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			image/* +		</default_type> +		<tooltip name="image_tooltip"> +			There is an image at this location +		</tooltip> +		<playtip name="image_playtip"> +			View this location's image +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			false +		</allow_looping> +	</widgetset> +	<widgetset name="audio"> +		<label name="audio_label"> +			Audio +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			audio/* +		</default_type> +		<tooltip name="audio_tooltip"> +			There is audio at this location +		</tooltip> +		<playtip name="audio_playtip"> +			Play this location's audio +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			true +		</allow_looping> +	</widgetset> +	<scheme name="rtsp"> +		<label name="rtsp_label"> +			Real Time Streaming +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</scheme> +	<mimetype name="blank"> +		<label name="blank_label"> +			- None - +		</label> +		<widgettype> +			none +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="none/none"> +		<label name="none/none_label"> +			- None - +		</label> +		<widgettype> +			none +		</widgettype> +	</mimetype> +	<mimetype name="audio/*"> +		<label name="audio2_label"> +			Audio +		</label> +		<widgettype> +			audio +		</widgettype> +	</mimetype> +	<mimetype name="video/*"> +		<label name="video2_label"> +			Video +		</label> +		<widgettype> +			movie +		</widgettype> +	</mimetype> +	<mimetype name="image/*"> +		<label name="image2_label"> +			Image +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> +		<label name="vnd.secondlife.qt.legacy_label"> +			Movie (QuickTime) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="application/javascript"> +		<label name="application/javascript_label"> +			Javascript +		</label> +		<widgettype> +			web +		</widgettype> +	</mimetype> +	<mimetype name="application/ogg"> +		<label name="application/ogg_label"> +			Ogg Audio/Video +		</label> +		<widgettype> +			audio +		</widgettype> +	</mimetype> +	<mimetype name="application/pdf"> +		<label name="application/pdf_label"> +			PDF Document +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/postscript"> +		<label name="application/postscript_label"> +			Postscript Document +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/rtf"> +		<label name="application/rtf_label"> +			Rich Text (RTF) +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/smil"> +		<label name="application/smil_label"> +			Synchronized Multimedia Integration Language (SMIL) +		</label> +		<widgettype> +			movie +		</widgettype> +	</mimetype> +	<mimetype name="application/xhtml+xml"> +		<label name="application/xhtml+xml_label"> +			Web Page (XHTML) +		</label> +		<widgettype> +			web +		</widgettype> +	</mimetype> +	<mimetype name="application/x-director"> +		<label name="application/x-director_label"> +			Macromedia Director +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="audio/mid"> +		<label name="audio/mid_label"> +			Audio (MIDI) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="audio/mpeg"> +		<label name="audio/mpeg_label"> +			Audio (MP3) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="audio/x-aiff"> +		<label name="audio/x-aiff_label"> +			Audio (AIFF) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="audio/x-wav"> +		<label name="audio/x-wav_label"> +			Audio (WAV) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/bmp"> +		<label name="image/bmp_label"> +			Image (BMP) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/gif"> +		<label name="image/gif_label"> +			Image (GIF) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/jpeg"> +		<label name="image/jpeg_label"> +			Image (JPEG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/png"> +		<label name="image/png_label"> +			Image (PNG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype name="image/svg+xml"> +		<label name="image/svg+xml_label"> +			Image (SVG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/tiff"> +		<label name="image/tiff_label"> +			Image (TIFF) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="text/html"> +		<label name="text/html_label"> +			Web Page +		</label> +		<widgettype> +			web +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="text/plain"> +		<label name="text/plain_label"> +			Text +		</label> +		<widgettype> +			text +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype name="text/xml"> +		<label name="text/xml_label"> +			XML +		</label> +		<widgettype> +			text +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/mpeg"> +		<label name="video/mpeg_label"> +			Movie (MPEG) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="video/mp4"> +		<label name="video/mp4_label"> +			Movie (MP4) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/quicktime"> +		<label name="video/quicktime_label"> +			Movie (QuickTime) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="video/x-ms-asf"> +		<label name="video/x-ms-asf_label"> +			Movie (Windows Media ASF) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype name="video/x-ms-wmv"> +		<label name="video/x-ms-wmv_label"> +			Movie (Windows Media WMV) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/x-msvideo"> +		<label name="video/x-msvideo_label"> +			Movie (AVI) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl> +	</mimetype> +</mimetypes> diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml new file mode 100644 index 0000000000..76c0d027f3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml @@ -0,0 +1,442 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> +	<defaultlabel> +		(Unknown) +	</defaultlabel> +	<defaultwidget> +		none +	</defaultwidget> +	<defaultimpl> +		media_plugin_webkit +	</defaultimpl> +	<widgetset name="web"> +		<label name="web_label"> +			Web Content +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			text/html +		</default_type> +		<tooltip name="web_tooltip"> +			This location has Web content +		</tooltip> +		<playtip name="web_playtip"> +			Show Web content +		</playtip> +		<allow_resize> +			true +		</allow_resize> +		<allow_looping> +			false +		</allow_looping> +	</widgetset> +	<widgetset name="movie"> +		<label name="movie_label"> +			Movie +		</label> +		<default_type> +			video/* +		</default_type> +		<icon> +			icn_media_movie.tga +		</icon> +		<tooltip name="movie_tooltip"> +			There is a movie to play here +		</tooltip> +		<playtip name="movie_playtip"> +			Play movie +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			true +		</allow_looping> +	</widgetset> +	<widgetset name="image"> +		<label name="image_label"> +			Image +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			image/* +		</default_type> +		<tooltip name="image_tooltip"> +			There is an image at this location +		</tooltip> +		<playtip name="image_playtip"> +			View this location's image +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			false +		</allow_looping> +	</widgetset> +	<widgetset name="audio"> +		<label name="audio_label"> +			Audio +		</label> +		<icon> +			icn_media_web.tga +		</icon> +		<default_type> +			audio/* +		</default_type> +		<tooltip name="audio_tooltip"> +			There is audio at this location +		</tooltip> +		<playtip name="audio_playtip"> +			Play this location's audio +		</playtip> +		<allow_resize> +			false +		</allow_resize> +		<allow_looping> +			true +		</allow_looping> +	</widgetset> +	<scheme name="rtsp"> +		<label name="rtsp_label"> +			Real Time Streaming +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</scheme> +	<mimetype name="blank"> +		<label name="blank_label"> +			- None - +		</label> +		<widgettype> +			none +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="none/none"> +		<label name="none/none_label"> +			- None - +		</label> +		<widgettype> +			none +		</widgettype> +	</mimetype> +	<mimetype name="audio/*"> +		<label name="audio2_label"> +			Audio +		</label> +		<widgettype> +			audio +		</widgettype> +	</mimetype> +	<mimetype name="video/*"> +		<label name="video2_label"> +			Video +		</label> +		<widgettype> +			movie +		</widgettype> +	</mimetype> +	<mimetype name="image/*"> +		<label name="image2_label"> +			Image +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> +		<label name="vnd.secondlife.qt.legacy_label"> +			Movie (QuickTime) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="application/javascript"> +		<label name="application/javascript_label"> +			Javascript +		</label> +		<widgettype> +			web +		</widgettype> +	</mimetype> +	<mimetype name="application/ogg"> +		<label name="application/ogg_label"> +			Ogg Audio/Video +		</label> +		<widgettype> +			audio +		</widgettype> +	</mimetype> +	<mimetype name="application/pdf"> +		<label name="application/pdf_label"> +			PDF Document +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/postscript"> +		<label name="application/postscript_label"> +			Postscript Document +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/rtf"> +		<label name="application/rtf_label"> +			Rich Text (RTF) +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="application/smil"> +		<label name="application/smil_label"> +			Synchronized Multimedia Integration Language (SMIL) +		</label> +		<widgettype> +			movie +		</widgettype> +	</mimetype> +	<mimetype name="application/xhtml+xml"> +		<label name="application/xhtml+xml_label"> +			Web Page (XHTML) +		</label> +		<widgettype> +			web +		</widgettype> +	</mimetype> +	<mimetype name="application/x-director"> +		<label name="application/x-director_label"> +			Macromedia Director +		</label> +		<widgettype> +			image +		</widgettype> +	</mimetype> +	<mimetype name="audio/mid"> +		<label name="audio/mid_label"> +			Audio (MIDI) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="audio/mpeg"> +		<label name="audio/mpeg_label"> +			Audio (MP3) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="audio/x-aiff"> +		<label name="audio/x-aiff_label"> +			Audio (AIFF) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="audio/x-wav"> +		<label name="audio/x-wav_label"> +			Audio (WAV) +		</label> +		<widgettype> +			audio +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/bmp"> +		<label name="image/bmp_label"> +			Image (BMP) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/gif"> +		<label name="image/gif_label"> +			Image (GIF) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/jpeg"> +		<label name="image/jpeg_label"> +			Image (JPEG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/png"> +		<label name="image/png_label"> +			Image (PNG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype name="image/svg+xml"> +		<label name="image/svg+xml_label"> +			Image (SVG) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="image/tiff"> +		<label name="image/tiff_label"> +			Image (TIFF) +		</label> +		<widgettype> +			image +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="text/html"> +		<label name="text/html_label"> +			Web Page +		</label> +		<widgettype> +			web +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="text/plain"> +		<label name="text/plain_label"> +			Text +		</label> +		<widgettype> +			text +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype name="text/xml"> +		<label name="text/xml_label"> +			XML +		</label> +		<widgettype> +			text +		</widgettype> +		<impl> +			media_plugin_webkit +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/mpeg"> +		<label name="video/mpeg_label"> +			Movie (MPEG) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="video/mp4"> +		<label name="video/mp4_label"> +			Movie (MP4) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/quicktime"> +		<label name="video/quicktime_label"> +			Movie (QuickTime) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="video/x-ms-asf"> +		<label name="video/x-ms-asf_label"> +			Movie (Windows Media ASF) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype name="video/x-ms-wmv"> +		<label name="video/x-ms-wmv_label"> +			Movie (Windows Media WMV) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +	<mimetype menu="1" name="video/x-msvideo"> +		<label name="video/x-msvideo_label"> +			Movie (AVI) +		</label> +		<widgettype> +			movie +		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl> +	</mimetype> +</mimetypes> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3e9cbe91e0..4645bfea74 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -579,7 +579,7 @@ Scripts must be allowed to run for weapons to work.     type="alertmodal">  Multiple faces are currently selected.  If you continue this action, separate instances of media will be set on multiple faces of the object. -To place the media on only one face, choose Select Texture and click on the desired face of that object then click Add. +To place the media on only one face, choose Select Face and click on the desired face of that object then click Add.      <usetemplate        ignoretext="Media will be set on multiple selected faces"        name="okcancelignore" diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml index b82a435b41..24c40b32fb 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml @@ -71,7 +71,7 @@     name="current_url_label">      Current URL:    </text> -  <line_editor  +  <text      bottom_delta="-20"      enabled="false"      follows="left|top"  diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index 6ff2c9446e..33d413bd21 100644 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -75,15 +75,13 @@  <string>baz</string>										\  </array>" -#define _DATA_URLS(ID,DIST,INT,URL1,URL2) "					\ +#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) "					\  <llsd>											\    <map>											\      <key>uuid</key>								\      <string>" ID "</string>						\ -    <key>distance</key>											\ -    <real>" DIST "</real>										\      <key>interest</key>											\ -    <real>" INT "</real>											\ +    <real>" INTEREST "</real>											\      <key>cap_urls</key>											\      <map>														\        <key>ObjectMedia</key>									\ @@ -93,21 +91,26 @@      </map>														\      <key>media_data</key>                                       \  	" MEDIA_DATA "												\ +    <key>is_dead</key>											\ +	<boolean>false</boolean>									\ +	<key>is_new</key>											\ +	<boolean>" NEW "</boolean>									\    </map>														\  </llsd>" -#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) +#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) -const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0"); +const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");  #define STR(I) boost::lexical_cast<std::string>(I)  #define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" <<			\  "================================================================================\n" << \ -"===================================== TEST " #N " ===================================\n" << \ +"==================================== TEST " #N " ===================================\n" << \  "================================================================================\n" << LL_ENDL;  LLSD *gPostRecords = NULL; +F64   gMinimumInterestLevel = (F64)0.0;  // stubs:  void LLHTTPClient::post( @@ -125,21 +128,20 @@ void LLHTTPClient::post(  	gPostRecords->append(record);  	// Magic URL that triggers a 503: +	LLSD result; +	result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY];  	if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )  	{  		responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason"); +		return;  	}  	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)   	{ -		LLSD result;  		LLSD error;  		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;  		result["error"] = error; -		responder->result(result); -	} -	else { -		responder->result(LLSD()); -	} +	}	 +	responder->result(result);  }  const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; @@ -152,13 +154,12 @@ public:  			std::istringstream d(data);  			LLSDSerialize::fromXML(mRep, d);  			mNumBounceBacks = 0; -			mDead = false;             // std::cout << ll_pretty_print_sd(mRep) << std::endl;             // std::cout << "ID: " << getID() << std::endl;  		}  	LLMediaDataClientObjectTest(const LLSD &rep)  -		: mRep(rep), mNumBounceBacks(0), mDead(false) {} +		: mRep(rep), mNumBounceBacks(0) {}  	~LLMediaDataClientObjectTest()  		{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; } @@ -169,43 +170,47 @@ public:  	virtual LLUUID getID() const   		{ return mRep["uuid"]; }  	virtual void mediaNavigateBounceBack(U8 index) -		{ -			mNumBounceBacks++; -		} +		{ mNumBounceBacks++; }	  	virtual bool hasMedia() const  		{ return mRep.has("media_data"); } -	virtual void updateObjectMediaData(LLSD const &media_data_array) -		{ mRep["media_data"] = media_data_array; } +	virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version) +		{ mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; } +		 +	virtual F64 getMediaInterest() const +		{ return (LLSD::Real)mRep["interest"]; } -	virtual F64 getDistanceFromAvatar() const -		{ return (LLSD::Real)mRep["distance"]; } +	virtual bool isInterestingEnough() const +		{ return getMediaInterest() > gMinimumInterestLevel; } -	virtual F64 getTotalMediaInterest() const -		{ return (LLSD::Real)mRep["interest"]; } -  	virtual std::string getCapabilityUrl(const std::string &name) const   		{ return mRep["cap_urls"][name]; }  	virtual bool isDead() const -		{ return mDead; } - -	void setDistanceFromAvatar(F64 val) -		{ mRep["distance"] = val; } +		{ return mRep["is_dead"]; } +	 +	virtual U32 getMediaVersion() const +		{ return (LLSD::Integer)mRep["media_version"]; } +	 +	virtual bool isNew() const +		{ return mRep["is_new"]; } -	void setTotalMediaInterest(F64 val) +	void setMediaInterest(F64 val)  		{ mRep["interest"] = val; }  	int getNumBounceBacks() const  		{ return mNumBounceBacks; }  	void markDead() -		{ mDead = true; } +		{ mRep["is_dead"] = true; } +	 +	void markOld() +		{ mRep["is_new"] = false; } +	  private:  	LLSD mRep;  	int mNumBounceBacks; -	bool mDead;  };  // This special timer delay should ensure that the timer will fire on the very @@ -224,10 +229,11 @@ namespace tut      {  		mediadataclient() {  			gPostRecords = &mLLSD; +			gMinimumInterestLevel = (F64)0.0; - 			//LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - 			//LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); -			//LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); +// 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG); +// 			LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); +//			LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);  		}  		LLSD mLLSD;      }; @@ -378,11 +384,11 @@ namespace tut  		LOG_TEST(4);  		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( -			_DATA(VALID_OBJECT_ID_1,"3.0","1.0")); +			_DATA(VALID_OBJECT_ID_1,"1.0","true"));  		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( -			_DATA(VALID_OBJECT_ID_2,"1.0","1.0")); +			_DATA(VALID_OBJECT_ID_2,"3.0","true"));  		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest( -			_DATA(VALID_OBJECT_ID_3,"2.0","1.0")); +			_DATA(VALID_OBJECT_ID_3,"2.0","true"));  		{  			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);    			const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 }; @@ -428,8 +434,7 @@ namespace tut  		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(  			_DATA_URLS(VALID_OBJECT_ID, -					   "1.0", -					   "1.0", +					   "1.0","true",  					   FAKE_OBJECT_MEDIA_CAP_URL_503,  					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));  		int num_refs_start = o->getNumRefs(); @@ -484,8 +489,7 @@ namespace tut  		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(  			_DATA_URLS(VALID_OBJECT_ID, -					   "1.0", -					   "1.0", +					   "1.0","true",  					   FAKE_OBJECT_MEDIA_CAP_URL,  					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));  		{		 @@ -517,9 +521,9 @@ namespace tut  		LOG_TEST(7);  		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( -			_DATA(VALID_OBJECT_ID_1,"3.0","1.0")); +			_DATA(VALID_OBJECT_ID_1,"3.0","true"));  		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( -			_DATA(VALID_OBJECT_ID_2,"1.0","1.0")); +			_DATA(VALID_OBJECT_ID_2,"1.0","true"));  		int num_refs_start = o1->getNumRefs();  		{  			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -551,10 +555,10 @@ namespace tut  		// Test queue handling of objects that are marked dead.  		LOG_TEST(8); -		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","1.0")); -		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","1.0")); -		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","1.0")); -		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","1.0")); +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));  		{  			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -616,10 +620,11 @@ namespace tut  		//  		LOG_TEST(9); -		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"10.0","1.0")); -		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"20.0","1.0")); -		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"30.0","1.0")); -		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"40.0","1.0")); +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true")); +		LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true")); +		LLMediaDataClientObject::ptr_t o4 = object4;  		{  			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); @@ -630,53 +635,52 @@ namespace tut  			mdc->fetchMedia(o3);  			mdc->fetchMedia(o4); -			int test_num = 0; +			int tick_num = 0; -			ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); -			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); -			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); -			ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); -			ensure(STR(test_num) + ". post records", gPostRecords->size(), 0); +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);  			::pump_timers(); -			++test_num; +			++tick_num;  			// The first tick should remove the first one  -			ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); -			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); -			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); -			ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); -			ensure(STR(test_num) + ". post records", gPostRecords->size(), 1); +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);  			// Now, pretend that object 4 moved relative to the avatar such  			// that it is now closest -			static_cast<LLMediaDataClientObjectTest*>( -				static_cast<LLMediaDataClientObject*>(o4))->setDistanceFromAvatar(5.0); +			object4->setMediaInterest(50.0);  			::pump_timers(); -			++test_num; +			++tick_num;  			// The second tick should still pick off item 2, but then re-sort  			// have picked off object 4 -			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); -			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); -			ensure(STR(test_num) + ". is not in queue 4", !mdc->isInQueue(o4)); -			ensure(STR(test_num) + ". post records", gPostRecords->size(), 2); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);  			::pump_timers(); -			++test_num; +			++tick_num;  			// The third tick should pick off object 2 -			ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); -			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); -			ensure(STR(test_num) + ". post records", gPostRecords->size(), 3); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);  			// The fourth tick should pick off object 3  			::pump_timers(); -			++test_num; +			++tick_num; -			ensure(STR(test_num) + ". is not in queue 3", !mdc->isInQueue(o3)); -			ensure(STR(test_num) + ". post records", gPostRecords->size(), 4); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);  			ensure("queue empty", mdc->isEmpty());  		} @@ -686,4 +690,249 @@ namespace tut  		ensure("refcount of o4", o4->getNumRefs(), 1);      } +	 +	template<> template<> +    void mediadataclient_object_t::test<10>() +    { +		// +		// Test using the "round-robin" queue +		// +		LOG_TEST(10); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects.  The first two should be in the sorted +			// queue [2 1], the second in the round-robin queue.  The queues +			// are serviced interleaved, so we should expect: +			// 2, 4, 1, 3 +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); +			 +			int tick_num = 0; +			 +			// 0 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			++tick_num; +			 +			// 1 The first tick should remove object 2 +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 2 The second tick should send object 4, but it will still be +			// "in the queue" +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 3 The third tick should remove object 1 +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 4 The fourth tick should send object 3, but it will still be +			// "in the queue" +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); +			 +			::pump_timers(); +			++tick_num; +						 +			// 5 The fifth tick should now identify objects 3 and 4 as no longer +			// needing "updating", and remove them from the queue +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); +			 +			::pump_timers(); +			 +			// Whew....better be empty +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1);		 +	} +	 +	 +	template<> template<> +	void mediadataclient_object_t::test<11>() +	{ +		// +		// Test LLMediaDataClient's destructor +		// +		LOG_TEST(11); +		 +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); +		int num_refs_start = o->getNumRefs(); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			mdc->fetchMedia(o); +			// must tick enough times to clear refcount of mdc +			::pump_timers(); +		}		 +		// Make sure everyone's destroyed properly +		ensure("REF COUNT", o->getNumRefs(), num_refs_start); +	} +	 +	template<> template<> +    void mediadataclient_object_t::test<12>() +    { +		// +		// Test the "not interesting enough" call +		// +		LOG_TEST(12); +		 +		LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		LLMediaDataClientObject::ptr_t o1 = object1; +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects.  The first two are "interesting enough". +			// Firing the timer 4 times should therefore leave them. +			// Note that they should be sorted 4,3,2,1 +			// Then, we'll make one "interesting enough", fire the timer a few  +			// times, and make sure only it gets pulled off the queue +			gMinimumInterestLevel = 2.5; +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); +			 +			int tick_num = 0; +			 +			// 0 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			++tick_num; +			 +			// 1 The first tick should remove object 4 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 2 The second tick should send object 3 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 3 The third tick should not pull off anything +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + +			::pump_timers(); +			++tick_num; +			 +			// 4 The fourth tick (for good measure) should not pull off anything +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			 +			// Okay, now futz with object 1's interest, such that it is now  +			// "interesting enough" +			object1->setMediaInterest((F64)5.0); +			 +			// This should sort so that the queue is now [1 2]  +			::pump_timers(); +			++tick_num; +			 +			// 5 The fifth tick should now identify objects 3 and 4 as no longer +			// needing "updating", and remove them from the queue +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 6 The sixth tick should not pull off anything +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			 +			::pump_timers(); +			++tick_num; +		 +			// Whew....better NOT be empty ... o2 should still be there +			ensure("queue not empty", !mdc->isEmpty()); +			 +			// But, we need to clear the queue, or else we won't destroy MDC... +			// this is a strange interplay between the queue timer and the MDC +			ensure("o2 couldn't be removed from queue", mdc->removeFromQueue(o2)); +			// tick +			::pump_timers(); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1);		 +	}  } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4133315480..32fdd41be2 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -803,7 +803,7 @@ class Linux_i686Manifest(LinuxManifest):          # plugins          if self.prefix(src="", dst="bin/llplugin"):              self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") -            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_quicktime.so") +            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")              self.end_prefix("bin/llplugin")          self.path("featuretable_linux.txt")  | 
