diff options
| author | Loren Shih <seraph@lindenlab.com> | 2009-12-15 11:52:44 -0500 | 
|---|---|---|
| committer | Loren Shih <seraph@lindenlab.com> | 2009-12-15 11:52:44 -0500 | 
| commit | 871e64726a147623f52776993ddced97bbf0e065 (patch) | |
| tree | d8941e09de552e354ad8b04a77f5f77fb71a4a6d | |
| parent | 045e3e06579d533619208fb415399e68714244e3 (diff) | |
| parent | f125039abcb566eaa7bdf33ce9c8c550cc25783a (diff) | |
automated merge avp->avp
--HG--
branch : avatar-pipeline
54 files changed, 2532 insertions, 843 deletions
| diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index f60838b1e7..dab6d645dd 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -79,8 +79,10 @@ LLPluginProcessParent::~LLPluginProcessParent()  		// and remove it from our map  		mSharedMemoryRegions.erase(iter);  	} - -	mProcess.kill(); +	 +	// orphaning the process means it won't be killed when the LLProcessLauncher is destructed. +	// This is what we want -- it should exit cleanly once it notices the sockets have been closed. +	mProcess.orphan();  	killSockets();  } @@ -414,7 +416,8 @@ void LLPluginProcessParent::idle(void)  			break;  			case STATE_CLEANUP: -				mProcess.kill(); +				// Don't do a kill here anymore -- closing the sockets is the new 'kill'. +				mProcess.orphan();  				killSockets();  				setState(STATE_DONE);  			break; 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/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 7cda2d31e6..33e5046f50 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -440,11 +440,17 @@ void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, E  	// Copy the map (because observers may delete themselves when updated?)  	LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers; -	observer_multimap_t::iterator oi = observers.lower_bound(id); -	observer_multimap_t::iterator end = observers.upper_bound(id); +	observer_multimap_t::iterator oi = observers.begin(); +	observer_multimap_t::iterator end = observers.end();  	for (; oi != end; ++oi)  	{ -		oi->second->processProperties(data,type); +		// only notify observers for the same agent, or if the observer +		// didn't know the agent ID and passed a NULL id. +		const LLUUID &agent_id = oi->first; +		if (agent_id == id || agent_id.isNull()) +		{ +			oi->second->processProperties(data,type); +		}  	}  } diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 56a86c2cb7..c1e8d251ee 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -72,11 +72,14 @@ LLFloaterOpenObject::~LLFloaterOpenObject()  {  //	sInstance = NULL;  } +  // virtual  BOOL LLFloaterOpenObject::postBuild()  {  	childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this  	mPanelInventoryObject = getChild<LLPanelObjectInventory>("object_contents"); +	 +	refresh();  	return TRUE;  } @@ -95,29 +98,57 @@ void LLFloaterOpenObject::onOpen(const LLSD& key)  		return;  	}  	mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); +	refresh();  } +  void LLFloaterOpenObject::refresh()  {  	mPanelInventoryObject->refresh(); -	std::string name; -	BOOL enabled; +	std::string name = ""; +	 +	// Enable the copy || copy & wear buttons only if we have something we can copy or copy & wear (respectively). +	bool copy_enabled = false; +	bool wear_enabled = false;  	LLSelectNode* node = mObjectSelection->getFirstRootNode(); -	if (node) +	if (node)   	{  		name = node->mName; -		enabled = TRUE; -	} -	else -	{ -		name = ""; -		enabled = FALSE; +		copy_enabled = true; +		 +		LLViewerObject* object = node->getObject(); +		if (object) +		{ +			// this folder is coming from an object, as there is only one folder in an object, the root, +			// we need to collect the entire contents and handle them as a group +			InventoryObjectList inventory_objects; +			object->getInventoryContents(inventory_objects); +			 +			if (!inventory_objects.empty()) +			{ +				for (InventoryObjectList::iterator it = inventory_objects.begin();  +					 it != inventory_objects.end();  +					 ++it) +				{ +					LLInventoryItem* item = static_cast<LLInventoryItem*> ((LLInventoryObject*)(*it)); +					LLInventoryType::EType type = item->getInventoryType(); +					if (type == LLInventoryType::IT_OBJECT  +						|| type == LLInventoryType::IT_ATTACHMENT  +						|| type == LLInventoryType::IT_WEARABLE +						|| type == LLInventoryType::IT_GESTURE) +					{ +						wear_enabled = true; +						break; +					} +				} +			} +		}  	}  	childSetTextArg("object_name", "[DESC]", name); -	childSetEnabled("copy_to_inventory_button", enabled); -	childSetEnabled("copy_and_wear_button", enabled); +	childSetEnabled("copy_to_inventory_button", copy_enabled); +	childSetEnabled("copy_and_wear_button", wear_enabled);  } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index d08d47bc81..7fb71d4d4f 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/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e361082f7b..ab06ac1691 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -973,7 +973,7 @@ bool LLInvFVBridge::isInOutfitsSidePanel() const  		dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));  	if (!outfit_panel)  		return false; -	return outfit_panel->isAccordionPanel(my_panel); +	return outfit_panel->isTabPanel(my_panel);  }  // +=================================================+ diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5d8a8805b5..0a8108899a 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -59,7 +59,8 @@  BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;  BOOL LLInventoryModel::sAllFoldersFetched = FALSE; -BOOL LLInventoryModel::sFullFetchStarted = FALSE; +BOOL LLInventoryModel::sMyInventoryFetchStarted = FALSE; +BOOL LLInventoryModel::sLibraryFetchStarted = FALSE;  S32  LLInventoryModel::sNumFetchRetries = 0;  F32  LLInventoryModel::sMinTimeBetweenFetches = 0.3f;  F32  LLInventoryModel::sMaxTimeBetweenFetches = 10.f; @@ -1342,11 +1343,11 @@ bool LLInventoryModel::isBulkFetchProcessingComplete()  			&& sBulkFetchCount<=0)  ?  TRUE : FALSE ) ;  } -class fetchDescendentsResponder: public LLHTTPClient::Responder +class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder  {  	public: -		fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; -		//fetchDescendentsResponder() {}; +		LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; +		//LLInventoryModelFetchDescendentsResponder() {};  		void result(const LLSD& content);  		void error(U32 status, const std::string& reason);  	public: @@ -1356,7 +1357,7 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder  };  //If we get back a normal response, handle it here -void  fetchDescendentsResponder::result(const LLSD& content) +void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  {  	if (content.has("folders"))	  	{ @@ -1423,7 +1424,8 @@ void  fetchDescendentsResponder::result(const LLSD& content)  				LLSD category = *category_it;  				tcategory->fromLLSD(category);  -				if (LLInventoryModel::sFullFetchStarted) +				if (LLInventoryModel::sMyInventoryFetchStarted || +					LLInventoryModel::sLibraryFetchStarted)  				{  					sFetchQueue.push_back(tcategory->getUUID());  				} @@ -1475,20 +1477,16 @@ void  fetchDescendentsResponder::result(const LLSD& content)  	if (LLInventoryModel::isBulkFetchProcessingComplete())  	{  		llinfos << "Inventory fetch completed" << llendl; -		if (LLInventoryModel::sFullFetchStarted) -		{ -			LLInventoryModel::sAllFoldersFetched = TRUE; -		} -		LLInventoryModel::stopBackgroundFetch(); +		LLInventoryModel::setAllFoldersFetched();  	}  	gInventory.notifyObservers("fetchDescendents");  }  //If we get back an error (not found, etc...), handle it here -void fetchDescendentsResponder::error(U32 status, const std::string& reason) +void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)  { -	llinfos << "fetchDescendentsResponder::error " +	llinfos << "LLInventoryModelFetchDescendentsResponder::error "  		<< status << ": " << reason << llendl;  	LLInventoryModel::incrBulkFetch(-1); @@ -1508,11 +1506,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason)  	{  		if (LLInventoryModel::isBulkFetchProcessingComplete())  		{ -			if (LLInventoryModel::sFullFetchStarted) -			{ -				LLInventoryModel::sAllFoldersFetched = TRUE; -			} -			LLInventoryModel::stopBackgroundFetch(); +			LLInventoryModel::setAllFoldersFetched();  		}  	}  	gInventory.notifyObservers("fetchDescendents"); @@ -1580,7 +1574,8 @@ void LLInventoryModel::bulkFetch(std::string url)  					    body["folders"].append(folder_sd);  				    folder_count++;  			    } -			    if (sFullFetchStarted) +			    if (sMyInventoryFetchStarted || +					sLibraryFetchStarted)  			    {	//Already have this folder but append child folders to list.  				    // add all children to queue  				    parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); @@ -1605,22 +1600,18 @@ void LLInventoryModel::bulkFetch(std::string url)  			sBulkFetchCount++;  			if (body["folders"].size())  			{ -				LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0); +				LLHTTPClient::post(url, body, new LLInventoryModelFetchDescendentsResponder(body),300.0);  			}  			if (body_lib["folders"].size())  			{  				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); -				LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0); +				LLHTTPClient::post(url_lib, body_lib, new LLInventoryModelFetchDescendentsResponder(body_lib),300.0);  			}  			sFetchTimer.reset();  		}  	else if (isBulkFetchProcessingComplete())  	{ -		if (sFullFetchStarted) -		{ -			sAllFoldersFetched = TRUE; -		} -		stopBackgroundFetch(); +		setAllFoldersFetched();  	}	  } @@ -1636,7 +1627,6 @@ BOOL LLInventoryModel::backgroundFetchActive()  	return sBackgroundFetchActive;  } -//static   void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)  {  	if (!sAllFoldersFetched) @@ -1644,9 +1634,16 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)  		sBackgroundFetchActive = TRUE;  		if (cat_id.isNull())  		{ -			if (!sFullFetchStarted) +			if (!sMyInventoryFetchStarted)  			{ -				sFullFetchStarted = TRUE; +				sMyInventoryFetchStarted = TRUE; +				sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); +				sFetchQueue.push_back(gInventory.getRootFolderID()); +				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); +			} +			if (!sLibraryFetchStarted) +			{ +				sLibraryFetchStarted = TRUE;  				sFetchQueue.push_back(gInventory.getLibraryRootFolderID());  				sFetchQueue.push_back(gInventory.getRootFolderID());  				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); @@ -1660,6 +1657,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)  				sFetchQueue.push_front(cat_id);  				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);  			} +			if (cat_id == gInventory.getLibraryRootFolderID()) +			{ +				sLibraryFetchStarted = TRUE; +			} +			if (cat_id == gInventory.getRootFolderID()) +			{ +				sMyInventoryFetchStarted = TRUE; +			}  		}  	}  } @@ -1681,10 +1686,20 @@ void LLInventoryModel::stopBackgroundFetch()  		gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);  		sBulkFetchCount=0;  		sMinTimeBetweenFetches=0.0f; -//		sFullFetchStarted=FALSE;  	}  } +// static +void LLInventoryModel::setAllFoldersFetched() +{ +	if (sMyInventoryFetchStarted && +		sLibraryFetchStarted) +	{ +		sAllFoldersFetched = TRUE; +	} +	stopBackgroundFetch(); +} +  //static   void LLInventoryModel::backgroundFetch(void*)  { @@ -1703,11 +1718,8 @@ void LLInventoryModel::backgroundFetch(void*)  		if (sFetchQueue.empty())  		{  			llinfos << "Inventory fetch completed" << llendl; -			if (sFullFetchStarted) -			{ -				sAllFoldersFetched = TRUE; -			} -			stopBackgroundFetch(); + +			setAllFoldersFetched();  			return;  		} diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b744d821c7..27bbca493d 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -72,6 +72,8 @@ class LLInventoryCollectFunctor;  class LLInventoryModel  {  public: +	friend class LLInventoryModelFetchDescendentsResponder; +  	enum EHasChildren  	{  		CHILDREN_NO, @@ -282,9 +284,6 @@ public:  	// Make sure we have the descendents in the structure.  Returns true  	// if a fetch was performed.  	bool fetchDescendentsOf(const LLUUID& folder_id); -	 -	// Add categories to a list to be fetched in bulk. -	static void bulkFetch(std::string url);  	// call this method to request the inventory.  	//void requestFromServer(const LLUUID& agent_id); @@ -369,15 +368,7 @@ public:  	// Utility Functions  	void removeItem(const LLUUID& item_id); -	// start and stop background breadth-first fetching of inventory contents -	// this gets triggered when performing a filter-search -	static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process      static void findLostItems(); -	static BOOL backgroundFetchActive(); -	static bool isEverythingFetched(); -	static void backgroundFetch(void*); // background fetch idle function -	static void incrBulkFetch(S16 fetching) {  sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; } -  	// Data about the agent's root folder and root library folder  	// are stored here, rather than in LLAgent where it used to be, because @@ -477,14 +468,11 @@ private:  	LLUUID mLibraryRootFolderID;  	LLUUID mLibraryOwnerID; -	// completing the fetch once per session should be sufficient -	static BOOL sBackgroundFetchActive;  	static BOOL sTimelyFetchPending;  	static S32  sNumFetchRetries;  	static LLFrameTimer sFetchTimer;  	static F32 sMinTimeBetweenFetches;  	static F32 sMaxTimeBetweenFetches; -	static S16 sBulkFetchCount;  	// Expected inventory cache version  	const static S32 sCurrentInvCacheVersion; @@ -510,11 +498,33 @@ private:  public:  	// *NOTE: DEBUG functionality  	void dumpInventory() const; -	static bool isBulkFetchProcessingComplete(); + +	//////////////////////////////////////////////////////////////////////////////// +	// Bulk / Background Fetch + +public: +	// Start and stop background breadth-first fetching of inventory contents. +	// This gets triggered when performing a filter-search +	void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); +	static BOOL backgroundFetchActive(); +	static bool isEverythingFetched(); +	static void backgroundFetch(void*); // background fetch idle function +	static void incrBulkFetch(S16 fetching) {  sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }  	static void stopBackgroundFetch(); // stop fetch process +	static bool isBulkFetchProcessingComplete(); + +	// Add categories to a list to be fetched in bulk. +	static void bulkFetch(std::string url); -	static BOOL sFullFetchStarted; +private: + 	static BOOL sMyInventoryFetchStarted; +	static BOOL sLibraryFetchStarted;  	static BOOL sAllFoldersFetched;  +	static void setAllFoldersFetched(); + +	// completing the fetch once per session should be sufficient +	static BOOL sBackgroundFetchActive; +	static S16 sBulkFetchCount;  };  // a special inventory model for the agent diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 3c337961e1..2694075a58 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -58,251 +58,342 @@  // - Any request that gets a 503 still goes through the retry logic  // +// +// Forward decls +//  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; + +// << operators +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q); +std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q);  //////////////////////////////////////////////////////////////////////////////////////  // -// 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 ); +	return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue;  } -// 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;	    -} - -////////////////////////////////////////////////////////////////////////////////////// -// -// 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 +409,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 +417,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 +432,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 +691,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 +703,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 +720,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/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index cef21e85d6..c0da8f3daa 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -530,11 +530,23 @@ BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	return handled;  } -void LLPanelMainInventory::changed(U32 mask) +// virtual +void LLPanelMainInventory::changed(U32)  { +	// empty, but must have this defined for abstract base class.  } +// virtual +void LLPanelMainInventory::draw() +{ +	if (mActivePanel && mFilterEditor) +	{ +		mFilterEditor->setText(mActivePanel->getFilterSubString()); +	}	 +	LLPanel::draw(); +} +  void LLPanelMainInventory::setFilterTextFromFilter()   {   	mFilterText = mActivePanel->getFilter()->getFilterText();  diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 92443df369..920de2665c 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -72,7 +72,8 @@ public:  									   void* cargo_data,  									   EAcceptance* accept,  									   std::string& tooltip_msg); -	/*virtual*/ void changed(U32 mask); +	/*virtual*/ void changed(U32); +	/*virtual*/ void draw();  	LLInventoryPanel* getPanel() { return mActivePanel; }  	LLInventoryPanel* getActivePanel() { return mActivePanel; } 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/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 4511bca23a..5b36a5406a 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -75,12 +75,12 @@ LLPanelOutfitsInventory::~LLPanelOutfitsInventory()  BOOL LLPanelOutfitsInventory::postBuild()  { -	initAccordionPanels(); +	initTabPanels();  	initListCommandsHandlers();  	return TRUE;  } -void LLPanelOutfitsInventory::updateParent() +void LLPanelOutfitsInventory::updateVerbs()  {  	if (mParent)  	{ @@ -127,7 +127,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)  	mActivePanel->setFilterSubString(string);  } -void LLPanelOutfitsInventory::onWear() +void LLPanelOutfitsInventory::onWearButtonClick()  {  	LLFolderViewEventListener* listenerp = getCorrectListenerForAction();  	if (listenerp) @@ -167,7 +167,7 @@ void LLPanelOutfitsInventory::onNew()  void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)  {  	updateListCommands(); -	updateParent(); +	updateVerbs();  	if (getRootFolder()->needsAutoRename() && items.size())  	{  		getRootFolder()->startRenamingSelectedItem(); @@ -234,13 +234,14 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()  	mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));  	mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));  	mListCommands->childSetAction("add_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this)); - +	mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this)); +	  	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");  	trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this -			,	_4 // BOOL drop -			,	_5 // EDragAndDropType cargo_type -			,	_7 // EAcceptance* accept -			)); +				   ,       _4 // BOOL drop +				   ,       _5 // EDragAndDropType cargo_type +				   ,       _7 // EAcceptance* accept +				   ));  	mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action",  								 boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2)); @@ -252,8 +253,10 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()  void LLPanelOutfitsInventory::updateListCommands()  {  	bool trash_enabled = isActionEnabled("delete"); +	bool wear_enabled = isActionEnabled("wear");  	mListCommands->childSetEnabled("trash_btn", trash_enabled); +	mListCommands->childSetEnabled("wear_btn", wear_enabled);  }  void LLPanelOutfitsInventory::onGearButtonClick() @@ -308,7 +311,7 @@ void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata)  	}  	if (command_name == "wear")  	{ -		onWear(); +		onWearButtonClick();  	}  	if (command_name == "add")  	{ @@ -407,41 +410,41 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy  ////////////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////////////// -// Accordion                                                                    // +// Tab panels                                                                    // -void LLPanelOutfitsInventory::initAccordionPanels() +void LLPanelOutfitsInventory::initTabPanels()  { -	mAccordionPanels.resize(2); +	mTabPanels.resize(2);  	LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>("outfitslist_accordionpanel");  	myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY);  	myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -	mAccordionPanels[0] = myoutfits_panel; +	mTabPanels[0] = myoutfits_panel;  	mActivePanel = myoutfits_panel;  	LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>("cof_accordionpanel");  	cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -	mAccordionPanels[1] = cof_panel; +	mTabPanels[1] = cof_panel; -	for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin(); -		 iter != mAccordionPanels.end(); +	for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); +		 iter != mTabPanels.end();  		 ++iter)  	{  		LLInventoryPanel *panel = (*iter); -		panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onAccordionSelectionChange, this, panel, _1, _2)); +		panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, panel, _1, _2));  	}  } -void LLPanelOutfitsInventory::onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action)  {  	if (user_action && items.size() > 0)  	{ -		for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin(); -			 iter != mAccordionPanels.end(); +		for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); +			 iter != mTabPanels.end();  			 ++iter)  		{  			LLInventoryPanel *panel = (*iter); -			if (panel == accordion_panel) +			if (panel == tab_panel)  			{  				mActivePanel = panel;  			} @@ -459,10 +462,10 @@ LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel()  	return mActivePanel;  } -bool LLPanelOutfitsInventory::isAccordionPanel(LLInventoryPanel *panel) +bool LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel)  { -	for(accordionpanels_vec_t::iterator it = mAccordionPanels.begin(); -		it != mAccordionPanels.end(); +	for(tabpanels_vec_t::iterator it = mTabPanels.begin(); +		it != mTabPanels.end();  		++it)  	{  		if (*it == panel) diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index afeaef485d..9b6b483e3b 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -54,7 +54,6 @@ public:  	/*virtual*/ BOOL postBuild();  	void onSearchEdit(const std::string& string); -	void onWear();  	void onAdd();  	void onRemove();  	void onEdit(); @@ -71,29 +70,30 @@ public:  	LLFolderView* getRootFolder();  protected: -	void updateParent(); +	void updateVerbs();  	bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const;  private:  	LLSidepanelAppearance*      mParent;  	LLSaveFolderState*			mSavedFolderState; +  public:  	////////////////////////////////////////////////////////////////////////////////// -	// Accordion                                                                    // +	// tab panels  	LLInventoryPanel* 	getActivePanel(); -	bool isAccordionPanel(LLInventoryPanel *panel); +	bool isTabPanel(LLInventoryPanel *panel);  protected: -	void 				initAccordionPanels(); -	void 				onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	void 				initTabPanels(); +	void 				onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);  private:  	LLInventoryPanel* 	mActivePanel; -	typedef std::vector<LLInventoryPanel *> accordionpanels_vec_t; -	accordionpanels_vec_t 		mAccordionPanels; +	typedef std::vector<LLInventoryPanel *> tabpanels_vec_t; +	tabpanels_vec_t 		mTabPanels; -	// Accordion                                                                  // +	// tab panels                                                               //  	//////////////////////////////////////////////////////////////////////////////// @@ -103,6 +103,7 @@ protected:  	void initListCommandsHandlers();  	void updateListCommands();  	void onGearButtonClick(); +	void onWearButtonClick();  	void onAddButtonClick();  	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);  	void onTrashButtonClick(); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 59a68bc12d..7d21867efc 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -37,6 +37,7 @@  #include "llagent.h"  #include "llagentpicksinfo.h"  #include "llavatarconstants.h" +#include "llcommandhandler.h"  #include "llflatlistview.h"  #include "llfloaterreg.h"  #include "llfloaterworldmap.h" @@ -55,6 +56,8 @@  #include "llpanelprofile.h"  #include "llpanelpick.h"  #include "llpanelclassified.h" +#include "llpanelprofileview.h" +#include "llsidetray.h"  static const std::string XML_BTN_NEW = "new_btn";  static const std::string XML_BTN_DELETE = "trash_btn"; @@ -72,6 +75,83 @@ static const std::string CLASSIFIED_NAME("classified_name");  static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks"); +class LLClassifiedHandler : +	public LLCommandHandler, +	public LLAvatarPropertiesObserver +{ +public: +	// throttle calls from untrusted browsers +	LLClassifiedHandler() :	LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} + +	std::set<LLUUID> mClassifiedIds; + +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +	{ +		if (params.size() < 2) +		{ +			return false; +		} + +		// get the ID for the classified +		LLUUID classified_id; +		if (!classified_id.set(params[0], FALSE)) +		{ +			return false; +		} + +		// show the classified in the side tray. +		// need to ask the server for more info first though... +		const std::string verb = params[1].asString(); +		if (verb == "about") +		{ +			mClassifiedIds.insert(classified_id); +			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); +			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); +			return true; +		} + +		return false; +	} + +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) +	{ +		if (APT_CLASSIFIED_INFO != type) +		{ +			return; +		} + +		// is this the classified that we asked for? +		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); +		if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) +		{ +			return; +		} + +		// open the people profile page for the classified's owner +		LLSD params; +		params["id"] = c_info->creator_id; +		params["classified"] = c_info->classified_id; +		params["open_tab_name"] = "panel_profile"; +		LLPanelProfileView *profile = dynamic_cast<LLPanelProfileView*>(LLSideTray::getInstance()->showPanel("panel_profile_view", params)); + +		// then open the classified panel on this user's profile panel +		if (profile) +		{ +			LLPanelPicks* panel_picks = profile->getChild<LLPanelPicks>("panel_picks"); +			if (panel_picks) +			{ +				panel_picks->openClassifiedInfo(c_info); +			} +		} + +		// remove our observer now that we're done +		mClassifiedIds.erase(c_info->classified_id); +		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); +	} + +}; +LLClassifiedHandler gClassifiedHandler; +  //////////////////////////////////////////////////////////////////////////  /** @@ -624,6 +704,25 @@ void LLPanelPicks::openClassifiedInfo()  	getProfilePanel()->openPanel(mPanelClassifiedInfo, params);  } +void LLPanelPicks::openClassifiedInfo(LLAvatarClassifiedInfo *c_info) +{ +	if (! c_info) +	{ +		return; +	} + +	createClassifiedInfoPanel(); + +	LLSD params; +	params["classified_id"] = c_info->classified_id; +	params["avatar_id"] = c_info->creator_id; +	params["snapshot_id"] = c_info->snapshot_id; +	params["name"] = c_info->name; +	params["desc"] = c_info->description; + +	getProfilePanel()->openPanel(mPanelClassifiedInfo, params); +} +  void LLPanelPicks::showAccordion(const std::string& name, bool show)  {  	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 21794d56b2..893a0c53a3 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -86,6 +86,9 @@ public:  	// parent panels failed to work (picks related code was in my profile panel)  	void setProfilePanel(LLPanelProfile* profile_panel); +	// display the info panel for the given classified +	void openClassifiedInfo(LLAvatarClassifiedInfo *c_info); +  protected:  	/*virtual*/void updateButtons(); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index e21eb01da3..685104a8b1 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -54,6 +54,7 @@  #include "llavatarpropertiesprocessor.h"  #include "llfloaterworldmap.h"  #include "llinventorybridge.h" +#include "llinventoryobserver.h"  #include "llinventorymodel.h"  #include "lllandmarkactions.h"  #include "lllandmarklist.h" @@ -62,6 +63,7 @@  #include "llpanelpick.h"  #include "llpanelplaceprofile.h"  #include "llpanelteleporthistory.h" +#include "llremoteparcelrequest.h"  #include "llteleporthistorystorage.h"  #include "lltoggleablemenu.h"  #include "llviewerinventory.h" @@ -85,8 +87,10 @@ static void onSLURLBuilt(std::string& slurl);  class LLPlacesParcelObserver : public LLParcelObserver  {  public: -	LLPlacesParcelObserver(LLPanelPlaces* places_panel) -	: mPlaces(places_panel) {} +	LLPlacesParcelObserver(LLPanelPlaces* places_panel) : +		LLParcelObserver(), +		mPlaces(places_panel) +	{}  	/*virtual*/ void changed()  	{ @@ -101,8 +105,10 @@ private:  class LLPlacesInventoryObserver : public LLInventoryObserver  {  public: -	LLPlacesInventoryObserver(LLPanelPlaces* places_panel) -	: mPlaces(places_panel) {} +	LLPlacesInventoryObserver(LLPanelPlaces* places_panel) : +		LLInventoryObserver(), +		mPlaces(places_panel) +	{}  	/*virtual*/ void changed(U32 mask)  	{ @@ -114,6 +120,59 @@ private:  	LLPanelPlaces*		mPlaces;  }; +class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver +{ +public: +	LLPlacesRemoteParcelInfoObserver(LLPanelPlaces* places_panel) : +		LLRemoteParcelInfoObserver(), +		mPlaces(places_panel) +	{} + +	~LLPlacesRemoteParcelInfoObserver() +	{ +		// remove any in-flight observers +		std::set<LLUUID>::iterator it; +		for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it) +		{ +			const LLUUID &id = *it; +			LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this); +		} +		mParcelIDs.clear(); +	} + +	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data) +	{ +		if (mPlaces) +		{ +			mPlaces->changedGlobalPos(LLVector3d(parcel_data.global_x, +												 parcel_data.global_y, +												 parcel_data.global_z)); +		} + +		mParcelIDs.erase(parcel_data.parcel_id); +		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this); +	} +	/*virtual*/ void setParcelID(const LLUUID& parcel_id) +	{ +		if (!parcel_id.isNull()) +		{ +			mParcelIDs.insert(parcel_id); +			LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); +			LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); +		} +	} +	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason) +	{ +		llerrs << "Can't complete remote parcel request. Http Status: " +			   << status << ". Reason : " << reason << llendl; +	} + +private: +	std::set<LLUUID>	mParcelIDs; +	LLPanelPlaces*		mPlaces; +}; + +  static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places");  LLPanelPlaces::LLPanelPlaces() @@ -131,6 +190,7 @@ LLPanelPlaces::LLPanelPlaces()  {  	mParcelObserver = new LLPlacesParcelObserver(this);  	mInventoryObserver = new LLPlacesInventoryObserver(this); +	mRemoteParcelObserver = new LLPlacesRemoteParcelInfoObserver(this);  	gInventory.addObserver(mInventoryObserver); @@ -149,6 +209,7 @@ LLPanelPlaces::~LLPanelPlaces()  	delete mInventoryObserver;  	delete mParcelObserver; +	delete mRemoteParcelObserver;  }  BOOL LLPanelPlaces::postBuild() @@ -239,7 +300,6 @@ void LLPanelPlaces::onOpen(const LLSD& key)  	mItem = NULL;  	isLandmarkEditModeOn = false;  	togglePlaceInfoPanel(TRUE); -	updateVerbs();  	if (mPlaceInfoType == AGENT_INFO_TYPE)  	{ @@ -282,6 +342,10 @@ void LLPanelPlaces::onOpen(const LLSD& key)  		{  			LLUUID parcel_id = key["id"].asUUID();  			mPlaceProfile->setParcelID(parcel_id); + +			// query the server to get the global 3D position of this +			// parcel - we need this for teleport/mapping functions. +			mRemoteParcelObserver->setParcelID(parcel_id);  		}  		else  		{ @@ -306,6 +370,8 @@ void LLPanelPlaces::onOpen(const LLSD& key)  		mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);  	} +	updateVerbs(); +  	LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();  	if (!parcel_mgr)  		return; @@ -837,6 +903,12 @@ void LLPanelPlaces::changedInventory(U32 mask)  	gInventory.removeObserver(mInventoryObserver);  } +void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos) +{ +	mPosGlobal = global_pos; +	updateVerbs(); +} +  void LLPanelPlaces::updateVerbs()  {  	bool is_place_info_visible; @@ -853,6 +925,7 @@ void LLPanelPlaces::updateVerbs()  	bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;  	bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; +	bool have_3d_pos = ! mPosGlobal.isExactlyZero();  	mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);  	mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); @@ -862,7 +935,7 @@ void LLPanelPlaces::updateVerbs()  	mCancelBtn->setVisible(isLandmarkEditModeOn);  	mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); -	mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn); +	mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);  	mOverflowBtn->setEnabled(is_place_info_visible && !is_create_landmark_visible);  	if (is_place_info_visible) @@ -871,12 +944,12 @@ void LLPanelPlaces::updateVerbs()  		{  			// We don't need to teleport to the current location  			// so check if the location is not within the current parcel. -			mTeleportBtn->setEnabled(!mPosGlobal.isExactlyZero() && +			mTeleportBtn->setEnabled(have_3d_pos &&  									 !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));  		}  		else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)  		{ -			mTeleportBtn->setEnabled(TRUE); +			mTeleportBtn->setEnabled(have_3d_pos);  		}  	}  	else diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 5f9aed6357..5ee8704992 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -47,6 +47,7 @@ class LLPanelPlacesTab;  class LLParcelSelection;  class LLPlacesInventoryObserver;  class LLPlacesParcelObserver; +class LLRemoteParcelInfoObserver;  class LLTabContainer;  class LLToggleableMenu; @@ -65,6 +66,8 @@ public:  	void changedParcelSelection();  	// Called on agent inventory change to find out when inventory gets usable.  	void changedInventory(U32 mask); +	// Called when we receive the global 3D position of a parcel. +	void changedGlobalPos(const LLVector3d &global_pos);  	void setItem(LLInventoryItem* item); @@ -112,6 +115,7 @@ private:  	LLPlacesInventoryObserver*	mInventoryObserver;  	LLPlacesParcelObserver*		mParcelObserver; +	LLRemoteParcelInfoObserver* mRemoteParcelObserver;  	// Pointer to a landmark item or to a linked landmark  	LLPointer<LLInventoryItem>	mItem; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index aa2b7d4554..3fe51106e4 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -150,7 +150,7 @@ BOOL LLPanelPrimMediaControls::postBuild()  	mSkipFwdCtrl			= getChild<LLUICtrl>("skip_forward");  	mSkipBackCtrl			= getChild<LLUICtrl>("skip_back");  	mVolumeCtrl				= getChild<LLUICtrl>("media_volume"); -	mVolumeBtn				= getChild<LLButton>("media_volume_button"); +	mMuteBtn				= getChild<LLButton>("media_mute_button");  	mVolumeUpCtrl			= getChild<LLUICtrl>("volume_up");  	mVolumeDownCtrl			= getChild<LLUICtrl>("volume_down");  	mVolumeSliderCtrl       = getChild<LLSliderCtrl>("volume_slider"); @@ -200,7 +200,7 @@ BOOL LLPanelPrimMediaControls::postBuild()  		mScrollDownCtrl->setHeldDownCallback(onScrollDownHeld, this);  		mScrollDownCtrl->setMouseUpCallback(onScrollStop, this);  	} -	 +		  	mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));  	mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");  	mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); @@ -215,11 +215,15 @@ void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S  {  	if (media_impl.notNull() && objectp.notNull())  	{ +		LLUUID prev_id = mTargetImplID;  		mTargetImplID = media_impl->getMediaTextureID();  		mTargetObjectID = objectp->getID();  		mTargetObjectFace = face;  		mTargetObjectNormal = pick_normal;  		mClearFaceOnFade = false; +		 +		if (prev_id != mTargetImplID) +			mVolumeSliderCtrl->setValue(media_impl->getVolume());  	}  	else  	{ @@ -308,13 +312,12 @@ void LLPanelPrimMediaControls::updateShape()  			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);  			mini_controls = (LLMediaEntry::MINI == media_data->getControls());  		} -		  		const bool is_hud = objectp->isHUDAttachment();  		//  		// Set the state of the buttons  		// -				 +		  		// XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,  		// and that only the proper controls get made visible/enabled according to that mode.   		mBackCtrl->setVisible(has_focus); @@ -343,7 +346,7 @@ void LLPanelPrimMediaControls::updateShape()  		mStopCtrl->setEnabled(has_focus && can_navigate);  		mHomeCtrl->setEnabled(has_focus && can_navigate);  		LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE; - +		  		if(media_plugin && media_plugin->pluginSupportsMediaTime())  		{  			mReloadCtrl->setEnabled(false); @@ -360,14 +363,14 @@ void LLPanelPrimMediaControls::updateShape()  			mSkipFwdCtrl->setEnabled(has_focus && !mini_controls);  			mSkipBackCtrl->setVisible(has_focus && !mini_controls);  			mSkipBackCtrl->setEnabled(has_focus && !mini_controls); -				 +			  			mVolumeCtrl->setVisible(has_focus);  			mVolumeUpCtrl->setVisible(has_focus);  			mVolumeDownCtrl->setVisible(has_focus);  			mVolumeCtrl->setEnabled(has_focus);  			mVolumeSliderCtrl->setEnabled(has_focus && mVolumeSliderVisible);  			mVolumeSliderCtrl->setVisible(has_focus && mVolumeSliderVisible); - +			  			mWhitelistIcon->setVisible(false);  			mSecureLockIcon->setVisible(false);  			if (mMediaPanelScroll) @@ -378,7 +381,7 @@ void LLPanelPrimMediaControls::updateShape()  				mScrollRightCtrl->setVisible(false);  				mScrollDownCtrl->setVisible(false);  			} -				 +			  			F32 volume = media_impl->getVolume();  			// movie's url changed  			if(mCurrentURL!=mPreviousURL) @@ -386,7 +389,7 @@ void LLPanelPrimMediaControls::updateShape()  				mMovieDuration = media_plugin->getDuration();  				mPreviousURL = mCurrentURL;  			} -				 +			  			if(mMovieDuration == 0)   			{  				mMovieDuration = media_plugin->getDuration(); @@ -394,7 +397,7 @@ void LLPanelPrimMediaControls::updateShape()  				mMediaPlaySliderCtrl->setEnabled(false);  			}  			// TODO: What if it's not fully loaded -					 +			  			if(mUpdateSlider && mMovieDuration!= 0)  			{  				F64 current_time =  media_plugin->getCurrentTime(); @@ -402,29 +405,27 @@ void LLPanelPrimMediaControls::updateShape()  				mMediaPlaySliderCtrl->setValue(percent);  				mMediaPlaySliderCtrl->setEnabled(true);  			} -				 +			  			// video vloume  			if(volume <= 0.0)  			{  				mVolumeUpCtrl->setEnabled(TRUE);  				mVolumeDownCtrl->setEnabled(FALSE); -				media_impl->setVolume(0.0); -				mVolumeBtn->setToggleState(true); +				mMuteBtn->setToggleState(true);  			}  			else if (volume >= 1.0)  			{  				mVolumeUpCtrl->setEnabled(FALSE);  				mVolumeDownCtrl->setEnabled(TRUE); -				media_impl->setVolume(1.0); -				mVolumeBtn->setToggleState(false); +				mMuteBtn->setToggleState(false);  			}  			else  			{ +				mMuteBtn->setToggleState(false);  				mVolumeUpCtrl->setEnabled(TRUE);  				mVolumeDownCtrl->setEnabled(TRUE);  			} -			mVolumeSliderCtrl->setValue(volume); -				 +			  			switch(result)  			{  				case LLPluginClassMediaOwner::MEDIA_PLAYING: @@ -453,7 +454,7 @@ void LLPanelPrimMediaControls::updateShape()  			{  				mCurrentURL.clear();  			} -				 +			  			mPlayCtrl->setVisible(FALSE);  			mPauseCtrl->setVisible(FALSE);  			mMediaStopCtrl->setVisible(FALSE); @@ -465,7 +466,7 @@ void LLPanelPrimMediaControls::updateShape()  			mSkipFwdCtrl->setEnabled(FALSE);  			mSkipBackCtrl->setVisible(FALSE);  			mSkipBackCtrl->setEnabled(FALSE); -				 +			  			mVolumeCtrl->setVisible(FALSE);  			mVolumeUpCtrl->setVisible(FALSE);  			mVolumeDownCtrl->setVisible(FALSE); @@ -491,13 +492,13 @@ void LLPanelPrimMediaControls::updateShape()  			{  				mSecureLockIcon->setVisible(has_focus);  			} -				 +			  			if(mCurrentURL!=mPreviousURL)  			{  				setCurrentURL();  				mPreviousURL = mCurrentURL;  			} - +			  			if(result == LLPluginClassMediaOwner::MEDIA_LOADING)  			{  				mReloadCtrl->setEnabled(FALSE); @@ -513,7 +514,7 @@ void LLPanelPrimMediaControls::updateShape()  				mStopCtrl->setVisible(FALSE);  			}  		} - +		  		if(media_plugin)  		{ @@ -530,7 +531,7 @@ void LLPanelPrimMediaControls::updateShape()  				mMediaProgressPanel->setVisible(false);  			}  		} - +		  		if(media_impl)  		{  			// @@ -538,28 +539,28 @@ void LLPanelPrimMediaControls::updateShape()  			//  			switch (mScrollState)   			{ -			case SCROLL_UP: -				media_impl->scrollWheel(0, -1, MASK_NONE); -				break; -			case SCROLL_DOWN: -				media_impl->scrollWheel(0, 1, MASK_NONE); -				break; -			case SCROLL_LEFT: -				media_impl->scrollWheel(1, 0, MASK_NONE); -//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); -				break; -			case SCROLL_RIGHT: -				media_impl->scrollWheel(-1, 0, MASK_NONE); -//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); -				break; -			case SCROLL_NONE: -			default: -				break; +				case SCROLL_UP: +					media_impl->scrollWheel(0, -1, MASK_NONE); +					break; +				case SCROLL_DOWN: +					media_impl->scrollWheel(0, 1, MASK_NONE); +					break; +				case SCROLL_LEFT: +					media_impl->scrollWheel(1, 0, MASK_NONE); +					//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); +					break; +				case SCROLL_RIGHT: +					media_impl->scrollWheel(-1, 0, MASK_NONE); +					//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); +					break; +				case SCROLL_NONE: +				default: +					break;  			}  		}  		setVisible(enabled); - +		  		//  		// Calculate position and shape of the controls  		// @@ -569,31 +570,31 @@ void LLPanelPrimMediaControls::updateShape()  		std::vector<LLVector3>::iterator vert_it;  		std::vector<LLVector3>::iterator vert_end;  		std::vector<LLVector3> vect_face; -			 +		  		LLVolume* volume = objectp->getVolume(); -			 +		  		if (volume)  		{  			const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace); -				 +			  			const LLVector3* ext = vf.mExtents; -				 +			  			LLVector3 center = (ext[0]+ext[1])*0.5f;  			LLVector3 size = (ext[1]-ext[0])*0.5f;  			LLVector3 vert[] = -				{ -					center + size.scaledVec(LLVector3(1,1,1)), -					center + size.scaledVec(LLVector3(-1,1,1)), -					center + size.scaledVec(LLVector3(1,-1,1)), -					center + size.scaledVec(LLVector3(-1,-1,1)), -					center + size.scaledVec(LLVector3(1,1,-1)), -					center + size.scaledVec(LLVector3(-1,1,-1)), -					center + size.scaledVec(LLVector3(1,-1,-1)), -					center + size.scaledVec(LLVector3(-1,-1,-1)), -				}; -				 +			{ +				center + size.scaledVec(LLVector3(1,1,1)), +				center + size.scaledVec(LLVector3(-1,1,1)), +				center + size.scaledVec(LLVector3(1,-1,1)), +				center + size.scaledVec(LLVector3(-1,-1,1)), +				center + size.scaledVec(LLVector3(1,1,-1)), +				center + size.scaledVec(LLVector3(-1,1,-1)), +				center + size.scaledVec(LLVector3(1,-1,-1)), +				center + size.scaledVec(LLVector3(-1,-1,-1)), +			}; +			  			LLVOVolume* vo = (LLVOVolume*) objectp; -				 +			  			for (U32 i = 0; i < 8; i++)  			{  				vect_face.push_back(vo->volumePositionToAgent(vert[i])); @@ -601,7 +602,7 @@ void LLPanelPrimMediaControls::updateShape()  		}  		vert_it = vect_face.begin();  		vert_end = vect_face.end(); -			 +		  		min = LLVector3(1,1,1);  		max = LLVector3(-1,-1,-1);  		for(; vert_it != vert_end; ++vert_it) @@ -609,19 +610,19 @@ void LLPanelPrimMediaControls::updateShape()  			// project silhouette vertices into screen space  			glh::vec3f screen_vert = glh::vec3f(vert_it->mV);   			mat.mult_matrix_vec(screen_vert); -				 +			  			// add to screenspace bounding box  			update_min_max(min, max, LLVector3(screen_vert.v));  		} -			 +		  		LLCoordGL screen_min;  		screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (min.mV[VX] + 1.f) * 0.5f);  		screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (min.mV[VY] + 1.f) * 0.5f); - +		  		LLCoordGL screen_max;  		screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (max.mV[VX] + 1.f) * 0.5f);  		screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (max.mV[VY] + 1.f) * 0.5f); - +		  		// grow panel so that screenspace bounding box fits inside "media_region" element of HUD  		LLRect media_controls_rect;  		S32 volume_slider_height = mVolumeSliderCtrl->getRect().getHeight() - /*fudge*/ 2; @@ -636,19 +637,19 @@ void LLPanelPrimMediaControls::updateShape()  		// clamp to minimum size, keeping centered  		media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(), -			llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); - +											 llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); +		  		setShape(media_controls_rect, true); - +		  		// Test mouse position to see if the cursor is stationary  		LLCoordWindow cursor_pos_window;  		getWindow()->getCursorPosition(&cursor_pos_window); - +		  		// If last pos is not equal to current pos, the mouse has moved  		// We need to reset the timer, and make sure the panel is visible  		if(cursor_pos_window.mX != mLastCursorPos.mX || -			cursor_pos_window.mY != mLastCursorPos.mY || -			mScrollState != SCROLL_NONE) +		   cursor_pos_window.mY != mLastCursorPos.mY || +		   mScrollState != SCROLL_NONE)  		{  			mInactivityTimer.start();  			mLastCursorPos = cursor_pos_window; @@ -673,7 +674,7 @@ void LLPanelPrimMediaControls::updateShape()  		else  		{  			// I don't think this is correct anymore.  This is done in draw() after the fade has completed. -//			setVisible(FALSE); +			//			setVisible(FALSE);  		}  	}  } @@ -1193,7 +1194,7 @@ void LLPanelPrimMediaControls::onCommitVolumeUp()  		}  		media_impl->setVolume(volume); -		mVolumeBtn->setToggleState(false); +		mMuteBtn->setToggleState(false);  	}  }		 @@ -1213,7 +1214,7 @@ void LLPanelPrimMediaControls::onCommitVolumeDown()  		}  		media_impl->setVolume(volume); -		mVolumeBtn->setToggleState(false); +		mMuteBtn->setToggleState(false);  	}  }		 @@ -1243,7 +1244,7 @@ void LLPanelPrimMediaControls::onToggleMute()  		}  		else   		{ -			media_impl->setVolume(0.5); +			media_impl->setVolume(mVolumeSliderCtrl->getValueF32());  		}  	}  } diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 06163051a5..17e65b8b0c 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -153,7 +153,7 @@ private:  	LLUICtrl *mMediaPlaySliderPanel;  	LLUICtrl *mMediaPlaySliderCtrl;  	LLUICtrl *mVolumeCtrl; -	LLButton *mVolumeBtn; +	LLButton *mMuteBtn;  	LLUICtrl *mVolumeUpCtrl;  	LLUICtrl *mVolumeDownCtrl;  	LLSliderCtrl *mVolumeSliderCtrl; diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index eb3695a371..30b0075c4b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -113,9 +113,6 @@ BOOL LLSidepanelAppearance::postBuild()  	mEditAppearanceBtn = getChild<LLButton>("editappearance_btn");  	mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); -	mWearBtn = getChild<LLButton>("wear_btn"); -	mWearBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onWearButtonClicked, this)); -  	mEditBtn = getChild<LLButton>("edit_btn");  	mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this)); @@ -199,14 +196,6 @@ void LLSidepanelAppearance::onFilterEdit(const std::string& search_string)  	}  } -void LLSidepanelAppearance::onWearButtonClicked() -{ -	if (!mLookInfo->getVisible()) -	{ -		mPanelOutfitsInventory->onWear(); -	} -} -  void LLSidepanelAppearance::onOpenOutfitButtonClicked()  {  	const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getCurrentOutfitLink(); @@ -284,7 +273,6 @@ void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible)  	mLookInfo->setVisible(visible);  	mPanelOutfitsInventory->setVisible(!visible);  	mFilterEditor->setVisible(!visible); -	mWearBtn->setVisible(!visible);  	mEditBtn->setVisible(!visible);  	mNewOutfitBtn->setVisible(!visible);  	mCurrOutfitPanel->setVisible(!visible); @@ -314,12 +302,10 @@ void LLSidepanelAppearance::updateVerbs()  	{  		const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL);  		mEditBtn->setEnabled(is_correct_type); -		mWearBtn->setEnabled(is_correct_type);  	}  	else  	{  		mEditBtn->setEnabled(FALSE); -		mWearBtn->setEnabled(FALSE);  	}  } diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 9c870f631a..8ef2088eda 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -67,7 +67,6 @@ private:  	void onOpenOutfitButtonClicked();  	void onEditAppearanceButtonClicked(); -	void onWearButtonClicked();  	void onEditButtonClicked();  	void onNewOutfitButtonClicked();  	void onBackButtonClicked(); @@ -82,7 +81,6 @@ private:  	LLButton*					mOpenOutfitBtn;  	LLButton*					mEditAppearanceBtn; -	LLButton*					mWearBtn;  	LLButton*					mEditBtn;  	LLButton*					mNewOutfitBtn;  	LLPanel*					mCurrOutfitPanel; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 67007629c0..e29c96bec4 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -311,10 +311,10 @@ public:  		{  			bool success = false;  			bool partial = false; -			if (200 <= status &&  status < 300) +			if (HTTP_OK <= status &&  status < HTTP_MULTIPLE_CHOICES)  			{  				success = true; -				if (203 == status) // partial information (i.e. last block) +				if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block)  				{  					partial = true;  				} diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 78cee15384..8dcd1b8f93 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -519,7 +519,7 @@ bool LLViewerInventoryCategory::fetchDescendents()  		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");  		if (!url.empty()) //Capability found.  Build up LLSD and use it.  		{ -			LLInventoryModel::startBackgroundFetch(mUUID);			 +			gInventory.startBackgroundFetch(mUUID);			  		}  		else  		{	//Deprecated, but if we don't have a capability, use the old system. diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ef8f63484e..57e4ed0c1e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -172,6 +172,11 @@ public:  			completeAny(status, "text/html");  		}  		else +		if(status == 403) +		{ +			completeAny(status, "text/html"); +		} +		else  		if(status == 404)  		{  			// 404 is content not found - sites often have bespoke 404 pages so @@ -240,6 +245,7 @@ public:  		bool mInitialized;  };  static LLViewerMedia::impl_list sViewerMediaImplList; +static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;  static LLTimer sMediaCreateTimer;  static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;  static F32 sGlobalVolume = 1.0f; @@ -297,7 +303,7 @@ viewer_media_t LLViewerMedia::newMediaImpl(  	else  	{  		media_impl->unload(); -		media_impl->mTextureId = texture_id; +		media_impl->setTextureID(texture_id);  		media_impl->mMediaWidth = media_width;  		media_impl->mMediaHeight = media_height;  		media_impl->mMediaAutoScale = media_auto_scale; @@ -412,18 +418,16 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s  // static  LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)  { -	impl_list::iterator iter = sViewerMediaImplList.begin(); -	impl_list::iterator end = sViewerMediaImplList.end(); - -	for(; iter != end; iter++) +	LLViewerMediaImpl* result = NULL; +	 +	// Look up the texture ID in the texture id->impl map. +	impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id); +	if(iter != sViewerMediaTextureIDMap.end())  	{ -		LLViewerMediaImpl* media_impl = *iter; -		if(media_impl->getMediaTextureID() == texture_id) -		{ -			return media_impl; -		} +		result = iter->second;  	} -	return NULL; + +	return result;  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -626,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); +	}  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -827,7 +846,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  :	  	mMediaSource( NULL ),  	mMovieImageHasMips(false), -	mTextureId(texture_id),  	mMediaWidth(media_width),  	mMediaHeight(media_height),  	mMediaAutoScale(media_auto_scale), @@ -857,6 +875,7 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	mProximityDistance(0.0f),  	mMimeTypeProbe(NULL),  	mMediaAutoPlay(false), +	mInNearbyMediaList(false),  	mIsUpdated(false)  {  @@ -868,6 +887,8 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	}  	add_media_impl(this); + +	setTextureID(texture_id);  	// connect this media_impl to the media texture, creating it if it doesn't exist.0  	// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded. @@ -891,6 +912,7 @@ LLViewerMediaImpl::~LLViewerMediaImpl()  	LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ; +	setTextureID();  	remove_media_impl(this);  } @@ -2421,6 +2443,26 @@ LLVOVolume *LLViewerMediaImpl::getSomeObject()  	return result;  } +void LLViewerMediaImpl::setTextureID(LLUUID id) +{ +	if(id != mTextureId) +	{ +		if(mTextureId.notNull()) +		{ +			// Remove this item's entry from the map +			sViewerMediaTextureIDMap.erase(mTextureId); +		} +		 +		if(id.notNull()) +		{ +			sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this)); +		} +		 +		mTextureId = id; +	} +} + +  //////////////////////////////////////////////////////////////////////////////////////////  //static  void LLViewerMedia::toggleMusicPlay(void*) diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 713eb2710b..349a66867a 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -79,6 +79,8 @@ class LLViewerMedia  		typedef std::vector<LLViewerMediaImpl*> impl_list; +		typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map; +  		// Special case early init for just web browser component  		// so we can show login screen.  See .cpp file for details. JC @@ -287,6 +289,8 @@ public:  	LLPluginClassMedia::EPriority getPriority() { return mPriority; };  	void setLowPrioritySizeLimit(int size); + +	void setTextureID(LLUUID id = LLUUID::null);  	typedef enum   	{ @@ -348,6 +352,7 @@ public:  	LLMimeDiscoveryResponder *mMimeTypeProbe;  	bool mMediaAutoPlay;  	std::string mMediaEntryURL; +	bool mInNearbyMediaList;	// used by LLFloaterNearbyMedia::refreshList() for performance reasons  private:  	BOOL mIsUpdated ; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 36d6d2c04b..08e12f4ad9 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 fe4b5488fa..7433404942 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_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 52fda97860..10b72144e7 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -4,7 +4,6 @@   height="420"   layout="topleft"   name="floaterland" - help_topic="floaterland"   save_rect="true"   title="ABOUT LAND"   width="490"> diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 15655a920e..2f26e5d0c1 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -7,7 +7,6 @@   height="460"   layout="topleft"   name="Preferences" - help_topic="preferences"   single_instance="true"   title="PREFERENCES"   width="620"> 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/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index 89492d8abc..439d68282f 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -4,7 +4,6 @@   height="240"   layout="topleft"   name="Water Floater" - help_topic="water_floater"   save_rect="true"   title="ADVANCED WATER EDITOR"   width="700"> 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/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index db95d01b43..ab73f135b9 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -1,61 +1,104 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel name="Outfits" -       height="510" -   width="333" -      follows="top|left" -             left="0" -	     top_pad="0"> -    <accordion -     single_expansion="true" -     height="510" -             layout="topleft" -             left="0" -      follows="top|left" -     name="outfits_accordion" -	     top_pad="0" -             width="333"> -     <accordion_tab -            expanded="false" -            layout="topleft" -         name="tab_cof" -         title="Current Outfit"> -	 <inventory_panel + + <panel name="Outfits" + background_visible="true" +  follows="all" + height="550" + label="Things" + layout="topleft" + min_height="350" + min_width="240" + width="330" + border="false"> +   <tab_container +     follows="all" +     height="500" +     layout="topleft" +     left="10" +     name="appearance_tabs" +     tab_min_width="100" +     tab_height="30" +     tab_position="top" +     halign="center" +     width="313"> +      <inventory_panel +        label="MY OUTFITS" +        help_topic="my_outfits_tab"  	    allow_multi_select="true" +	    follows="all"  	    border="false" -            height="460" -	     left="0" -             top="0" -		 mouse_opaque="true" -	         name="cof_accordionpanel" -		 start_folder="Current Outfit" /> -        </accordion_tab> -        <accordion_tab -            expanded="true" -            layout="topleft" -         name="tab_outfits" -         title="My Outfits"> -	 <inventory_panel -	 	 allow_multi_select="true" -		 border="false" -	     follows="all" -		 left="0" -             top="0" -            height="460" -		 mouse_opaque="true" -	     name="outfitslist_accordionpanel" -		 start_folder="My Outfits" /> -        </accordion_tab> -	</accordion> -	<!--<button bottom="0" -		 halign="center" -		 height="23" -		 label=">" -		 enabled="false" -	     mouse_opaque="false" -		 name="selector" -		 width="20" -		 left="0" -		 visible="false" -	     follows="right|bottom" -		 tool_tip="View outfit properties" />--> +	    left="0" +        top="0" +        height="500" +        width="290" + 		mouse_opaque="true" + 	    name="outfitslist_accordionpanel" + 		start_folder="My Outfits" />  +         <inventory_panel +        label="WEARING" +        help_topic="now_wearing_tab" +        allow_multi_select="true" +        border="false" +        height="500" +        width="290" +        left="0" +        top="0" +        mouse_opaque="true" +        name="cof_accordionpanel" +        start_folder="Current Outfit" /> +   </tab_container> +	<panel +	  background_visible="true" +	  follows="bottom|left" +	  height="50" +	  layout="topleft" +	  left="0" +	  visible="true" +	  name="bottom_panel" +	  top_pad="10" +	  width="313"> +		 <button +		  follows="bottom|left" +		  tool_tip="Show additional options" +		  height="18" +		  image_disabled="OptionsMenu_Disabled" +		  image_selected="OptionsMenu_Press" +		  image_unselected="OptionsMenu_Off" +		  layout="topleft" +		  left="10" +		  name="options_gear_btn" +		  top="6" +		  width="18" /> +		 <button +		  follows="bottom|left" +		  height="18" +		  image_selected="AddItem_Press" +		  image_unselected="AddItem_Off" +		  image_disabled="AddItem_Disabled" +		  layout="topleft" +		  left_pad="5" +		  name="add_btn" +		  tool_tip="Add new item" +		  width="18" /> +		 <dnd_button +		  follows="bottom|left" +		  height="18" +		  image_selected="TrashItem_Press" +		  image_unselected="TrashItem_Off" +		  layout="topleft" +		  right="-5" +		  name="trash_btn" +		  tool_tip="Remove selected item" +		  top="6" +		  width="18" /> +	 <button +	  follows="top|left" +		height="23" +		label="Wear" +		layout="topleft" +		name="wear_btn" +		right="-5" +		top_pad="0" +		width="90" /> +	 </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index e21de31498..b4f72a48bc 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -380,7 +380,7 @@  		  image_selected="AudioMute_Off"  		  image_unselected="Audio_Off"  		  hover_glow_amount="0.15" -		  name="media_volume_button" +		  name="media_mute_button"  		  height="22"  		  is_toggle="true"  		  layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_region_covenant.xml b/indra/newview/skins/default/xui/en/panel_region_covenant.xml index 75d7d85505..ff55090f16 100644 --- a/indra/newview/skins/default/xui/en/panel_region_covenant.xml +++ b/indra/newview/skins/default/xui/en/panel_region_covenant.xml @@ -3,6 +3,7 @@   border="true"   follows="top|left"   height="320" + help_topic="panel_region_covenant_tab"   label="Covenant"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml index e07585d285..a6b4ddd01e 100644 --- a/indra/newview/skins/default/xui/en/panel_region_debug.xml +++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml @@ -3,6 +3,7 @@   border="true"   follows="top|left"   height="320" + help_topic="panel_region_debug_tab"   label="Debug"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index f381c5c213..ba39e88024 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -3,6 +3,7 @@   border="false"   follows="top|left"   height="320" + help_topic="panel_region_estate_tab"   label="Estate"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 79d8f3a0ee..26568c2a28 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -3,6 +3,7 @@   border="true"   follows="top|left"   height="320" + help_topic="panel_region_general_tab"   label="Region"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index ffd51bf510..5093c52129 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -3,6 +3,7 @@   border="true"   follows="top|left"   height="320" + help_topic="panel_region_terrain_tab"   label="Terrain"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_region_texture.xml b/indra/newview/skins/default/xui/en/panel_region_texture.xml index 5089064c07..a4d24cb0fc 100644 --- a/indra/newview/skins/default/xui/en/panel_region_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_region_texture.xml @@ -3,6 +3,7 @@   border="true"   follows="top|left"   height="320" + help_topic="panel_region_texture_tab"   label="Ground Textures"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 3dac1a9614..27f19d44fa 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -85,72 +85,21 @@ left="0"     class="panel_outfits_inventory"     filename="panel_outfits_inventory.xml"     name="panel_outfits_inventory" -   height="510" +   height="550"     min_height="510"     width="333"     top_pad="0" -   follows="top|left" +   follows="all"     /> -   <panel -   visible="true" -   name="bottom_panel" -   height="50" -   left="0" -   top_pad="3" -   follows="bottom|left" -   width="333"> -      <button -       follows="bottom|left" -       tool_tip="Show additional options" -       height="18" -       image_disabled="OptionsMenu_Disabled" -       image_selected="OptionsMenu_Press" -       image_unselected="OptionsMenu_Off" -       layout="topleft" -       left="10" -       name="options_gear_btn" -       top="6" -       width="18" /> -      <button -       follows="bottom|left" -       height="18" -       image_selected="AddItem_Press" -       image_unselected="AddItem_Off" -       image_disabled="AddItem_Disabled" -       layout="topleft" -       left_pad="5" -   name="newlook_btn" -       tool_tip="Add new outfit" -       width="18" /> -      <dnd_button -       follows="bottom|left" -       height="18" -       image_selected="TrashItem_Press" -       image_unselected="TrashItem_Off" -       layout="topleft" -       right="-5" -       name="trash_btn" -       tool_tip="Remove selected item" -       top="6" -       width="18" /> -      <button -       follows="bottom|left" -      height="23" -      label="Wear" -      layout="topleft" -      name="wear_btn" -      right="-5" -      top_pad="0" -      width="90" /> -   </panel> -   <!--   <button -   follows="bottom|left" -   height="23" -   label="New outfit" -   layout="topleft" -   left_pad="5" -   right="-10" -   width="100" />--> +  <!--   <button +	  follows="bottom|left" +		height="23" +		label="New outfit" +		layout="topleft" +		left_pad="5" +		right="-10" +		name="newlook_btn" +		 width="100" />-->     <panel     class="panel_look_info"     filename="panel_look_info.xml" @@ -167,4 +116,5 @@ left="0"     left="0"     name="panel_edit_wearable"     visible="false" /> -</panel>
\ No newline at end of file +</panel> + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index c3650c71c3..3044f10573 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -460,7 +460,7 @@ Returns the rotation of detected object number (returns <0,0,0,1> if numbe  	</string>  	<string name="LSLTipText_llDetectedGroup" translate="false">  integer llDetectedGroup(integer number) -Returns TRUE if detected object is part of same group as owner +Returns an integer that is a boolean representing if the detected object or avatar is in the same group that the prim containing the script is set to  	</string>  	<string name="LSLTipText_llDetectedLinkNumber" translate="false">  integer llDetectedLinkNumber(integer number) @@ -812,7 +812,7 @@ Preloads a sound on viewers within range  	</string>  	<string name="LSLTipText_llRotLookAt" translate="false">  llRotLookAt(rotation target, float strength, float damping) -Causes object name to point its forward axis towards target +Causes object to point its forward axis towards target  	</string>  	<string name="LSLTipText_llStringLength" translate="false">  integer llStringLength(string str) @@ -1471,7 +1471,7 @@ Returns the requested permission mask for the root object the task is attached t  	</string>  	<string name="LSLTipText_llSetObjectPermMask" translate="false">  llSetObjectPermMask(integer mask, integer value) -Sets the given permission mask to the new value on the root object the task is attached to +Sets the given permission mask to the new value on the root object the task is attached to (requires God Mode)  	</string>  	<string name="LSLTipText_llGetInventoryPermMask" translate="false">  integer llGetInventoryPermMask(string item, integer mask) @@ -1479,7 +1479,7 @@ Returns the requested permission mask for the inventory item  	</string>  	<string name="LSLTipText_llSetInventoryPermMask" translate="false">  llSetInventoryPermMask(string item, integer mask, integer value) -Sets the given permission mask to the new value on the inventory item +Sets the given permission mask to the new value on the inventory item (requires God Mode)  	</string>  	<string name="LSLTipText_llGetInventoryCreator" translate="false">  key llGetInventoryCreator(string item) 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") | 
