diff options
Diffstat (limited to 'indra')
132 files changed, 5539 insertions, 694 deletions
| diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmod.cpp index a4620fa13c..fe94688565 100644 --- a/indra/llaudio/llstreamingaudio_fmod.cpp +++ b/indra/llaudio/llstreamingaudio_fmod.cpp @@ -271,7 +271,7 @@ void LLStreamingAudio_FMOD::setGain(F32 vol)  	if (mFMODInternetStreamChannel != -1)  	{ -		vol = llclamp(vol, 0.f, 1.f); +		vol = llclamp(vol * vol, 0.f, 1.f);  		int vol_int = llround(vol * 255.f);  		FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int);  	} diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 9dab9d9582..e19f8b0454 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -77,23 +77,23 @@ LLAssetDictionary::LLAssetDictionary()  {  	//       												   DESCRIPTION			TYPE NAME	HUMAN NAME			CAN LINK?   CAN FETCH?  CAN KNOW?	  	//      												  |--------------------|-----------|-------------------|-----------|-----------|---------| -	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			false,		false,		true)); -	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			false,		true,		true)); -	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		false,		false,		false)); -	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			false,		true,		true)); -	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	false,		false,		false)); +	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			true,		false,		true)); +	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			true,		true,		true)); +	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		true,		false,		false)); +	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			true,		true,		true)); +	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	true,		false,		false));  	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			true,		true,		true));  	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			true,		false,		false)); -	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		false,		false,		true)); +	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		true,		false,		true));  	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			true,		false,		false)); -	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		false,		false,		false)); -	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		false,		false,		false)); -	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		false,		false,		false)); +	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		true,		false,		false)); +	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		true,		false,		false)); +	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		true,		false,		false));  	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		true,		true,		true)); -	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			false,		false,		false)); -	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		false,		false,		false)); -	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		false,		false,		false)); -	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		false,		true,		true)); +	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			true,		false,		false)); +	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		true,		false,		false)); +	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		true,		false,		false)); +	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		true,		true,		true));  	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			true,		true,		true));  	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			false,		false,		false)); diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 0874f574c5..aa7c8c789a 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1338,7 +1338,7 @@ LLImageFormatted::LLImageFormatted(S8 codec)  	  mCodec(codec),  	  mDecoding(0),  	  mDecoded(0), -	  mDiscardLevel(0) +	  mDiscardLevel(-1)  {  	mMemType = LLMemType::MTYPE_IMAGEFORMATTED;  } diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index c268625064..2d4ee604b0 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -210,6 +210,10 @@ bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)  bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,  									 LLAssetType::EType asset_type)  { +	// Links can be of any inventory type. +	if (LLAssetType::lookupIsLinkType(asset_type)) +		return true; +  	const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type);  	if (!entry) return false; diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index e09b511a6e..0c9b325b68 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -160,7 +160,7 @@ void LLPluginClassMedia::idle(void)  		mPlugin->idle();  	} -	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL)) +	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))  	{  		// Can't process a size change at this time  	} @@ -437,6 +437,12 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int  {  	if(type == MOUSE_EVENT_MOVE)  	{ +		if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked()) +		{ +			// Don't queue up mouse move events that can't be delivered. +			return; +		} +  		if((x == mLastMouseX) && (y == mLastMouseY))  		{  			// Don't spam unnecessary mouse move events. diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp index 1d7ddc5592..89f8b44569 100644 --- a/indra/llplugin/llpluginmessagepipe.cpp +++ b/indra/llplugin/llpluginmessagepipe.cpp @@ -96,11 +96,14 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)  	}  } -LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket) +LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket): +	mInputMutex(gAPRPoolp), +	mOutputMutex(gAPRPoolp), +	mOwner(owner), +	mSocket(socket)  { -	mOwner = owner; +	  	mOwner->setMessagePipe(this); -	mSocket = socket;  }  LLPluginMessagePipe::~LLPluginMessagePipe() @@ -114,6 +117,7 @@ LLPluginMessagePipe::~LLPluginMessagePipe()  bool LLPluginMessagePipe::addMessage(const std::string &message)  {  	// queue the message for later output +	LLMutexLock lock(&mOutputMutex);  	mOutput += message;  	mOutput += MESSAGE_DELIMITER;	// message separator @@ -149,6 +153,18 @@ void LLPluginMessagePipe::setSocketTimeout(apr_interval_time_t timeout_usec)  bool LLPluginMessagePipe::pump(F64 timeout)  { +	bool result = pumpOutput(); +	 +	if(result) +	{ +		result = pumpInput(timeout); +	} +	 +	return result; +} + +bool LLPluginMessagePipe::pumpOutput() +{  	bool result = true;  	if(mSocket) @@ -156,6 +172,7 @@ bool LLPluginMessagePipe::pump(F64 timeout)  		apr_status_t status;  		apr_size_t size; +		LLMutexLock lock(&mOutputMutex);  		if(!mOutput.empty())  		{  			// write any outgoing messages @@ -183,6 +200,17 @@ bool LLPluginMessagePipe::pump(F64 timeout)  				// remove the written part from the buffer and try again later.  				mOutput = mOutput.substr(size);  			} +			else if(APR_STATUS_IS_EOF(status)) +			{ +				// This is what we normally expect when a plugin exits. +				llinfos << "Got EOF from plugin socket. " << llendl; + +				if(mOwner) +				{ +					mOwner->socketError(status); +				} +				result = false; +			}  			else   			{  				// some other error @@ -196,6 +224,19 @@ bool LLPluginMessagePipe::pump(F64 timeout)  				result = false;  			}  		} +	} +	 +	return result; +} + +bool LLPluginMessagePipe::pumpInput(F64 timeout) +{ +	bool result = true; + +	if(mSocket) +	{ +		apr_status_t status; +		apr_size_t size;  		// FIXME: For some reason, the apr timeout stuff isn't working properly on windows.  		// Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead. @@ -216,8 +257,16 @@ bool LLPluginMessagePipe::pump(F64 timeout)  			char input_buf[1024];  			apr_size_t request_size; -			// Start out by reading one byte, so that any data received will wake us up. -			request_size = 1; +			if(timeout == 0.0f) +			{ +				// If we have no timeout, start out with a full read. +				request_size = sizeof(input_buf); +			} +			else +			{ +				// Start out by reading one byte, so that any data received will wake us up. +				request_size = 1; +			}  			// and use the timeout so we'll sleep if no data is available.  			setSocketTimeout((apr_interval_time_t)(timeout * 1000000)); @@ -236,11 +285,14 @@ bool LLPluginMessagePipe::pump(F64 timeout)  //				LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;  				if(size > 0) +				{ +					LLMutexLock lock(&mInputMutex);  					mInput.append(input_buf, size); +				}  				if(status == APR_SUCCESS)  				{ -//					llinfos << "success, read " << size << llendl; +					LL_DEBUGS("PluginSocket") << "success, read " << size << LL_ENDL;  					if(size != request_size)  					{ @@ -250,16 +302,28 @@ bool LLPluginMessagePipe::pump(F64 timeout)  				}  				else if(APR_STATUS_IS_TIMEUP(status))  				{ -//					llinfos << "TIMEUP, read " << size << llendl; +					LL_DEBUGS("PluginSocket") << "TIMEUP, read " << size << LL_ENDL;  					// Timeout was hit.  Since the initial read is 1 byte, this should never be a partial read.  					break;  				}  				else if(APR_STATUS_IS_EAGAIN(status))  				{ -//					llinfos << "EAGAIN, read " << size << llendl; +					LL_DEBUGS("PluginSocket") << "EAGAIN, read " << size << LL_ENDL; -					// We've been doing partial reads, and we're done now. +					// Non-blocking read returned immediately. +					break; +				} +				else if(APR_STATUS_IS_EOF(status)) +				{ +					// This is what we normally expect when a plugin exits. +					LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL; + +					if(mOwner) +					{ +						mOwner->socketError(status); +					} +					result = false;  					break;  				}  				else @@ -276,22 +340,18 @@ bool LLPluginMessagePipe::pump(F64 timeout)  					break;  				} -				// Second and subsequent reads should not use the timeout -				setSocketTimeout(0); -				// and should try to fill the input buffer -				request_size = sizeof(input_buf); +				if(timeout != 0.0f) +				{ +					// Second and subsequent reads should not use the timeout +					setSocketTimeout(0); +					// and should try to fill the input buffer +					request_size = sizeof(input_buf); +				}  			}  			processInput();  		}  	} - -	if(!result) -	{ -		// If we got an error, we're done. -		LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL; -		delete this; -	}  	return result;	  } @@ -299,26 +359,27 @@ bool LLPluginMessagePipe::pump(F64 timeout)  void LLPluginMessagePipe::processInput(void)  {  	// Look for input delimiter(s) in the input buffer. -	int start = 0;  	int delim; -	while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos) +	mInputMutex.lock(); +	while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos)  	{	  		// Let the owner process this message  		if (mOwner)  		{ -			mOwner->receiveMessageRaw(mInput.substr(start, delim - start)); +			// Pull the message out of the input buffer before calling receiveMessageRaw. +			// It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request) +			// and this guarantees that the messages will get dequeued correctly. +			std::string message(mInput, 0, delim); +			mInput.erase(0, delim + 1); +			mInputMutex.unlock(); +			mOwner->receiveMessageRaw(message); +			mInputMutex.lock();  		}  		else  		{  			LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;  		} -		 -		start = delim + 1;  	} -	 -	// Remove delivered messages from the input buffer. -	if(start != 0) -		mInput = mInput.substr(start); -	 +	mInputMutex.unlock();  } diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h index 1ddb38de68..1b0a08254b 100644 --- a/indra/llplugin/llpluginmessagepipe.h +++ b/indra/llplugin/llpluginmessagepipe.h @@ -35,6 +35,7 @@  #define LL_LLPLUGINMESSAGEPIPE_H  #include "lliosocket.h" +#include "llthread.h"  class LLPluginMessagePipe; @@ -51,7 +52,7 @@ public:  	virtual apr_status_t socketError(apr_status_t error);  	// called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use! -	virtual void setMessagePipe(LLPluginMessagePipe *message_pipe) ; +	virtual void setMessagePipe(LLPluginMessagePipe *message_pipe);  protected:  	// returns false if writeMessageRaw() would drop the message @@ -76,14 +77,18 @@ public:  	void clearOwner(void);  	bool pump(F64 timeout = 0.0f); -	 +	bool pumpOutput(); +	bool pumpInput(F64 timeout = 0.0f); +		  protected:	  	void processInput(void);  	// used internally by pump()  	void setSocketTimeout(apr_interval_time_t timeout_usec); +	LLMutex mInputMutex;  	std::string mInput; +	LLMutex mOutputMutex;  	std::string mOutput;  	LLPluginMessagePipeOwner *mOwner; diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index ccaf95b36d..d1cf91b253 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -48,6 +48,8 @@ LLPluginProcessChild::LLPluginProcessChild()  	mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);  	mSleepTime = PLUGIN_IDLE_SECONDS;	// default: send idle messages at 100Hz  	mCPUElapsed = 0.0f; +	mBlockingRequest = false; +	mBlockingResponseReceived = false;  }  LLPluginProcessChild::~LLPluginProcessChild() @@ -83,9 +85,14 @@ void LLPluginProcessChild::idle(void)  	bool idle_again;  	do  	{ -		if(mSocketError != APR_SUCCESS) +		if(APR_STATUS_IS_EOF(mSocketError))  		{ -			LL_INFOS("Plugin") << "message pipe is in error state, moving to STATE_ERROR"<< LL_ENDL; +			// Plugin socket was closed.  This covers both normal plugin termination and host crashes. +			setState(STATE_ERROR); +		} +		else if(mSocketError != APR_SUCCESS) +		{ +			LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR"<< LL_ENDL;  			setState(STATE_ERROR);  		}	 @@ -226,6 +233,7 @@ void LLPluginProcessChild::idle(void)  void LLPluginProcessChild::sleep(F64 seconds)  { +	deliverQueuedMessages();  	if(mMessagePipe)  	{  		mMessagePipe->pump(seconds); @@ -238,6 +246,7 @@ void LLPluginProcessChild::sleep(F64 seconds)  void LLPluginProcessChild::pump(void)  { +	deliverQueuedMessages();  	if(mMessagePipe)  	{  		mMessagePipe->pump(0.0f); @@ -309,15 +318,32 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)  	LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL; +	// Decode this message +	LLPluginMessage parsed; +	parsed.parse(message); + +	if(mBlockingRequest) +	{ +		// We're blocking the plugin waiting for a response. + +		if(parsed.hasValue("blocking_response")) +		{ +			// This is the message we've been waiting for -- fall through and send it immediately.  +			mBlockingResponseReceived = true; +		} +		else +		{ +			// Still waiting.  Queue this message and don't process it yet. +			mMessageQueue.push(message); +			return; +		} +	} +	  	bool passMessage = true;  	// FIXME: how should we handle queueing here?  	{ -		// Decode this message -		LLPluginMessage parsed; -		parsed.parse(message); -		  		std::string message_class = parsed.getClass();  		if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)  		{ @@ -425,7 +451,13 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)  void LLPluginProcessChild::receivePluginMessage(const std::string &message)  {  	LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; - +	 +	if(mBlockingRequest) +	{ +		//  +		LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL; +	} +	  	// Incoming message from the plugin instance  	bool passMessage = true; @@ -436,6 +468,12 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)  		// Decode this message  		LLPluginMessage parsed;  		parsed.parse(message); +		 +		if(parsed.hasValue("blocking_request")) +		{ +			mBlockingRequest = true; +		} +  		std::string message_class = parsed.getClass();  		if(message_class == "base")  		{ @@ -494,6 +532,19 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)  		LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;  		writeMessageRaw(message);  	} +	 +	while(mBlockingRequest) +	{ +		// The plugin wants to block and wait for a response to this message. +		sleep(mSleepTime);	// this will pump the message pipe and process messages + +		if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL)) +		{ +			// Response has been received, or we've hit an error state.  Stop waiting. +			mBlockingRequest = false; +			mBlockingResponseReceived = false; +		} +	}  } @@ -502,3 +553,15 @@ void LLPluginProcessChild::setState(EState state)  	LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;  	mState = state;   }; + +void LLPluginProcessChild::deliverQueuedMessages() +{ +	if(!mBlockingRequest) +	{ +		while(!mMessageQueue.empty()) +		{ +			receiveMessageRaw(mMessageQueue.front()); +			mMessageQueue.pop(); +		} +	} +} diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h index 0e5e85406a..1430ad7a5d 100644 --- a/indra/llplugin/llpluginprocesschild.h +++ b/indra/llplugin/llpluginprocesschild.h @@ -106,6 +106,11 @@ private:  	LLTimer mHeartbeat;  	F64		mSleepTime;  	F64		mCPUElapsed; +	bool	mBlockingRequest; +	bool	mBlockingResponseReceived; +	std::queue<std::string> mMessageQueue; +	 +	void deliverQueuedMessages();  }; diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 895c858979..3589b22a77 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -45,8 +45,51 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()  } -LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) +bool LLPluginProcessParent::sUseReadThread = false; +apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; +bool LLPluginProcessParent::sPollsetNeedsRebuild = false; +LLMutex *LLPluginProcessParent::sInstancesMutex; +std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; +LLThread *LLPluginProcessParent::sReadThread = NULL; + + +class LLPluginProcessParentPollThread: public LLThread  { +public: +	LLPluginProcessParentPollThread() : +		LLThread("LLPluginProcessParentPollThread", gAPRPoolp) +	{ +	} +protected: +	// Inherited from LLThread +	/*virtual*/ void run(void) +	{ +		while(!isQuitting() && LLPluginProcessParent::getUseReadThread()) +		{ +			LLPluginProcessParent::poll(0.1f); +			checkPause(); +		} +		 +		// Final poll to clean up the pollset, etc. +		LLPluginProcessParent::poll(0.0f); +	}  + +	// Inherited from LLThread +	/*virtual*/ bool runCondition(void) +	{ +		return(LLPluginProcessParent::canPollThreadRun()); +	} + +}; + +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): +	mIncomingQueueMutex(gAPRPoolp) +{ +	if(!sInstancesMutex) +	{ +		sInstancesMutex = new LLMutex(gAPRPoolp); +	} +	  	mOwner = owner;  	mBoundPort = 0;  	mState = STATE_UNINITIALIZED; @@ -54,18 +97,37 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)  	mCPUUsage = 0.0;  	mDisableTimeout = false;  	mDebug = false; +	mBlocked = false; +	mPolledInput = false; +	mPollFD.client_data = NULL;  	mPluginLaunchTimeout = 60.0f;  	mPluginLockupTimeout = 15.0f;  	// Don't start the timer here -- start it when we actually launch the plugin process.  	mHeartbeat.stop(); +	 +	// Don't add to the global list until fully constructed. +	{ +		LLMutexLock lock(sInstancesMutex); +		sInstances.push_back(this); +	}  }  LLPluginProcessParent::~LLPluginProcessParent()  {  	LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; +	// Remove from the global list before beginning destruction. +	{ +		// Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll() +		LLMutexLock lock(sInstancesMutex); +		{ +			LLMutexLock lock2(&mIncomingQueueMutex); +			sInstances.remove(this); +		} +	} +  	// Destroy any remaining shared memory regions  	sharedMemoryRegionsType::iterator iter;  	while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end()) @@ -77,15 +139,17 @@ LLPluginProcessParent::~LLPluginProcessParent()  		mSharedMemoryRegions.erase(iter);  	} -	// 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(); +	mProcess.kill();  	killSockets();  }  void LLPluginProcessParent::killSockets(void)  { -	killMessagePipe(); +	{ +		LLMutexLock lock(&mIncomingQueueMutex); +		killMessagePipe(); +	} +  	mListenSocket.reset();  	mSocket.reset();  } @@ -159,21 +223,47 @@ void LLPluginProcessParent::idle(void)  	do  	{ +		// process queued messages +		mIncomingQueueMutex.lock(); +		while(!mIncomingQueue.empty()) +		{ +			LLPluginMessage message = mIncomingQueue.front(); +			mIncomingQueue.pop(); +			mIncomingQueueMutex.unlock(); +				 +			receiveMessage(message); +			 +			mIncomingQueueMutex.lock(); +		} + +		mIncomingQueueMutex.unlock(); +		  		// Give time to network processing  		if(mMessagePipe)  		{ -			if(!mMessagePipe->pump()) +			// Drain any queued outgoing messages +			mMessagePipe->pumpOutput(); +			 +			// Only do input processing here if this instance isn't in a pollset. +			if(!mPolledInput)  			{ -//				LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL; -				errorState(); +				mMessagePipe->pumpInput();  			}  		} - -		if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING)) +		 +		if(mState <= STATE_RUNNING)  		{ -			// The socket is in an error state -- the plugin is gone. -			LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; -			errorState(); +			if(APR_STATUS_IS_EOF(mSocketError)) +			{ +				// Plugin socket was closed.  This covers both normal plugin termination and plugin crashes. +				errorState(); +			} +			else if(mSocketError != APR_SUCCESS) +			{ +				// The socket is in an error state -- the plugin is gone. +				LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; +				errorState(); +			}  		}	  		// If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). @@ -354,7 +444,7 @@ void LLPluginProcessParent::idle(void)  			break;  			case STATE_HELLO: -				LL_DEBUGS("Plugin") << "received hello message" << llendl; +				LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;  				// Send the message to load the plugin  				{ @@ -388,7 +478,7 @@ void LLPluginProcessParent::idle(void)  				}  				else if(pluginLockedUp())  				{ -					LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl; +					LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;  					errorState();  				}  			break; @@ -410,8 +500,7 @@ void LLPluginProcessParent::idle(void)  			break;  			case STATE_CLEANUP: -				// Don't do a kill here anymore -- closing the sockets is the new 'kill'. -				mProcess.orphan(); +				mProcess.kill();  				killSockets();  				setState(STATE_DONE);  			break; @@ -479,23 +568,323 @@ void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send)  void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)  { +	if(message.hasValue("blocking_response")) +	{ +		mBlocked = false; + +		// reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. +		mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); +	}  	std::string buffer = message.generate();  	LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;	  	writeMessageRaw(buffer); +	 +	// Try to send message immediately. +	if(mMessagePipe) +	{ +		mMessagePipe->pumpOutput(); +	}  } +//virtual  +void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) +{ +	bool update_pollset = false; +	 +	if(mMessagePipe) +	{ +		// Unsetting an existing message pipe -- remove from the pollset		 +		mPollFD.client_data = NULL; + +		// pollset needs an update +		update_pollset = true; +	} +	if(message_pipe != NULL) +	{ +		// Set up the apr_pollfd_t +		mPollFD.p = gAPRPoolp; +		mPollFD.desc_type = APR_POLL_SOCKET; +		mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; +		mPollFD.rtnevents = 0; +		mPollFD.desc.s = mSocket->getSocket(); +		mPollFD.client_data = (void*)this;	 +		 +		// pollset needs an update +		update_pollset = true; +	} + +	mMessagePipe = message_pipe; +	 +	if(update_pollset) +	{ +		dirtyPollSet(); +	} +} + +//static  +void LLPluginProcessParent::dirtyPollSet() +{ +	sPollsetNeedsRebuild = true; +	 +	if(sReadThread) +	{ +		LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL; +		sReadThread->unpause(); +	} +} + +void LLPluginProcessParent::updatePollset() +{ +	if(!sInstancesMutex) +	{ +		// No instances have been created yet.  There's no work to do. +		return; +	} +		 +	LLMutexLock lock(sInstancesMutex); + +	if(sPollSet) +	{ +		LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL; +		// delete the existing pollset. +		apr_pollset_destroy(sPollSet); +		sPollSet = NULL; +	} +	 +	std::list<LLPluginProcessParent*>::iterator iter; +	int count = 0; +	 +	// Count the number of instances that want to be in the pollset +	for(iter = sInstances.begin(); iter != sInstances.end(); iter++) +	{ +		(*iter)->mPolledInput = false; +		if((*iter)->mPollFD.client_data) +		{ +			// This instance has a socket that needs to be polled. +			++count; +		} +	} + +	if(sUseReadThread && sReadThread && !sReadThread->isQuitting()) +	{ +		if(!sPollSet && (count > 0)) +		{ +#ifdef APR_POLLSET_NOCOPY +			// The pollset doesn't exist yet.  Create it now. +			apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); +			if(status != APR_SUCCESS) +			{ +#endif // APR_POLLSET_NOCOPY +				LL_WARNS("PluginPoll") << "Couldn't create pollset.  Falling back to non-pollset mode." << LL_ENDL; +				sPollSet = NULL; +#ifdef APR_POLLSET_NOCOPY +			} +			else +			{ +				LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL; +				 +				// Pollset was created, add all instances to it. +				for(iter = sInstances.begin(); iter != sInstances.end(); iter++) +				{ +					if((*iter)->mPollFD.client_data) +					{ +						status = apr_pollset_add(sPollSet, &((*iter)->mPollFD)); +						if(status == APR_SUCCESS) +						{ +							(*iter)->mPolledInput = true; +						} +						else +						{ +							LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL; +						} +					} +				} +			} +#endif // APR_POLLSET_NOCOPY +		} +	} +} + +void LLPluginProcessParent::setUseReadThread(bool use_read_thread) +{ +	if(sUseReadThread != use_read_thread) +	{ +		sUseReadThread = use_read_thread; +		 +		if(sUseReadThread) +		{ +			if(!sReadThread) +			{ +				// start up the read thread +				LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL; + +				// make sure the pollset gets rebuilt. +				sPollsetNeedsRebuild = true; +				 +				sReadThread = new LLPluginProcessParentPollThread; +				sReadThread->start(); +			} +		} +		else +		{ +			if(sReadThread) +			{ +				// shut down the read thread +				LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL; +				delete sReadThread; +				sReadThread = NULL; +			} +		} + +	} +} + +void LLPluginProcessParent::poll(F64 timeout) +{ +	if(sPollsetNeedsRebuild || !sUseReadThread) +	{ +		sPollsetNeedsRebuild = false; +		updatePollset(); +	} +	 +	if(sPollSet) +	{ +		apr_status_t status; +		apr_int32_t count; +		const apr_pollfd_t *descriptors; +		status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors); +		if(status == APR_SUCCESS) +		{ +			// One or more of the descriptors signalled.  Call them. +			for(int i = 0; i < count; i++) +			{ +				LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data); +				// NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY). +				// This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor. +				// It's even possible that the old pointer no longer points to a valid LLPluginProcessParent. +				// This means that we can't safely dereference the 'self' pointer here without some extra steps... +				if(self) +				{ +					// Make sure this pointer is still in the instances list +					bool valid = false; +					{ +						LLMutexLock lock(sInstancesMutex); +						for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) +						{ +							if(*iter == self) +							{ +								// Lock the instance's mutex before unlocking the global mutex.   +								// This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call. +								self->mIncomingQueueMutex.lock(); +								valid = true; +								break; +							} +						} +					} +					 +					if(valid) +					{ +						// The instance is still valid. +						// Pull incoming messages off the socket +						self->servicePoll(); +						self->mIncomingQueueMutex.unlock(); +					} +					else +					{ +						LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL; +					} + +				} +			} +		} +		else if(APR_STATUS_IS_TIMEUP(status)) +		{ +			// timed out with no incoming data.  Just return. +		} +		else if(status == EBADF) +		{ +			// This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. +			// The pollset has been or will be recreated, so just return. +			LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; +		} +		else if(status != APR_SUCCESS) +		{ +			LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; +		} +	} +} + +void LLPluginProcessParent::servicePoll() +{ +	bool result = true; +	 +	// poll signalled on this object's socket.  Try to process incoming messages. +	if(mMessagePipe) +	{ +		result = mMessagePipe->pumpInput(0.0f); +	} + +	if(!result) +	{ +		// If we got a read error on input, remove this pipe from the pollset +		apr_pollset_remove(sPollSet, &mPollFD); + +		// and tell the code not to re-add it +		mPollFD.client_data = NULL; +	} +}  void LLPluginProcessParent::receiveMessageRaw(const std::string &message)  {  	LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; - -	// FIXME: should this go into a queue instead?  	LLPluginMessage parsed;  	if(parsed.parse(message) != -1)  	{ -		receiveMessage(parsed); +		if(parsed.hasValue("blocking_request")) +		{ +			mBlocked = true; +		} + +		if(mPolledInput) +		{ +			// This is being called on the polling thread -- only do minimal processing/queueing. +			receiveMessageEarly(parsed); +		} +		else +		{ +			// This is not being called on the polling thread -- do full message processing at this time. +			receiveMessage(parsed); +		} +	} +} + +void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) +{ +	// NOTE: this function will be called from the polling thread.  It will be called with mIncomingQueueMutex _already locked_.  + +	bool handled = false; +	 +	std::string message_class = message.getClass(); +	if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) +	{ +		// no internal messages need to be handled early. +	} +	else +	{ +		// Call out to the owner and see if they to reply +		// TODO: Should this only happen when blocked? +		if(mOwner != NULL) +		{ +			handled = mOwner->receivePluginMessageEarly(message); +		} +	} +	 +	if(!handled) +	{ +		// any message that wasn't handled early needs to be queued. +		mIncomingQueue.push(message);  	}  } @@ -689,18 +1078,15 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()  {  	bool result = false; -	if(!mDisableTimeout && !mDebug) +	if(!mProcess.isRunning())  	{ -		if(!mProcess.isRunning()) -		{ -			LL_WARNS("Plugin") << "child exited" << llendl; -			result = true; -		} -		else if(pluginLockedUp()) -		{ -			LL_WARNS("Plugin") << "timeout" << llendl; -			result = true; -		} +		LL_WARNS("Plugin") << "child exited" << LL_ENDL; +		result = true; +	} +	else if(pluginLockedUp()) +	{ +		LL_WARNS("Plugin") << "timeout" << LL_ENDL; +		result = true;  	}  	return result; @@ -708,6 +1094,12 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()  bool LLPluginProcessParent::pluginLockedUp()  { +	if(mDisableTimeout || mDebug || mBlocked) +	{ +		// Never time out a plugin process in these cases. +		return false; +	} +	  	// If the timer is running and has expired, the plugin has locked up.  	return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());  } diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index cc6c513615..4dff835b6a 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -41,12 +41,14 @@  #include "llpluginsharedmemory.h"  #include "lliosocket.h" +#include "llthread.h"  class LLPluginProcessParentOwner  {  public:  	virtual ~LLPluginProcessParentOwner();  	virtual void receivePluginMessage(const LLPluginMessage &message) = 0; +	virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;};  	// This will only be called when the plugin has died unexpectedly   	virtual void pluginLaunchFailed() {};  	virtual void pluginDied() {}; @@ -74,6 +76,9 @@ public:  	// returns true if the process has exited or we've had a fatal error  	bool isDone(void);	 +	// returns true if the process is currently waiting on a blocking request +	bool isBlocked(void) { return mBlocked; }; +	  	void killSockets(void);  	// Go to the proper error state @@ -87,7 +92,9 @@ public:  	void receiveMessage(const LLPluginMessage &message);  	// Inherited from LLPluginMessagePipeOwner -	void receiveMessageRaw(const std::string &message); +	/*virtual*/ void receiveMessageRaw(const std::string &message); +	/*virtual*/ void receiveMessageEarly(const LLPluginMessage &message); +	/*virtual*/ void setMessagePipe(LLPluginMessagePipe *message_pipe) ;  	// This adds a memory segment shared with the client, generating a name for the segment.  The name generated is guaranteed to be unique on the host.  	// The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name. @@ -110,7 +117,11 @@ public:  	void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; };  	F64 getCPUUsage() { return mCPUUsage; }; - +	 +	static void poll(F64 timeout); +	static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); }; +	static void setUseReadThread(bool use_read_thread); +	static bool getUseReadThread() { return sUseReadThread; };  private:  	enum EState @@ -160,12 +171,27 @@ private:  	bool mDisableTimeout;  	bool mDebug; +	bool mBlocked; +	bool mPolledInput;  	LLProcessLauncher mDebugger;  	F32 mPluginLaunchTimeout;		// Somewhat longer timeout for initial launch.  	F32 mPluginLockupTimeout;		// If we don't receive a heartbeat in this many seconds, we declare the plugin locked up. +	static bool sUseReadThread; +	apr_pollfd_t mPollFD; +	static apr_pollset_t *sPollSet; +	static bool sPollsetNeedsRebuild; +	static LLMutex *sInstancesMutex; +	static std::list<LLPluginProcessParent*> sInstances; +	static void dirtyPollSet(); +	static void updatePollset(); +	void servicePoll(); +	static LLThread *sReadThread; +	 +	LLMutex mIncomingQueueMutex; +	std::queue<LLPluginMessage> mIncomingQueue;  };  #endif // LL_LLPLUGINPROCESSPARENT_H diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 00f0fd5b9a..2f02ccf30b 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1653,6 +1653,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)  	}  	U32 length = w * h; +	U32 alphatotal = 0;  	U32 sample[16];  	memset(sample, 0, sizeof(U32)*16); @@ -1672,11 +1673,15 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)  			const GLubyte* current = rowstart;  			for (U32 x = 0; x < w; x+=2)  			{ -				U32 s1 = current[0]; -				U32 s2 = current[w * mAlphaStride]; +				const U32 s1 = current[0]; +				alphatotal += s1; +				const U32 s2 = current[w * mAlphaStride]; +				alphatotal += s2;  				current += mAlphaStride; -				U32 s3 = current[0]; -				U32 s4 = current[w * mAlphaStride]; +				const U32 s3 = current[0]; +				alphatotal += s3; +				const U32 s4 = current[w * mAlphaStride]; +				alphatotal += s4;  				current += mAlphaStride;  				++sample[s1/16]; @@ -1684,19 +1689,23 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)  				++sample[s3/16];  				++sample[s4/16]; -				sample[(s1+s2+s3+s4)/(16 * 4)] += 4; +				const U32 asum = (s1+s2+s3+s4); +				alphatotal += asum; +				sample[asum/(16*4)] += 4;  			}  			rowstart += 2 * w * mAlphaStride;  		} -		length += length; +		length *= 2; // we sampled everything twice, essentially  	}  	else  	{  		const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;  		for (U32 i = 0; i < length; i++)  		{ -			++sample[*current/16]; +			const U32 s1 = *current; +			alphatotal += s1; +			++sample[s1/16];  			current += mAlphaStride;  		}  	} @@ -1704,15 +1713,31 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)  	// if more than 1/16th of alpha samples are mid-range, this  	// shouldn't be treated as a 1-bit mask +	// also, if all of the alpha samples are clumped on one half +	// of the range (but not at an absolute extreme), then consider +	// this to be an intentional effect and don't treat as a mask. +  	U32 midrangetotal = 0;  	for (U32 i = 4; i < 11; i++)  	{  		midrangetotal += sample[i];  	} +	U32 lowerhalftotal = 0; +	for (U32 i = 0; i < 8; i++) +	{ +		lowerhalftotal += sample[i]; +	} +	U32 upperhalftotal = 0; +	for (U32 i = 8; i < 16; i++) +	{ +		upperhalftotal += sample[i]; +	} -	if (midrangetotal > length/16) +	if (midrangetotal > length/16 || // lots of midrange, or +	    (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or +	    (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque  	{ -		mIsMask = FALSE; +		mIsMask = FALSE; // not suitable for masking  	}  	else  	{ diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 3c706ce90e..596da782ce 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -436,6 +436,34 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)  	addChild(panel,0);  } +void LLAccordionCtrlTab::setTitle(const std::string& title) +{ +	LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); +	if (header) +	{ +		header->setTitle(title); +	} +} + +boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) +{ +	LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); +	if (header) +	{ +		return header->setFocusReceivedCallback(cb); +	} +	return boost::signals2::connection(); +} + +boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb) +{ +	LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); +	if (header) +	{ +		return header->setFocusLostCallback(cb); +	} +	return boost::signals2::connection(); +}  LLView*	LLAccordionCtrlTab::findContainerView()  { diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index fb19d17e99..de254ed3eb 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -113,6 +113,12 @@ public:  	void		setAccordionView(LLView* panel);  	LLView*		getAccordionView() { return mContainerPanel; }; +	// Set text in LLAccordionCtrlTabHeader +	void setTitle(const std::string& title); + +	boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); +	boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); +  	bool getCollapsible() {return mCollapsible;};  	void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index e0b2244654..ec247b25c3 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1147,12 +1147,17 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p)  } -void LLFlatListViewEx::updateNoItemsMessage(bool items_filtered) +void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string)  { +	bool items_filtered = !filter_string.empty();  	if (items_filtered)  	{  		// items were filtered -		setNoItemsCommentText(mNoFilteredItemsMsg); +		LLStringUtil::format_map_t args; +		args["[SEARCH_TERM]"] = LLURI::escape(filter_string); +		std::string text = mNoFilteredItemsMsg; +		LLStringUtil::format(text, args); +		setNoItemsCommentText(text);  	}  	else  	{ diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index f7d094f7e7..4f718ab0dc 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -470,10 +470,10 @@ protected:  	/**  	 * Applies a message for empty list depend on passed argument.  	 * -	 * @param items_filtered - if true message for filtered items will be set, otherwise for -	 * completely empty list. +	 * @param filter_string - if is not empty, message for filtered items will be set, otherwise for +	 * completely empty list. Value of filter string will be passed as search_term in SLURL.  	 */ -	void updateNoItemsMessage(bool items_filtered); +	void updateNoItemsMessage(const std::string& filter_string);  private:  	std::string mNoFilteredItemsMsg; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 403723d9d8..444711de81 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -432,11 +432,15 @@ private:  class LLFloaterView : public LLUICtrl  { +public: +	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>{}; +  protected:  	LLFloaterView (const Params& p);  	friend class LLUICtrlFactory;  public: +  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  	void reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical); diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 8dec6ea9df..f8b029e19c 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -78,10 +78,8 @@ void LLLoadingIndicator::Data::initSingleton()  LLPointer<LLUIImage> LLLoadingIndicator::Data::getNextImage(S8& idx) const  { -	// Actually selects previous image because -	// current images seem to be in wrong order; -	// performs array bounds checking. -	idx = idx > 0 ? llmin(NIMAGES-1, idx-1) : NIMAGES-1; +	// Calculate next index, performing array bounds checking. +	idx = (idx >= NIMAGES || idx < 0) ? 0 : (idx + 1) % NIMAGES;   	return mImages[idx];  } diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 491cd7b6f3..b47f21ed8a 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -457,3 +457,8 @@ BOOL LLSpinCtrl::handleKeyHere(KEY key, MASK mask)  	return FALSE;  } +BOOL LLSpinCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) +{ +	// just treat a double click as a second click +	return handleMouseDown(x, y, mask); +} diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index 00d6f86f83..06201255d2 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -94,6 +94,7 @@ public:  	virtual BOOL	handleScrollWheel(S32 x,S32 y,S32 clicks);  	virtual BOOL	handleKeyHere(KEY key, MASK mask); +	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);  	void			onEditorCommit(const LLSD& data);  	static void		onEditorGainFocus(LLFocusableElement* caller, void *userdata); diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 27237800d4..930dadc377 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -435,7 +435,10 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st  	std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);  	if (existing_tag != NULL && *existing_tag != tag)  	{ -		llerrs << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << llendl; +		std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl; +		// forcing crash here +		char* foo = 0; +		*foo = 1;  	}  	LLWidgetNameRegistry ::instance().defaultRegistrar().add(param_block_type, tag);  	// associate widget type with factory function diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index cc03d9cb72..85318aea3b 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -10,4 +10,8 @@ if (WINDOWS OR DARWIN)      add_subdirectory(quicktime)  endif (WINDOWS OR DARWIN) +if (WINDOWS) +    add_subdirectory(winmmshim) +endif (WINDOWS) +  add_subdirectory(example) diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp index 9788f10a58..38727e5965 100644 --- a/indra/media_plugins/webkit/mac_volume_catcher.cpp +++ b/indra/media_plugins/webkit/mac_volume_catcher.cpp @@ -1,5 +1,5 @@  /**  - * @file dummy_volume_catcher.cpp + * @file mac_volume_catcher.cpp   * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process.   *   * @cond @@ -98,7 +98,7 @@ VolumeCatcherImpl *VolumeCatcherImpl::getInstance()  VolumeCatcherImpl::VolumeCatcherImpl()  {  	mVolume = 1.0;	// default to full volume -	mPan = 0.5;		// and center pan +	mPan = 0.0;		// and center pan  	ComponentDescription desc;  	desc.componentType = kAudioUnitType_Output; diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp index 8debe8fac6..fdff28c2c1 100644 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -33,262 +33,62 @@  #include "volume_catcher.h"  #include <windows.h> +#include "llsingleton.h" -// -// Abstracts a Win32 mixer line and associated state -// for muting and changing volume on a given output -// -class Mixer -{ -public: -	static Mixer* create(U32 index); -	~Mixer(); - -	void setMute(bool mute); -	void setVolume(F32 volume_left, F32 volume_right); - -private: -	// use create(index) to create a Mixer -	Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume); - -	HMIXER	mHandle;		 -	U32		mMuteControlID;		// handle to mixer controller for muting -	U32		mVolumeControlID;	// handle to mixer controller for changing volume -	U32		mMinVolume;			// value that specifies minimum volume as reported by mixer -	U32		mMaxVolume;			// value that specifies maximum volume as reported by mixer -}; - -// factory function that attempts to create a Mixer object associated with a given mixer line index -// returns NULL if creation failed -// static  -Mixer* Mixer::create(U32 index) -{ -	// get handle to mixer object -	HMIXER mixer_handle; -	MMRESULT result = mixerOpen( &mixer_handle, -							index,	 -							0,	// HWND to call when state changes - not used -							0,	// user data for callback - not used -							MIXER_OBJECTF_MIXER ); - -	if (result == MMSYSERR_NOERROR) -	{ -		MIXERLINE mixer_line; -		mixer_line.cbStruct = sizeof( MIXERLINE ); - -		// try speakers first -		mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; - -		MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), -								&mixer_line, -								MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); -		if (result != MMSYSERR_NOERROR) -		{	// failed - try headphones next -			mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES; -			result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), -									&mixer_line, -									MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); -		} - -		if (result == MMSYSERR_NOERROR) -		{	// successfully found mixer line object, now use it to get volume and mute controls - -			// reuse these objects to query for both volume and mute controls -			MIXERCONTROL mixer_control; -			MIXERLINECONTROLS mixer_line_controls; -			mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS ); -			mixer_line_controls.dwLineID = mixer_line.dwLineID; -			mixer_line_controls.cControls = 1; -			mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL ); -			mixer_line_controls.pamxctrl = &mixer_control; - -			// first, query for mute -			mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; - -			// get control id for mute controls -			result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ), -				&mixer_line_controls, -				MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE ); -			if (result == MMSYSERR_NOERROR ) -			{	// we have a mute controls.  Remember the mute control id and then query for  -				// volume controls using the same struct, but different dwControlType - -				U32 mute_control_id = mixer_control.dwControlID; -				mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; -				result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ), -					&mixer_line_controls, -					MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE ); - -				if (result == MMSYSERR_NOERROR) -				{	// we have both mute and volume controls for this mixer, so we're keeping it -					return new Mixer(mixer_handle,  -								mute_control_id,  -								mixer_control.dwControlID,  -								mixer_control.Bounds.dwMinimum,  -								mixer_control.Bounds.dwMaximum); -				} -			} -		} -	} - -	// if we got here, we didn't successfully create a Mixer object -	mixerClose(mixer_handle); -	return NULL; -} - -Mixer::Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume) -:	mHandle(handle), -	mMuteControlID(mute_control_id), -	mVolumeControlID(volume_control_id), -	mMinVolume(min_volume), -	mMaxVolume(max_volume) -{} - -Mixer::~Mixer() -{} - -// toggle mute for this mixer -// if mute is set, then volume level will be ignored -void Mixer::setMute(bool mute) -{ -	MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute }; -	MIXERCONTROLDETAILS mixer_control_details; -	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS ); -	mixer_control_details.dwControlID = mMuteControlID; -	mixer_control_details.cChannels = 1; -	mixer_control_details.cMultipleItems = 0; -	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN ); -	mixer_control_details.paDetails = &mixer_control_details_bool; - -	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ), -								 &mixer_control_details, -								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ); -} - -// set individual volume levels for left and right channels -// if mute is set, then these values will apply once mute is unset -void Mixer::setVolume(F32 volume_left, F32 volume_right) -{ -	// assuming pan is in range [-1, 1] set volume levels accordingly -	// if pan == -1 then	volume_left_mixer = volume_left	&& volume_right_mixer = 0 -	// if pan == 0 then		volume_left_mixer = volume_left	&& volume_right_mixer = volume_right -	// if pan == 1 then		volume_left_mixer = 0			&& volume_right_mixer = volume_right -	U32 volume_left_mixer = (U32) -							((F32)mMinVolume  -								+ (volume_left * ((F32)mMaxVolume - (F32)mMinVolume))); -	U32 volume_right_mixer = (U32) -							((F32)mMinVolume  -								+ (volume_right * ((F32)mMaxVolume - (F32)mMinVolume))); - -	// pass volume levels on to mixer -	MIXERCONTROLDETAILS_UNSIGNED mixer_control_details_unsigned[ 2 ] = { volume_left_mixer, volume_right_mixer }; -	MIXERCONTROLDETAILS mixer_control_details; -	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS ); -	mixer_control_details.dwControlID = mVolumeControlID; -	mixer_control_details.cChannels = 2; -	mixer_control_details.cMultipleItems = 0; -	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED ); -	mixer_control_details.paDetails = &mixer_control_details_unsigned; - -	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ), -								 &mixer_control_details, -								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ); -} - -class VolumeCatcherImpl +class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>  { +friend LLSingleton<VolumeCatcherImpl>;  public:  	void setVolume(F32 volume);  	void setPan(F32 pan); -	static VolumeCatcherImpl *getInstance();  private:  	// This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.  	VolumeCatcherImpl();  	~VolumeCatcherImpl(); -	static VolumeCatcherImpl *sInstance; -	 +	typedef void (*set_volume_func_t)(F32); +	typedef void (*set_mute_func_t)(bool); + +	set_volume_func_t mSetVolumeFunc; +	set_mute_func_t mSetMuteFunc; +  	F32 	mVolume;  	F32 	mPan; -	typedef std::vector<Mixer*> mixer_vector_t; -	mixer_vector_t	mMixers;  }; -VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL; - -VolumeCatcherImpl *VolumeCatcherImpl::getInstance() -{ -	if(!sInstance) -	{ -		sInstance = new VolumeCatcherImpl; -	} -	 -	return sInstance; -} -  VolumeCatcherImpl::VolumeCatcherImpl()  :	mVolume(1.0f),	// default volume is max  	mPan(0.f)		// default pan is centered  { -	OSVERSIONINFOEX	V = {sizeof(OSVERSIONINFOEX)};	//EX for NT 5.0 and later - -	::GetVersionEx((POSVERSIONINFO)&V); - -	// disable volume on XP and below -	if (V.dwPlatformId == VER_PLATFORM_WIN32_NT && V.dwMajorVersion >= 6) +	HMODULE handle = ::LoadLibrary(L"winmm.dll"); +	if(handle)  	{ -		// for each reported mixer "device", create a proxy object and add to list -		U32 num_mixers = mixerGetNumDevs(); -		for (U32 mixer_index = 0; mixer_index < num_mixers; ++mixer_index) -		{ -			Mixer* mixerp = Mixer::create(mixer_index); -			if (mixerp) -			{ -				mMixers.push_back(mixerp); -			} -		} +		mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); +		mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute");  	}  }  VolumeCatcherImpl::~VolumeCatcherImpl()  { -	for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end(); -		it != end_it; -		++it) -	{ -		delete *it; -		*it = NULL; -	}  }  void VolumeCatcherImpl::setVolume(F32 volume)  { -	F32 left_volume = volume * min(1.f, 1.f - mPan); -	F32 right_volume = volume * max(0.f, 1.f + mPan); +	//F32 left_volume = volume * min(1.f, 1.f - mPan); +	//F32 right_volume = volume * max(0.f, 1.f + mPan); -	for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end(); -		it != end_it; -		++it) -	{	// set volume levels and mute for each mixer -		// note that a muted mixer will ignore this volume level - -		(*it)->setVolume(left_volume, right_volume); -		 -		if (volume == 0.f && mVolume != 0.f) -		{ -			(*it)->setMute(true); -		} -		else if (mVolume == 0.f && volume != 0.f) -		{ -			(*it)->setMute(false); -		} - -	} -  	mVolume = volume; +	if (mSetMuteFunc) +	{ +		mSetMuteFunc(volume == 0.f); +	} +	if (mSetVolumeFunc) +	{ +		mSetVolumeFunc(mVolume); +	}  }  void VolumeCatcherImpl::setPan(F32 pan) diff --git a/indra/media_plugins/winmmshim/CMakeLists.txt b/indra/media_plugins/winmmshim/CMakeLists.txt new file mode 100644 index 0000000000..387214088f --- /dev/null +++ b/indra/media_plugins/winmmshim/CMakeLists.txt @@ -0,0 +1,34 @@ +# -*- cmake -*- + +project(winmm_shim) + +### winmm_shim + +set(winmm_shim_SOURCE_FILES +    forwarding_api.cpp +    winmm_shim.cpp +    ) + +set(winmm_shim_HEADER_FILES +    forwarding_api.h +    winmm.def +    ) + +list(APPEND winmm_shim_SOURCE_FILES ${winmm_shim_HEADER_FILES}) + +set_source_files_properties(${media_plugin_webkit_HEADER_FILES} +                            PROPERTIES HEADER_FILE_ONLY TRUE) + +add_library(winmm_shim +    SHARED +    ${winmm_shim_SOURCE_FILES} +) + +if (WINDOWS) +  set_target_properties( +    winmm_shim +    PROPERTIES +    LINK_FLAGS "/MANIFEST:NO" +    OUTPUT_NAME "winmm" +    ) +endif (WINDOWS) diff --git a/indra/media_plugins/winmmshim/forwarding_api.cpp b/indra/media_plugins/winmmshim/forwarding_api.cpp new file mode 100644 index 0000000000..c2f553dfef --- /dev/null +++ b/indra/media_plugins/winmmshim/forwarding_api.cpp @@ -0,0 +1,1460 @@ +/**  + * @file forwarding_api.cpp + * @brief forwards winmm API calls to real winmm.dll + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "forwarding_api.h" + +CloseDriver_type CloseDriver_orig; +OpenDriver_type OpenDriver_orig; +SendDriverMessage_type SendDriverMessage_orig; +DrvGetModuleHandle_type DrvGetModuleHandle_orig; +GetDriverModuleHandle_type GetDriverModuleHandle_orig; +DefDriverProc_type DefDriverProc_orig; +DriverCallback_type DriverCallback_orig; +mmsystemGetVersion_type mmsystemGetVersion_orig; +sndPlaySoundA_type sndPlaySoundA_orig; +sndPlaySoundW_type sndPlaySoundW_orig; +PlaySoundA_type PlaySoundA_orig; +PlaySoundW_type PlaySoundW_orig; +waveOutGetNumDevs_type waveOutGetNumDevs_orig; +waveOutGetDevCapsA_type waveOutGetDevCapsA_orig; +waveOutGetDevCapsW_type waveOutGetDevCapsW_orig; +waveOutGetVolume_type waveOutGetVolume_orig; +waveOutSetVolume_type waveOutSetVolume_orig; +waveOutGetErrorTextA_type waveOutGetErrorTextA_orig; +waveOutGetErrorTextW_type waveOutGetErrorTextW_orig; +waveOutOpen_type waveOutOpen_orig; +waveOutClose_type waveOutClose_orig; +waveOutPrepareHeader_type waveOutPrepareHeader_orig; +waveOutUnprepareHeader_type waveOutUnprepareHeader_orig; +waveOutWrite_type waveOutWrite_orig; +waveOutPause_type waveOutPause_orig; +waveOutRestart_type waveOutRestart_orig; +waveOutReset_type waveOutReset_orig; +waveOutBreakLoop_type waveOutBreakLoop_orig; +waveOutGetPosition_type waveOutGetPosition_orig; +waveOutGetPitch_type waveOutGetPitch_orig; +waveOutSetPitch_type waveOutSetPitch_orig; +waveOutGetPlaybackRate_type waveOutGetPlaybackRate_orig; +waveOutSetPlaybackRate_type waveOutSetPlaybackRate_orig; +waveOutGetID_type waveOutGetID_orig; +waveOutMessage_type waveOutMessage_orig; +waveInGetNumDevs_type waveInGetNumDevs_orig; +waveInGetDevCapsA_type waveInGetDevCapsA_orig; +waveInGetDevCapsW_type waveInGetDevCapsW_orig; +waveInGetErrorTextA_type waveInGetErrorTextA_orig; +waveInGetErrorTextW_type waveInGetErrorTextW_orig; +waveInOpen_type waveInOpen_orig; +waveInClose_type waveInClose_orig; +waveInPrepareHeader_type waveInPrepareHeader_orig; +waveInUnprepareHeader_type waveInUnprepareHeader_orig; +waveInAddBuffer_type waveInAddBuffer_orig; +waveInStart_type waveInStart_orig; +waveInStop_type waveInStop_orig; +waveInReset_type waveInReset_orig; +waveInGetPosition_type waveInGetPosition_orig; +waveInGetID_type waveInGetID_orig; +waveInMessage_type waveInMessage_orig; +midiOutGetNumDevs_type midiOutGetNumDevs_orig; +midiStreamOpen_type midiStreamOpen_orig; +midiStreamClose_type midiStreamClose_orig; +midiStreamProperty_type midiStreamProperty_orig; +midiStreamPosition_type midiStreamPosition_orig; +midiStreamOut_type midiStreamOut_orig; +midiStreamPause_type midiStreamPause_orig; +midiStreamRestart_type midiStreamRestart_orig; +midiStreamStop_type midiStreamStop_orig; +midiConnect_type midiConnect_orig; +midiDisconnect_type midiDisconnect_orig; +midiOutGetDevCapsA_type midiOutGetDevCapsA_orig; +midiOutGetDevCapsW_type midiOutGetDevCapsW_orig; +midiOutGetVolume_type midiOutGetVolume_orig; +midiOutSetVolume_type midiOutSetVolume_orig; +midiOutGetErrorTextA_type midiOutGetErrorTextA_orig; +midiOutGetErrorTextW_type midiOutGetErrorTextW_orig; +midiOutOpen_type midiOutOpen_orig; +midiOutClose_type midiOutClose_orig; +midiOutPrepareHeader_type midiOutPrepareHeader_orig; +midiOutUnprepareHeader_type midiOutUnprepareHeader_orig; +midiOutShortMsg_type midiOutShortMsg_orig; +midiOutLongMsg_type midiOutLongMsg_orig; +midiOutReset_type midiOutReset_orig; +midiOutCachePatches_type midiOutCachePatches_orig; +midiOutCacheDrumPatches_type midiOutCacheDrumPatches_orig; +midiOutGetID_type midiOutGetID_orig; +midiOutMessage_type midiOutMessage_orig; +midiInGetNumDevs_type midiInGetNumDevs_orig; +midiInGetDevCapsA_type midiInGetDevCapsA_orig; +midiInGetDevCapsW_type midiInGetDevCapsW_orig; +midiInGetErrorTextA_type midiInGetErrorTextA_orig; +midiInGetErrorTextW_type midiInGetErrorTextW_orig; +midiInOpen_type midiInOpen_orig; +midiInClose_type midiInClose_orig; +midiInPrepareHeader_type midiInPrepareHeader_orig; +midiInUnprepareHeader_type midiInUnprepareHeader_orig; +midiInAddBuffer_type midiInAddBuffer_orig; +midiInStart_type midiInStart_orig; +midiInStop_type midiInStop_orig; +midiInReset_type midiInReset_orig; +midiInGetID_type midiInGetID_orig; +midiInMessage_type midiInMessage_orig; +auxGetNumDevs_type auxGetNumDevs_orig; +auxGetDevCapsA_type auxGetDevCapsA_orig; +auxGetDevCapsW_type auxGetDevCapsW_orig; +auxSetVolume_type auxSetVolume_orig; +auxGetVolume_type auxGetVolume_orig; +auxOutMessage_type auxOutMessage_orig; +mixerGetNumDevs_type mixerGetNumDevs_orig; +mixerGetDevCapsA_type mixerGetDevCapsA_orig; +mixerGetDevCapsW_type mixerGetDevCapsW_orig; +mixerOpen_type mixerOpen_orig; +mixerClose_type mixerClose_orig; +mixerMessage_type mixerMessage_orig; +mixerGetLineInfoA_type mixerGetLineInfoA_orig; +mixerGetLineInfoW_type mixerGetLineInfoW_orig; +mixerGetID_type mixerGetID_orig; +mixerGetLineControlsA_type mixerGetLineControlsA_orig; +mixerGetLineControlsW_type mixerGetLineControlsW_orig; +mixerGetControlDetailsA_type mixerGetControlDetailsA_orig; +mixerGetControlDetailsW_type mixerGetControlDetailsW_orig; +mixerSetControlDetails_type mixerSetControlDetails_orig; +mmGetCurrentTask_type mmGetCurrentTask_orig; +mmTaskBlock_type mmTaskBlock_orig; +mmTaskCreate_type mmTaskCreate_orig; +mmTaskSignal_type mmTaskSignal_orig; +mmTaskYield_type mmTaskYield_orig; +timeGetSystemTime_type timeGetSystemTime_orig; +timeGetTime_type timeGetTime_orig; +timeSetEvent_type timeSetEvent_orig; +timeKillEvent_type timeKillEvent_orig; +timeGetDevCaps_type timeGetDevCaps_orig; +timeBeginPeriod_type timeBeginPeriod_orig; +timeEndPeriod_type timeEndPeriod_orig; +joyGetNumDevs_type joyGetNumDevs_orig; +joyConfigChanged_type joyConfigChanged_orig; +joyGetDevCapsA_type joyGetDevCapsA_orig; +joyGetDevCapsW_type joyGetDevCapsW_orig; +joyGetPos_type joyGetPos_orig; +joyGetPosEx_type joyGetPosEx_orig; +joyGetThreshold_type joyGetThreshold_orig; +joyReleaseCapture_type joyReleaseCapture_orig; +joySetCapture_type joySetCapture_orig; +joySetThreshold_type joySetThreshold_orig; +mmioStringToFOURCCA_type mmioStringToFOURCCA_orig; +mmioStringToFOURCCW_type mmioStringToFOURCCW_orig; +mmioInstallIOProcA_type mmioInstallIOProcA_orig; +mmioInstallIOProcW_type mmioInstallIOProcW_orig; +mmioOpenA_type mmioOpenA_orig; +mmioOpenW_type mmioOpenW_orig; +mmioRenameA_type mmioRenameA_orig; +mmioRenameW_type mmioRenameW_orig; +mmioClose_type mmioClose_orig; +mmioRead_type mmioRead_orig; +mmioWrite_type mmioWrite_orig; +mmioSeek_type mmioSeek_orig; +mmioGetInfo_type mmioGetInfo_orig; +mmioSetInfo_type mmioSetInfo_orig; +mmioSetBuffer_type mmioSetBuffer_orig; +mmioFlush_type mmioFlush_orig; +mmioAdvance_type mmioAdvance_orig; +mmioSendMessage_type mmioSendMessage_orig; +mmioDescend_type mmioDescend_orig; +mmioAscend_type mmioAscend_orig; +mmioCreateChunk_type mmioCreateChunk_orig; +mciSendCommandA_type mciSendCommandA_orig; +mciSendCommandW_type mciSendCommandW_orig; +mciSendStringA_type mciSendStringA_orig; +mciSendStringW_type mciSendStringW_orig; +mciGetDeviceIDA_type mciGetDeviceIDA_orig; +mciGetDeviceIDW_type mciGetDeviceIDW_orig; +mciGetDeviceIDFromElementIDA_type mciGetDeviceIDFromElementIDA_orig; +mciGetDeviceIDFromElementIDW_type mciGetDeviceIDFromElementIDW_orig; +mciGetDriverData_type mciGetDriverData_orig; +mciGetErrorStringA_type mciGetErrorStringA_orig; +mciGetErrorStringW_type mciGetErrorStringW_orig; +mciSetDriverData_type mciSetDriverData_orig; +mciDriverNotify_type mciDriverNotify_orig; +mciDriverYield_type mciDriverYield_orig; +mciSetYieldProc_type mciSetYieldProc_orig; +mciFreeCommandResource_type mciFreeCommandResource_orig; +mciGetCreatorTask_type mciGetCreatorTask_orig; +mciGetYieldProc_type mciGetYieldProc_orig; +mciLoadCommandResource_type mciLoadCommandResource_orig; +mciExecute_type mciExecute_orig; + +// grab pointers to function calls in the real DLL +void init_function_pointers(HMODULE winmm_handle) +{	 +	CloseDriver_orig = (CloseDriver_type)::GetProcAddress(winmm_handle, "CloseDriver"); +	OpenDriver_orig = (OpenDriver_type)::GetProcAddress(winmm_handle, "OpenDriver"); +	SendDriverMessage_orig = (SendDriverMessage_type)::GetProcAddress(winmm_handle, "SendDriverMessage"); +	DrvGetModuleHandle_orig = (DrvGetModuleHandle_type)::GetProcAddress(winmm_handle, "DrvGetModuleHandle"); +	GetDriverModuleHandle_orig = (GetDriverModuleHandle_type)::GetProcAddress(winmm_handle, "GetDriverModuleHandle"); +	DefDriverProc_orig = (DefDriverProc_type)::GetProcAddress(winmm_handle, "DefDriverProc"); +	DriverCallback_orig = (DriverCallback_type)::GetProcAddress(winmm_handle, "DriverCallback"); +	mmsystemGetVersion_orig = (mmsystemGetVersion_type)::GetProcAddress(winmm_handle, "mmsystemGetVersion"); +	sndPlaySoundA_orig = (sndPlaySoundA_type)::GetProcAddress(winmm_handle, "sndPlaySoundA"); +	sndPlaySoundW_orig = (sndPlaySoundW_type)::GetProcAddress(winmm_handle, "sndPlaySoundW"); +	PlaySoundA_orig = (PlaySoundA_type)::GetProcAddress(winmm_handle, "PlaySoundA"); +	PlaySoundW_orig = (PlaySoundW_type)::GetProcAddress(winmm_handle, "PlaySoundW"); +	waveOutGetNumDevs_orig = (waveOutGetNumDevs_type)::GetProcAddress(winmm_handle, "waveOutGetNumDevs"); +	waveOutGetDevCapsA_orig = (waveOutGetDevCapsA_type)::GetProcAddress(winmm_handle, "waveOutGetDevCapsA"); +	waveOutGetDevCapsW_orig = (waveOutGetDevCapsW_type)::GetProcAddress(winmm_handle, "waveOutGetDevCapsW"); +	waveOutGetVolume_orig = (waveOutGetVolume_type)::GetProcAddress(winmm_handle, "waveOutGetVolume"); +	waveOutSetVolume_orig = (waveOutSetVolume_type)::GetProcAddress(winmm_handle, "waveOutSetVolume"); +	waveOutGetErrorTextA_orig = (waveOutGetErrorTextA_type)::GetProcAddress(winmm_handle, "waveOutGetErrorTextA"); +	waveOutGetErrorTextW_orig = (waveOutGetErrorTextW_type)::GetProcAddress(winmm_handle, "waveOutGetErrorTextW"); +	waveOutOpen_orig = (waveOutOpen_type)::GetProcAddress(winmm_handle, "waveOutOpen"); +	waveOutClose_orig = (waveOutClose_type)::GetProcAddress(winmm_handle, "waveOutClose"); +	waveOutPrepareHeader_orig = (waveOutPrepareHeader_type)::GetProcAddress(winmm_handle, "waveOutPrepareHeader"); +	waveOutUnprepareHeader_orig = (waveOutUnprepareHeader_type)::GetProcAddress(winmm_handle, "waveOutUnprepareHeader"); +	waveOutWrite_orig = (waveOutWrite_type)::GetProcAddress(winmm_handle, "waveOutWrite"); +	waveOutPause_orig = (waveOutPause_type)::GetProcAddress(winmm_handle, "waveOutPause"); +	waveOutRestart_orig = (waveOutRestart_type)::GetProcAddress(winmm_handle, "waveOutRestart"); +	waveOutReset_orig = (waveOutReset_type)::GetProcAddress(winmm_handle, "waveOutReset"); +	waveOutBreakLoop_orig = (waveOutBreakLoop_type)::GetProcAddress(winmm_handle, "waveOutBreakLoop"); +	waveOutGetPosition_orig = (waveOutGetPosition_type)::GetProcAddress(winmm_handle, "waveOutGetPosition"); +	waveOutGetPitch_orig = (waveOutGetPitch_type)::GetProcAddress(winmm_handle, "waveOutGetPitch"); +	waveOutSetPitch_orig = (waveOutSetPitch_type)::GetProcAddress(winmm_handle, "waveOutSetPitch"); +	waveOutGetPlaybackRate_orig = (waveOutGetPlaybackRate_type)::GetProcAddress(winmm_handle, "waveOutGetPlaybackRate"); +	waveOutSetPlaybackRate_orig = (waveOutSetPlaybackRate_type)::GetProcAddress(winmm_handle, "waveOutSetPlaybackRate"); +	waveOutGetID_orig = (waveOutGetID_type)::GetProcAddress(winmm_handle, "waveOutGetID"); +	waveOutMessage_orig = (waveOutMessage_type)::GetProcAddress(winmm_handle, "waveOutMessage"); +	waveInGetNumDevs_orig = (waveInGetNumDevs_type)::GetProcAddress(winmm_handle, "waveInGetNumDevs"); +	waveInGetDevCapsA_orig = (waveInGetDevCapsA_type)::GetProcAddress(winmm_handle, "waveInGetDevCapsA"); +	waveInGetDevCapsW_orig = (waveInGetDevCapsW_type)::GetProcAddress(winmm_handle, "waveInGetDevCapsW"); +	waveInGetErrorTextA_orig = (waveInGetErrorTextA_type)::GetProcAddress(winmm_handle, "waveInGetErrorTextA"); +	waveInGetErrorTextW_orig = (waveInGetErrorTextW_type)::GetProcAddress(winmm_handle, "waveInGetErrorTextW"); +	waveInOpen_orig = (waveInOpen_type)::GetProcAddress(winmm_handle, "waveInOpen"); +	waveInClose_orig = (waveInClose_type)::GetProcAddress(winmm_handle, "waveInClose"); +	waveInPrepareHeader_orig = (waveInPrepareHeader_type)::GetProcAddress(winmm_handle, "waveInPrepareHeader"); +	waveInUnprepareHeader_orig = (waveInUnprepareHeader_type)::GetProcAddress(winmm_handle, "waveInUnprepareHeader"); +	waveInAddBuffer_orig = (waveInAddBuffer_type)::GetProcAddress(winmm_handle, "waveInAddBuffer"); +	waveInStart_orig = (waveInStart_type)::GetProcAddress(winmm_handle, "waveInStart"); +	waveInStop_orig = (waveInStop_type)::GetProcAddress(winmm_handle, "waveInStop"); +	waveInReset_orig = (waveInReset_type)::GetProcAddress(winmm_handle, "waveInReset"); +	waveInGetPosition_orig = (waveInGetPosition_type)::GetProcAddress(winmm_handle, "waveInGetPosition"); +	waveInGetID_orig = (waveInGetID_type)::GetProcAddress(winmm_handle, "waveInGetID"); +	waveInMessage_orig = (waveInMessage_type)::GetProcAddress(winmm_handle, "waveInMessage"); +	midiOutGetNumDevs_orig = (midiOutGetNumDevs_type)::GetProcAddress(winmm_handle, "midiOutGetNumDevs"); +	midiStreamOpen_orig = (midiStreamOpen_type)::GetProcAddress(winmm_handle, "midiStreamOpen"); +	midiStreamClose_orig = (midiStreamClose_type)::GetProcAddress(winmm_handle, "midiStreamClose"); +	midiStreamProperty_orig = (midiStreamProperty_type)::GetProcAddress(winmm_handle, "midiStreamProperty"); +	midiStreamPosition_orig = (midiStreamPosition_type)::GetProcAddress(winmm_handle, "midiStreamPosition"); +	midiStreamOut_orig = (midiStreamOut_type)::GetProcAddress(winmm_handle, "midiStreamOut"); +	midiStreamPause_orig = (midiStreamPause_type)::GetProcAddress(winmm_handle, "midiStreamPause"); +	midiStreamRestart_orig = (midiStreamRestart_type)::GetProcAddress(winmm_handle, "midiStreamRestart"); +	midiStreamStop_orig = (midiStreamStop_type)::GetProcAddress(winmm_handle, "midiStreamStop"); +	midiConnect_orig = (midiConnect_type)::GetProcAddress(winmm_handle, "midiConnect"); +	midiDisconnect_orig = (midiDisconnect_type)::GetProcAddress(winmm_handle, "midiDisconnect"); +	midiOutGetDevCapsA_orig = (midiOutGetDevCapsA_type)::GetProcAddress(winmm_handle, "midiOutGetDevCapsA"); +	midiOutGetDevCapsW_orig = (midiOutGetDevCapsW_type)::GetProcAddress(winmm_handle, "midiOutGetDevCapsW"); +	midiOutGetVolume_orig = (midiOutGetVolume_type)::GetProcAddress(winmm_handle, "midiOutGetVolume"); +	midiOutSetVolume_orig = (midiOutSetVolume_type)::GetProcAddress(winmm_handle, "midiOutSetVolume"); +	midiOutGetErrorTextA_orig = (midiOutGetErrorTextA_type)::GetProcAddress(winmm_handle, "midiOutGetErrorTextA"); +	midiOutGetErrorTextW_orig = (midiOutGetErrorTextW_type)::GetProcAddress(winmm_handle, "midiOutGetErrorTextW"); +	midiOutOpen_orig = (midiOutOpen_type)::GetProcAddress(winmm_handle, "midiOutOpen"); +	midiOutClose_orig = (midiOutClose_type)::GetProcAddress(winmm_handle, "midiOutClose"); +	midiOutPrepareHeader_orig = (midiOutPrepareHeader_type)::GetProcAddress(winmm_handle, "midiOutPrepareHeader"); +	midiOutUnprepareHeader_orig = (midiOutUnprepareHeader_type)::GetProcAddress(winmm_handle, "midiOutUnprepareHeader"); +	midiOutShortMsg_orig = (midiOutShortMsg_type)::GetProcAddress(winmm_handle, "midiOutShortMsg"); +	midiOutLongMsg_orig = (midiOutLongMsg_type)::GetProcAddress(winmm_handle, "midiOutLongMsg"); +	midiOutReset_orig = (midiOutReset_type)::GetProcAddress(winmm_handle, "midiOutReset"); +	midiOutCachePatches_orig = (midiOutCachePatches_type)::GetProcAddress(winmm_handle, "midiOutCachePatches"); +	midiOutCacheDrumPatches_orig = (midiOutCacheDrumPatches_type)::GetProcAddress(winmm_handle, "midiOutCacheDrumPatches"); +	midiOutGetID_orig = (midiOutGetID_type)::GetProcAddress(winmm_handle, "midiOutGetID"); +	midiOutMessage_orig = (midiOutMessage_type)::GetProcAddress(winmm_handle, "midiOutMessage"); +	midiInGetNumDevs_orig = (midiInGetNumDevs_type)::GetProcAddress(winmm_handle, "midiInGetNumDevs"); +	midiInGetDevCapsA_orig = (midiInGetDevCapsA_type)::GetProcAddress(winmm_handle, "midiInGetDevCapsA"); +	midiInGetDevCapsW_orig = (midiInGetDevCapsW_type)::GetProcAddress(winmm_handle, "midiInGetDevCapsW"); +	midiInGetErrorTextA_orig = (midiInGetErrorTextA_type)::GetProcAddress(winmm_handle, "midiInGetErrorTextA"); +	midiInGetErrorTextW_orig = (midiInGetErrorTextW_type)::GetProcAddress(winmm_handle, "midiInGetErrorTextW"); +	midiInOpen_orig = (midiInOpen_type)::GetProcAddress(winmm_handle, "midiInOpen"); +	midiInClose_orig = (midiInClose_type)::GetProcAddress(winmm_handle, "midiInClose"); +	midiInPrepareHeader_orig = (midiInPrepareHeader_type)::GetProcAddress(winmm_handle, "midiInPrepareHeader"); +	midiInUnprepareHeader_orig = (midiInUnprepareHeader_type)::GetProcAddress(winmm_handle, "midiInUnprepareHeader"); +	midiInAddBuffer_orig = (midiInAddBuffer_type)::GetProcAddress(winmm_handle, "midiInAddBuffer"); +	midiInStart_orig = (midiInStart_type)::GetProcAddress(winmm_handle, "midiInStart"); +	midiInStop_orig = (midiInStop_type)::GetProcAddress(winmm_handle, "midiInStop"); +	midiInReset_orig = (midiInReset_type)::GetProcAddress(winmm_handle, "midiInReset"); +	midiInGetID_orig = (midiInGetID_type)::GetProcAddress(winmm_handle, "midiInGetID"); +	midiInMessage_orig = (midiInMessage_type)::GetProcAddress(winmm_handle, "midiInMessage"); +	auxGetNumDevs_orig = (auxGetNumDevs_type)::GetProcAddress(winmm_handle, "auxGetNumDevs"); +	auxGetDevCapsA_orig = (auxGetDevCapsA_type)::GetProcAddress(winmm_handle, "auxGetDevCapsA"); +	auxGetDevCapsW_orig = (auxGetDevCapsW_type)::GetProcAddress(winmm_handle, "auxGetDevCapsW"); +	auxSetVolume_orig = (auxSetVolume_type)::GetProcAddress(winmm_handle, "auxSetVolume"); +	auxGetVolume_orig = (auxGetVolume_type)::GetProcAddress(winmm_handle, "auxGetVolume"); +	auxOutMessage_orig = (auxOutMessage_type)::GetProcAddress(winmm_handle, "auxOutMessage"); +	mixerGetNumDevs_orig = (mixerGetNumDevs_type)::GetProcAddress(winmm_handle, "mixerGetNumDevs"); +	mixerGetDevCapsA_orig = (mixerGetDevCapsA_type)::GetProcAddress(winmm_handle, "mixerGetDevCapsA"); +	mixerGetDevCapsW_orig = (mixerGetDevCapsW_type)::GetProcAddress(winmm_handle, "mixerGetDevCapsW"); +	mixerOpen_orig = (mixerOpen_type)::GetProcAddress(winmm_handle, "mixerOpen"); +	mixerClose_orig = (mixerClose_type)::GetProcAddress(winmm_handle, "mixerClose"); +	mixerMessage_orig = (mixerMessage_type)::GetProcAddress(winmm_handle, "mixerMessage"); +	mixerGetLineInfoA_orig = (mixerGetLineInfoA_type)::GetProcAddress(winmm_handle, "mixerGetLineInfoA"); +	mixerGetLineInfoW_orig = (mixerGetLineInfoW_type)::GetProcAddress(winmm_handle, "mixerGetLineInfoW"); +	mixerGetID_orig = (mixerGetID_type)::GetProcAddress(winmm_handle, "mixerGetID"); +	mixerGetLineControlsA_orig = (mixerGetLineControlsA_type)::GetProcAddress(winmm_handle, "mixerGetLineControlsA"); +	mixerGetLineControlsW_orig = (mixerGetLineControlsW_type)::GetProcAddress(winmm_handle, "mixerGetLineControlsW"); +	mixerGetControlDetailsA_orig = (mixerGetControlDetailsA_type)::GetProcAddress(winmm_handle, "mixerGetControlDetailsA"); +	mixerGetControlDetailsW_orig = (mixerGetControlDetailsW_type)::GetProcAddress(winmm_handle, "mixerGetControlDetailsW"); +	mixerSetControlDetails_orig = (mixerSetControlDetails_type)::GetProcAddress(winmm_handle, "mixerSetControlDetails"); +	mmGetCurrentTask_orig = (mmGetCurrentTask_type)::GetProcAddress(winmm_handle, "mmGetCurrentTask"); +	mmTaskBlock_orig = (mmTaskBlock_type)::GetProcAddress(winmm_handle, "mmTaskBlock"); +	mmTaskCreate_orig = (mmTaskCreate_type)::GetProcAddress(winmm_handle, "mmTaskCreate"); +	mmTaskSignal_orig = (mmTaskSignal_type)::GetProcAddress(winmm_handle, "mmTaskSignal"); +	mmTaskYield_orig = (mmTaskYield_type)::GetProcAddress(winmm_handle, "mmTaskYield"); +	timeGetSystemTime_orig = (timeGetSystemTime_type)::GetProcAddress(winmm_handle, "timeGetSystemTime"); +	timeGetTime_orig = (timeGetTime_type)::GetProcAddress(winmm_handle, "timeGetTime"); +	timeSetEvent_orig = (timeSetEvent_type)::GetProcAddress(winmm_handle, "timeSetEvent"); +	timeKillEvent_orig = (timeKillEvent_type)::GetProcAddress(winmm_handle, "timeKillEvent"); +	timeGetDevCaps_orig = (timeGetDevCaps_type)::GetProcAddress(winmm_handle, "timeGetDevCaps"); +	timeBeginPeriod_orig = (timeBeginPeriod_type)::GetProcAddress(winmm_handle, "timeBeginPeriod"); +	timeEndPeriod_orig = (timeEndPeriod_type)::GetProcAddress(winmm_handle, "timeEndPeriod"); +	joyGetNumDevs_orig = (joyGetNumDevs_type)::GetProcAddress(winmm_handle, "joyGetNumDevs"); +	joyConfigChanged_orig = (joyConfigChanged_type)::GetProcAddress(winmm_handle, "joyConfigChanged"); +	joyGetDevCapsA_orig = (joyGetDevCapsA_type)::GetProcAddress(winmm_handle, "joyGetDevCapsA"); +	joyGetDevCapsW_orig = (joyGetDevCapsW_type)::GetProcAddress(winmm_handle, "joyGetDevCapsW"); +	joyGetPos_orig = (joyGetPos_type)::GetProcAddress(winmm_handle, "joyGetPos"); +	joyGetPosEx_orig = (joyGetPosEx_type)::GetProcAddress(winmm_handle, "joyGetPosEx"); +	joyGetThreshold_orig = (joyGetThreshold_type)::GetProcAddress(winmm_handle, "joyGetThreshold"); +	joyReleaseCapture_orig = (joyReleaseCapture_type)::GetProcAddress(winmm_handle, "joyReleaseCapture"); +	joySetCapture_orig = (joySetCapture_type)::GetProcAddress(winmm_handle, "joySetCapture"); +	joySetThreshold_orig = (joySetThreshold_type)::GetProcAddress(winmm_handle, "joySetThreshold"); +	mciDriverNotify_orig = (mciDriverNotify_type)::GetProcAddress(winmm_handle, "mciDriverNotify"); +	mciDriverYield_orig = (mciDriverYield_type)::GetProcAddress(winmm_handle, "mciDriverYield"); +	mmioStringToFOURCCA_orig = (mmioStringToFOURCCA_type)::GetProcAddress(winmm_handle, "mmioStringToFOURCCA"); +	mmioStringToFOURCCW_orig = (mmioStringToFOURCCW_type)::GetProcAddress(winmm_handle, "mmioStringToFOURCCW"); +	mmioInstallIOProcA_orig = (mmioInstallIOProcA_type)::GetProcAddress(winmm_handle, "mmioInstallIOProcA"); +	mmioInstallIOProcW_orig = (mmioInstallIOProcW_type)::GetProcAddress(winmm_handle, "mmioInstallIOProcW"); +	mmioOpenA_orig = (mmioOpenA_type)::GetProcAddress(winmm_handle, "mmioOpenA"); +	mmioOpenW_orig = (mmioOpenW_type)::GetProcAddress(winmm_handle, "mmioOpenW"); +	mmioRenameA_orig = (mmioRenameA_type)::GetProcAddress(winmm_handle, "mmioRenameA"); +	mmioRenameW_orig = (mmioRenameW_type)::GetProcAddress(winmm_handle, "mmioRenameW"); +	mmioClose_orig = (mmioClose_type)::GetProcAddress(winmm_handle, "mmioClose"); +	mmioRead_orig = (mmioRead_type)::GetProcAddress(winmm_handle, "mmioRead"); +	mmioWrite_orig = (mmioWrite_type)::GetProcAddress(winmm_handle, "mmioWrite"); +	mmioSeek_orig = (mmioSeek_type)::GetProcAddress(winmm_handle, "mmioSeek"); +	mmioGetInfo_orig = (mmioGetInfo_type)::GetProcAddress(winmm_handle, "mmioGetInfo"); +	mmioSetInfo_orig = (mmioSetInfo_type)::GetProcAddress(winmm_handle, "mmioSetInfo"); +	mmioSetBuffer_orig = (mmioSetBuffer_type)::GetProcAddress(winmm_handle, "mmioSetBuffer"); +	mmioFlush_orig = (mmioFlush_type)::GetProcAddress(winmm_handle, "mmioFlush"); +	mmioAdvance_orig = (mmioAdvance_type)::GetProcAddress(winmm_handle, "mmioAdvance"); +	mmioSendMessage_orig = (mmioSendMessage_type)::GetProcAddress(winmm_handle, "mmioSendMessage"); +	mmioDescend_orig = (mmioDescend_type)::GetProcAddress(winmm_handle, "mmioDescend"); +	mmioAscend_orig = (mmioAscend_type)::GetProcAddress(winmm_handle, "mmioAscend"); +	mmioCreateChunk_orig = (mmioCreateChunk_type)::GetProcAddress(winmm_handle, "mmioCreateChunk"); +	mciSendCommandA_orig = (mciSendCommandA_type)::GetProcAddress(winmm_handle, "mciSendCommandA"); +	mciSendCommandW_orig = (mciSendCommandW_type)::GetProcAddress(winmm_handle, "mciSendCommandW"); +	mciSendStringA_orig = (mciSendStringA_type)::GetProcAddress(winmm_handle, "mciSendStringA"); +	mciSendStringW_orig = (mciSendStringW_type)::GetProcAddress(winmm_handle, "mciSendStringW"); +	mciGetDeviceIDA_orig = (mciGetDeviceIDA_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDA"); +	mciGetDeviceIDW_orig = (mciGetDeviceIDW_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDW"); +	mciGetDeviceIDFromElementIDA_orig = (mciGetDeviceIDFromElementIDA_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDFromElementIDA"); +	mciGetDeviceIDFromElementIDW_orig = (mciGetDeviceIDFromElementIDW_type)::GetProcAddress(winmm_handle, "mciGetDeviceIDFromElementIDW"); +	mciGetDriverData_orig = (mciGetDriverData_type)::GetProcAddress(winmm_handle, "mciGetDriverData"); +	mciGetErrorStringA_orig = (mciGetErrorStringA_type)::GetProcAddress(winmm_handle, "mciGetErrorStringA"); +	mciGetErrorStringW_orig = (mciGetErrorStringW_type)::GetProcAddress(winmm_handle, "mciGetErrorStringW"); +	mciSetDriverData_orig = (mciSetDriverData_type)::GetProcAddress(winmm_handle, "mciSetDriverData"); +	mciSetYieldProc_orig = (mciSetYieldProc_type)::GetProcAddress(winmm_handle, "mciSetYieldProc"); +	mciFreeCommandResource_orig = (mciFreeCommandResource_type)::GetProcAddress(winmm_handle, "mciFreeCommandResource"); +	mciGetCreatorTask_orig = (mciGetCreatorTask_type)::GetProcAddress(winmm_handle, "mciGetCreatorTask"); +	mciGetYieldProc_orig = (mciGetYieldProc_type)::GetProcAddress(winmm_handle, "mciGetYieldProc"); +	mciLoadCommandResource_orig = (mciLoadCommandResource_type)::GetProcAddress(winmm_handle, "mciLoadCommandResource"); +	mciExecute_orig = (mciExecute_type)::GetProcAddress(winmm_handle, "mciExecute"); +} + +extern "C" { +	LRESULT   WINAPI CloseDriver( HDRVR hDriver, LPARAM lParam1, LPARAM lParam2) +	{ +		//OutputDebugString(L"CloseDriver\n"); +		return CloseDriver_orig( hDriver, lParam1, lParam2); +	} + +	HDRVR     WINAPI OpenDriver( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2) +	{ +		//OutputDebugString(L"OpenDriver\n"); +		return OpenDriver_orig( szDriverName, szSectionName, lParam2); +	} + +	LRESULT   WINAPI SendDriverMessage( HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2) +	{ +		//OutputDebugString(L"SendDriverMessage\n"); +		return SendDriverMessage_orig( hDriver, message, lParam1, lParam2); +	} + +	HMODULE   WINAPI DrvGetModuleHandle( HDRVR hDriver) +	{ +		//OutputDebugString(L"DrvGetModuleHandle\n"); +		return DrvGetModuleHandle_orig( hDriver); +	} + +	HMODULE   WINAPI GetDriverModuleHandle( HDRVR hDriver) +	{ +		//OutputDebugString(L"GetDriverModuleHandle\n"); +		return GetDriverModuleHandle_orig( hDriver); +	} + +	LRESULT   WINAPI DefDriverProc( DWORD_PTR dwDriverIdentifier, HDRVR hdrvr, UINT uMsg, LPARAM lParam1, LPARAM lParam2) +	{ +		//OutputDebugString(L"DefDriverProc\n"); +		return DefDriverProc_orig( dwDriverIdentifier, hdrvr, uMsg, lParam1, lParam2); +	} + +	BOOL WINAPI DriverCallback( DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) +	{ +		//OutputDebugString(L"DriverCallback\n"); +		return DriverCallback_orig(dwCallBack, dwFlags, hdrvr, msg, dwUser, dwParam1, dwParam2); +	} + +	UINT WINAPI mmsystemGetVersion(void) +	{ +		//OutputDebugString(L"mmsystemGetVersion\n"); +		return mmsystemGetVersion_orig(); +	} + +	BOOL WINAPI sndPlaySoundA( LPCSTR pszSound, UINT fuSound) +	{ +		//OutputDebugString(L"sndPlaySoundA\n"); +		return sndPlaySoundA_orig( pszSound, fuSound); +	} + +	BOOL WINAPI sndPlaySoundW( LPCWSTR pszSound, UINT fuSound) +	{ +		//OutputDebugString(L"sndPlaySoundW\n"); +		return sndPlaySoundW_orig( pszSound, fuSound); +	} + +	BOOL WINAPI PlaySoundA( LPCSTR pszSound, HMODULE hmod, DWORD fdwSound) +	{ +		//OutputDebugString(L"PlaySoundA\n"); +		return PlaySoundA_orig( pszSound, hmod, fdwSound); +	} + +	BOOL WINAPI PlaySoundW( LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound) +	{ +		//OutputDebugString(L"PlaySoundW\n"); +		return PlaySoundW_orig( pszSound, hmod, fdwSound); +	} + +	UINT WINAPI waveOutGetNumDevs(void) +	{ +		//OutputDebugString(L"waveOutGetNumDevs\n"); +		return waveOutGetNumDevs_orig(); +	} + +	MMRESULT WINAPI waveOutGetDevCapsA( UINT_PTR uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc) +	{ +		//OutputDebugString(L"waveOutGetDevCapsA\n"); +		return waveOutGetDevCapsA_orig( uDeviceID, pwoc, cbwoc); +	} + +	MMRESULT WINAPI waveOutGetDevCapsW( UINT_PTR uDeviceID, LPWAVEOUTCAPSW pwoc, UINT cbwoc) +	{ +		//OutputDebugString(L"waveOutGetDevCapsW\n"); +		return waveOutGetDevCapsW_orig( uDeviceID, pwoc, cbwoc); +	} + + +	MMRESULT WINAPI waveOutGetVolume( HWAVEOUT hwo, LPDWORD pdwVolume) +	{ +		//OutputDebugString(L"waveOutGetVolume\n"); +		return waveOutGetVolume_orig( hwo, pdwVolume); +	} + +	MMRESULT WINAPI waveOutSetVolume( HWAVEOUT hwo, DWORD dwVolume) +	{ +		//OutputDebugString(L"waveOutSetVolume\n"); +		return waveOutSetVolume_orig( hwo, dwVolume); +	} + +	MMRESULT WINAPI waveOutGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"waveOutGetErrorTextA\n"); +		return waveOutGetErrorTextA_orig( mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI waveOutGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"waveOutGetErrorTextW\n"); +		return waveOutGetErrorTextW_orig( mmrError, pszText, cchText); +	} + +	//MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	//{ +	//	//OutputDebugString(L"waveOutGetErrorTextW\n"); +	//	return waveOutOpen_orig( phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen); +	//} + +	//MMRESULT WINAPI waveOutClose( HWAVEOUT hwo) +	//{ +	//	//OutputDebugString(L"waveOutGetErrorTextW\n"); +	//	return waveOutClose_orig( hwo ); +	//} + +	MMRESULT WINAPI waveOutPrepareHeader( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) +	{ +		//OutputDebugString(L"waveOutPrepareHeader\n"); +		return waveOutPrepareHeader_orig( hwo, pwh, cbwh); +	} + +	MMRESULT WINAPI waveOutUnprepareHeader( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) +	{ +		//OutputDebugString(L"waveOutUnprepareHeader\n"); +		return waveOutUnprepareHeader_orig( hwo, pwh, cbwh); +	} + + +	//MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) +	//{ +	//	//OutputDebugString(L"waveOutUnprepareHeader\n"); +	//	return waveOutWrite_orig( hwo, pwh, cbwh); +	//} + +	MMRESULT WINAPI waveOutPause( HWAVEOUT hwo) +	{ +		//OutputDebugString(L"waveOutPause\n"); +		return waveOutPause_orig( hwo); +	} + +	MMRESULT WINAPI waveOutRestart( HWAVEOUT hwo) +	{ +		//OutputDebugString(L"waveOutRestart\n"); +		return waveOutRestart_orig( hwo); +	} + +	MMRESULT WINAPI waveOutReset( HWAVEOUT hwo) +	{ +		//OutputDebugString(L"waveOutReset\n"); +		return waveOutReset_orig( hwo); +	} + +	MMRESULT WINAPI waveOutBreakLoop( HWAVEOUT hwo) +	{ +		//OutputDebugString(L"waveOutBreakLoop\n"); +		return waveOutBreakLoop_orig( hwo); +	} + +	MMRESULT WINAPI waveOutGetPosition( HWAVEOUT hwo, LPMMTIME pmmt, UINT cbmmt) +	{ +		//OutputDebugString(L"waveOutGetPosition\n"); +		return waveOutGetPosition_orig( hwo, pmmt, cbmmt); +	} + +	MMRESULT WINAPI waveOutGetPitch( HWAVEOUT hwo, LPDWORD pdwPitch) +	{ +		//OutputDebugString(L"waveOutGetPitch\n"); +		return waveOutGetPitch_orig( hwo, pdwPitch); +	} + +	MMRESULT WINAPI waveOutSetPitch( HWAVEOUT hwo, DWORD dwPitch) +	{ +		//OutputDebugString(L"waveOutSetPitch\n"); +		return waveOutSetPitch_orig( hwo, dwPitch); +	} + +	MMRESULT WINAPI waveOutGetPlaybackRate( HWAVEOUT hwo, LPDWORD pdwRate) +	{ +		//OutputDebugString(L"waveOutGetPlaybackRate\n"); +		return waveOutGetPlaybackRate_orig( hwo, pdwRate); +	} + +	MMRESULT WINAPI waveOutSetPlaybackRate( HWAVEOUT hwo, DWORD dwRate) +	{ +		//OutputDebugString(L"waveOutSetPlaybackRate\n"); +		return waveOutSetPlaybackRate_orig( hwo, dwRate); +	} + +	MMRESULT WINAPI waveOutGetID( HWAVEOUT hwo, LPUINT puDeviceID) +	{ +		//OutputDebugString(L"waveOutGetID\n"); +		return waveOutGetID_orig( hwo, puDeviceID); +	} + +	MMRESULT WINAPI waveOutMessage( HWAVEOUT hwo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2) +	{ +		//OutputDebugString(L"waveOutMessage\n"); +		return waveOutMessage_orig( hwo, uMsg, dw1, dw2); +	} + +	UINT WINAPI waveInGetNumDevs(void) +	{ +		//OutputDebugString(L"waveInGetNumDevs\n"); +		return waveInGetNumDevs_orig(); +	} + +	MMRESULT WINAPI waveInGetDevCapsA( UINT_PTR uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic) +	{ +		//OutputDebugString(L"waveInGetDevCapsA\n"); +		return waveInGetDevCapsA_orig( uDeviceID, pwic, cbwic); +	} + +	MMRESULT WINAPI waveInGetDevCapsW( UINT_PTR uDeviceID, LPWAVEINCAPSW pwic, UINT cbwic) +	{ +		//OutputDebugString(L"waveInGetDevCapsW\n"); +		return waveInGetDevCapsW_orig( uDeviceID, pwic, cbwic); +	} + +	MMRESULT WINAPI waveInGetErrorTextA(MMRESULT mmrError, LPSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"waveInGetErrorTextA\n"); +		return waveInGetErrorTextA_orig(mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI waveInGetErrorTextW(MMRESULT mmrError, LPWSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"waveInGetErrorTextW\n"); +		return waveInGetErrorTextW_orig(mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI waveInOpen( LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		//OutputDebugString(L"waveInOpen\n"); +		return waveInOpen_orig(phwi, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen); +	} + +	MMRESULT WINAPI waveInClose( HWAVEIN hwi) +	{ +		//OutputDebugString(L"waveInClose\n"); +		return waveInClose_orig( hwi); +	} + +	MMRESULT WINAPI waveInPrepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh) +	{ +		//OutputDebugString(L"waveInPrepareHeader\n"); +		return waveInPrepareHeader_orig( hwi, pwh, cbwh); +	} + +	MMRESULT WINAPI waveInUnprepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh) +	{ +		//OutputDebugString(L"waveInUnprepareHeader\n"); +		return waveInUnprepareHeader_orig( hwi, pwh, cbwh); +	} + +	MMRESULT WINAPI waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh) +	{ +		//OutputDebugString(L"waveInAddBuffer\n"); +		return waveInAddBuffer_orig( hwi, pwh, cbwh); +	} + +	MMRESULT WINAPI waveInStart( HWAVEIN hwi) +	{ +		//OutputDebugString(L"waveInStart\n"); +		return waveInStart_orig( hwi); +	} + +	MMRESULT WINAPI waveInStop( HWAVEIN hwi) +	{ +		//OutputDebugString(L"waveInStop\n"); +		return waveInStop_orig(hwi); +	} + +	MMRESULT WINAPI waveInReset( HWAVEIN hwi) +	{ +		//OutputDebugString(L"waveInReset\n"); +		return waveInReset_orig(hwi); +	} + +	MMRESULT WINAPI waveInGetPosition( HWAVEIN hwi, LPMMTIME pmmt, UINT cbmmt) +	{ +		//OutputDebugString(L"waveInGetPosition\n"); +		return waveInGetPosition_orig( hwi, pmmt, cbmmt); +	} + +	MMRESULT WINAPI waveInGetID( HWAVEIN hwi, LPUINT puDeviceID) +	{ +		//OutputDebugString(L"waveInGetID\n"); +		return waveInGetID_orig( hwi, puDeviceID); +	} + +	MMRESULT WINAPI waveInMessage( HWAVEIN hwi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2) +	{ +		//OutputDebugString(L"waveInMessage\n"); +		return waveInMessage_orig( hwi, uMsg, dw1, dw2); +	} + +	UINT WINAPI midiOutGetNumDevs(void) +	{ +		//OutputDebugString(L"midiOutGetNumDevs\n"); +		return midiOutGetNumDevs_orig(); +	} + +	MMRESULT WINAPI midiStreamOpen( LPHMIDISTRM phms, LPUINT puDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		//OutputDebugString(L"midiStreamOpen\n"); +		return midiStreamOpen_orig( phms, puDeviceID, cMidi, dwCallback, dwInstance, fdwOpen); +	} + +	MMRESULT WINAPI midiStreamClose( HMIDISTRM hms) +	{ +		//OutputDebugString(L"midiStreamClose\n"); +		return midiStreamClose_orig( hms); +	} + +	MMRESULT WINAPI midiStreamProperty( HMIDISTRM hms, LPBYTE lppropdata, DWORD dwProperty) +	{ +		//OutputDebugString(L"midiStreamProperty\n"); +		return midiStreamProperty_orig( hms, lppropdata, dwProperty); +	} + +	MMRESULT WINAPI midiStreamPosition( HMIDISTRM hms, LPMMTIME lpmmt, UINT cbmmt) +	{ +		//OutputDebugString(L"midiStreamPosition\n"); +		return midiStreamPosition_orig( hms, lpmmt, cbmmt); +	} + +	MMRESULT WINAPI midiStreamOut( HMIDISTRM hms, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiStreamOut\n"); +		return midiStreamOut_orig( hms, pmh, cbmh); +	} + +	MMRESULT WINAPI midiStreamPause( HMIDISTRM hms) +	{ +		//OutputDebugString(L"midiStreamPause\n"); +		return midiStreamPause_orig( hms); +	} + +	MMRESULT WINAPI midiStreamRestart( HMIDISTRM hms) +	{ +		//OutputDebugString(L"midiStreamRestart\n"); +		return midiStreamRestart_orig( hms); +	} + +	MMRESULT WINAPI midiStreamStop( HMIDISTRM hms) +	{ +		//OutputDebugString(L"midiStreamStop\n"); +		return midiStreamStop_orig( hms); +	} + +	MMRESULT WINAPI midiConnect( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved) +	{ +		//OutputDebugString(L"midiConnect\n"); +		return midiConnect_orig( hmi, hmo, pReserved); +	} + +	MMRESULT WINAPI midiDisconnect( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved) +	{ +		//OutputDebugString(L"midiDisconnect\n"); +		return midiDisconnect_orig( hmi, hmo, pReserved); +	} + +	MMRESULT WINAPI midiOutGetDevCapsA( UINT_PTR uDeviceID, LPMIDIOUTCAPSA pmoc, UINT cbmoc) +	{ +		//OutputDebugString(L"midiOutGetDevCapsA\n"); +		return midiOutGetDevCapsA_orig( uDeviceID, pmoc, cbmoc); +	} + +	MMRESULT WINAPI midiOutGetDevCapsW( UINT_PTR uDeviceID, LPMIDIOUTCAPSW pmoc, UINT cbmoc) +	{ +		//OutputDebugString(L"midiOutGetDevCapsW\n"); +		return midiOutGetDevCapsW_orig( uDeviceID, pmoc, cbmoc); +	} + +	MMRESULT WINAPI midiOutGetVolume( HMIDIOUT hmo, LPDWORD pdwVolume) +	{ +		//OutputDebugString(L"midiOutGetVolume\n"); +		return midiOutGetVolume_orig( hmo, pdwVolume); +	} + +	MMRESULT WINAPI midiOutSetVolume( HMIDIOUT hmo, DWORD dwVolume) +	{ +		//OutputDebugString(L"midiOutSetVolume\n"); +		return midiOutSetVolume_orig( hmo, dwVolume); +	} + +	MMRESULT WINAPI midiOutGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"midiOutGetErrorTextA\n"); +		return midiOutGetErrorTextA_orig( mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI midiOutGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"midiOutGetErrorTextW\n"); +		return midiOutGetErrorTextW_orig( mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI midiOutOpen( LPHMIDIOUT phmo, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		//OutputDebugString(L"midiOutOpen\n"); +		return midiOutOpen_orig(phmo, uDeviceID, dwCallback, dwInstance, fdwOpen); +	} + +	MMRESULT WINAPI midiOutClose( HMIDIOUT hmo) +	{ +		//OutputDebugString(L"midiOutClose\n"); +		return midiOutClose_orig( hmo); +	} + +	MMRESULT WINAPI midiOutPrepareHeader( HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiOutPrepareHeader\n"); +		return midiOutPrepareHeader_orig( hmo, pmh, cbmh); +	} + +	MMRESULT WINAPI midiOutUnprepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiOutUnprepareHeader\n"); +		return midiOutUnprepareHeader_orig(hmo, pmh, cbmh); +	} + +	MMRESULT WINAPI midiOutShortMsg( HMIDIOUT hmo, DWORD dwMsg) +	{ +		//OutputDebugString(L"midiOutShortMsg\n"); +		return midiOutShortMsg_orig( hmo, dwMsg); +	} + +	MMRESULT WINAPI midiOutLongMsg(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiOutLongMsg\n"); +		return midiOutLongMsg_orig(hmo, pmh, cbmh); +	} + +	MMRESULT WINAPI midiOutReset( HMIDIOUT hmo) +	{ +		//OutputDebugString(L"midiOutReset\n"); +		return midiOutReset_orig( hmo); +	} + +	MMRESULT WINAPI midiOutCachePatches( HMIDIOUT hmo, UINT uBank, LPWORD pwpa, UINT fuCache) +	{ +		//OutputDebugString(L"midiOutCachePatches\n"); +		return midiOutCachePatches_orig( hmo, uBank, pwpa, fuCache); +	} + +	MMRESULT WINAPI midiOutCacheDrumPatches( HMIDIOUT hmo, UINT uPatch, LPWORD pwkya, UINT fuCache) +	{ +		//OutputDebugString(L"midiOutCacheDrumPatches\n"); +		return midiOutCacheDrumPatches_orig( hmo, uPatch, pwkya, fuCache); +	} + +	MMRESULT WINAPI midiOutGetID( HMIDIOUT hmo, LPUINT puDeviceID) +	{ +		//OutputDebugString(L"midiOutGetID\n"); +		return midiOutGetID_orig( hmo, puDeviceID); +	} + +	MMRESULT WINAPI midiOutMessage( HMIDIOUT hmo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2) +	{ +		//OutputDebugString(L"midiOutMessage\n"); +		return midiOutMessage_orig( hmo, uMsg, dw1, dw2); +	} + +	UINT WINAPI midiInGetNumDevs(void) +	{ +		//OutputDebugString(L"midiInGetNumDevs\n"); +		return midiInGetNumDevs_orig(); +	} + +	MMRESULT WINAPI midiInGetDevCapsA( UINT_PTR uDeviceID, LPMIDIINCAPSA pmic, UINT cbmic) +	{ +		//OutputDebugString(L"midiInGetDevCapsA\n"); +		return midiInGetDevCapsA_orig( uDeviceID, pmic, cbmic); +	} + +	MMRESULT WINAPI midiInGetDevCapsW( UINT_PTR uDeviceID, LPMIDIINCAPSW pmic, UINT cbmic) +	{ +		//OutputDebugString(L"midiInGetDevCapsW\n"); +		return midiInGetDevCapsW_orig( uDeviceID, pmic, cbmic); +	} + +	MMRESULT WINAPI midiInGetErrorTextA( MMRESULT mmrError, LPSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"midiInGetErrorTextA\n"); +		return midiInGetErrorTextA_orig( mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI midiInGetErrorTextW( MMRESULT mmrError, LPWSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"midiInGetErrorTextW\n"); +		return midiInGetErrorTextW_orig( mmrError, pszText, cchText); +	} + +	MMRESULT WINAPI midiInOpen( LPHMIDIIN phmi, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		//OutputDebugString(L"midiInOpen\n"); +		return midiInOpen_orig(phmi, uDeviceID, dwCallback, dwInstance, fdwOpen); +	} + +	MMRESULT WINAPI midiInClose( HMIDIIN hmi) +	{ +		//OutputDebugString(L"midiInClose\n"); +		return midiInClose_orig( hmi); +	} + +	MMRESULT WINAPI midiInPrepareHeader( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiInPrepareHeader\n"); +		return midiInPrepareHeader_orig( hmi, pmh, cbmh); +	} + +	MMRESULT WINAPI midiInUnprepareHeader( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiInUnprepareHeader\n"); +		return midiInUnprepareHeader_orig( hmi, pmh, cbmh); +	} + +	MMRESULT WINAPI midiInAddBuffer( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh) +	{ +		//OutputDebugString(L"midiInAddBuffer\n"); +		return midiInAddBuffer_orig( hmi, pmh, cbmh); +	} + +	MMRESULT WINAPI midiInStart( HMIDIIN hmi) +	{ +		//OutputDebugString(L"midiInStart\n"); +		return midiInStart_orig( hmi); +	} + +	MMRESULT WINAPI midiInStop( HMIDIIN hmi) +	{ +		//OutputDebugString(L"midiInStop\n"); +		return midiInStop_orig(hmi); +	} + +	MMRESULT WINAPI midiInReset( HMIDIIN hmi) +	{ +		//OutputDebugString(L"midiInReset\n"); +		return midiInReset_orig( hmi); +	} + +	MMRESULT WINAPI midiInGetID( HMIDIIN hmi, LPUINT puDeviceID) +	{ +		//OutputDebugString(L"midiInGetID\n"); +		return midiInGetID_orig( hmi, puDeviceID); +	} + +	MMRESULT WINAPI midiInMessage( HMIDIIN hmi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2) +	{ +		//OutputDebugString(L"midiInMessage\n"); +		return midiInMessage_orig( hmi, uMsg, dw1, dw2); +	} + +	UINT WINAPI auxGetNumDevs(void) +	{ +		//OutputDebugString(L"auxGetNumDevs\n"); +		return auxGetNumDevs_orig(); +	} + +	MMRESULT WINAPI auxGetDevCapsA( UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac) +	{ +		//OutputDebugString(L"auxGetDevCapsA\n"); +		return auxGetDevCapsA_orig( uDeviceID, pac, cbac); +	} + +	MMRESULT WINAPI auxGetDevCapsW( UINT_PTR uDeviceID, LPAUXCAPSW pac, UINT cbac) +	{ +		//OutputDebugString(L"auxGetDevCapsW\n"); +		return auxGetDevCapsW_orig( uDeviceID, pac, cbac); +	} + +	MMRESULT WINAPI auxSetVolume( UINT uDeviceID, DWORD dwVolume) +	{ +		//OutputDebugString(L"auxSetVolume\n"); +		return auxSetVolume_orig( uDeviceID, dwVolume); +	} + +	MMRESULT WINAPI auxGetVolume( UINT uDeviceID, LPDWORD pdwVolume) +	{ +		//OutputDebugString(L"auxGetVolume\n"); +		return auxGetVolume_orig( uDeviceID, pdwVolume); +	} + +	MMRESULT WINAPI auxOutMessage( UINT uDeviceID, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2) +	{ +		//OutputDebugString(L"auxOutMessage\n"); +		return auxOutMessage_orig( uDeviceID, uMsg, dw1, dw2); +	} + +	UINT WINAPI mixerGetNumDevs(void) +	{ +		//OutputDebugString(L"mixerGetNumDevs\n"); +		return mixerGetNumDevs_orig(); +	} + +	MMRESULT WINAPI mixerGetDevCapsA( UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps) +	{ +		//OutputDebugString(L"mixerGetDevCapsA\n"); +		return mixerGetDevCapsA_orig( uMxId, pmxcaps, cbmxcaps); +	} + +	MMRESULT WINAPI mixerGetDevCapsW( UINT_PTR uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps) +	{ +		//OutputDebugString(L"mixerGetDevCapsW\n"); +		return mixerGetDevCapsW_orig( uMxId, pmxcaps, cbmxcaps); +	} + +	MMRESULT WINAPI mixerOpen( LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		//OutputDebugString(L"mixerOpen\n"); +		return mixerOpen_orig( phmx, uMxId, dwCallback, dwInstance, fdwOpen); +	} + +	MMRESULT WINAPI mixerClose( HMIXER hmx) +	{ +		//OutputDebugString(L"mixerClose\n"); +		return mixerClose_orig( hmx); +	} + +	DWORD WINAPI mixerMessage( HMIXER hmx, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) +	{ +		//OutputDebugString(L"mixerMessage\n"); +		return mixerMessage_orig( hmx, uMsg, dwParam1, dwParam2); +	} + +	MMRESULT WINAPI mixerGetLineInfoA( HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo) +	{ +		//OutputDebugString(L"mixerGetLineInfoA\n"); +		return mixerGetLineInfoA_orig( hmxobj, pmxl, fdwInfo); +	} + +	MMRESULT WINAPI mixerGetLineInfoW( HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo) +	{ +		//OutputDebugString(L"mixerGetLineInfoW\n"); +		return mixerGetLineInfoW_orig( hmxobj, pmxl, fdwInfo); +	} + +	MMRESULT WINAPI mixerGetID( HMIXEROBJ hmxobj, UINT FAR *puMxId, DWORD fdwId) +	{ +		//OutputDebugString(L"mixerGetID\n"); +		return mixerGetID_orig( hmxobj, puMxId, fdwId); +	} + +	MMRESULT WINAPI mixerGetLineControlsA( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls) +	{ +		//OutputDebugString(L"mixerGetLineControlsA\n"); +		return mixerGetLineControlsA_orig( hmxobj, pmxlc, fdwControls); +	} + +	MMRESULT WINAPI mixerGetLineControlsW( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW pmxlc, DWORD fdwControls) +	{ +		//OutputDebugString(L"mixerGetLineControlsW\n"); +		return mixerGetLineControlsW_orig( hmxobj, pmxlc, fdwControls); +	} + +	MMRESULT WINAPI mixerGetControlDetailsA( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) +	{ +		//OutputDebugString(L"mixerGetControlDetailsA\n"); +		return mixerGetControlDetailsA_orig( hmxobj, pmxcd, fdwDetails); +	} + +	MMRESULT WINAPI mixerGetControlDetailsW( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) +	{ +		//OutputDebugString(L"mixerGetControlDetailsW\n"); +		return mixerGetControlDetailsW_orig( hmxobj, pmxcd, fdwDetails); +	} + +	MMRESULT WINAPI mixerSetControlDetails( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) +	{ +		//OutputDebugString(L"mixerSetControlDetails\n"); +		return mixerSetControlDetails_orig( hmxobj, pmxcd, fdwDetails); +	} + +	DWORD    WINAPI mmGetCurrentTask(void) +	{ +		//OutputDebugString(L"mmGetCurrentTask\n"); +		return mmGetCurrentTask_orig(); +	} + +	void WINAPI mmTaskBlock(DWORD val) +	{ +		//OutputDebugString(L"mmTaskBlock\n"); +		return mmTaskBlock_orig(val); +	} + +	UINT WINAPI mmTaskCreate(LPTASKCALLBACK a, HANDLE* b, DWORD_PTR c) +	{ +		//OutputDebugString(L"mmTaskCreate\n"); +		return mmTaskCreate_orig(a, b, c); +	} + +	BOOL WINAPI mmTaskSignal(DWORD a) +	{ +		//OutputDebugString(L"mmTaskSignal\n"); +		return mmTaskSignal_orig(a); +	} + +	VOID WINAPI mmTaskYield() +	{ +		//OutputDebugString(L"mmTaskYield\n"); +		mmTaskYield_orig(); +	} + +	MMRESULT WINAPI timeGetSystemTime( LPMMTIME pmmt, UINT cbmmt) +	{ +		//OutputDebugString(L"timeGetSystemTime\n"); +		return timeGetSystemTime_orig( pmmt, cbmmt); +	} + +	DWORD WINAPI timeGetTime(void) +	{ +		//OutputDebugString(L"timeGetTime\n"); +		return timeGetTime_orig(); +	} + +	MMRESULT WINAPI timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) +	{ +		//OutputDebugString(L"timeSetEvent\n"); +		return timeSetEvent_orig(uDelay, uResolution, fptc, dwUser, fuEvent); +	} + +	MMRESULT WINAPI timeKillEvent( UINT uTimerID) +	{ +		//OutputDebugString(L"timeKillEvent\n"); +		return timeKillEvent_orig( uTimerID); +	} + +	MMRESULT WINAPI timeGetDevCaps( LPTIMECAPS ptc, UINT cbtc) +	{ +		//OutputDebugString(L"timeGetDevCaps\n"); +		return timeGetDevCaps_orig( ptc, cbtc); +	} + +	MMRESULT WINAPI timeBeginPeriod( UINT uPeriod) +	{ +		//OutputDebugString(L"timeBeginPeriod\n"); +		return timeBeginPeriod_orig( uPeriod); +	} + +	MMRESULT WINAPI timeEndPeriod( UINT uPeriod) +	{ +		//OutputDebugString(L"timeEndPeriod\n"); +		return timeEndPeriod_orig( uPeriod); +	} + +	UINT WINAPI joyGetNumDevs(void) +	{ +		//OutputDebugString(L"joyGetNumDevs\n"); +		return joyGetNumDevs_orig(); +	} + +	MMRESULT WINAPI joyConfigChanged(DWORD dwFlags) +	{ +		//OutputDebugString(L"joyConfigChanged\n"); +		return joyConfigChanged_orig(dwFlags); +	} + +	MMRESULT WINAPI joyGetDevCapsA( UINT_PTR uJoyID, LPJOYCAPSA pjc, UINT cbjc) +	{ +		//OutputDebugString(L"joyGetDevCapsA\n"); +		return joyGetDevCapsA_orig( uJoyID, pjc, cbjc); +	} + +	MMRESULT WINAPI joyGetDevCapsW( UINT_PTR uJoyID, LPJOYCAPSW pjc, UINT cbjc) +	{ +		//OutputDebugString(L"joyGetDevCapsW\n"); +		return joyGetDevCapsW_orig( uJoyID, pjc, cbjc); +	} + +	MMRESULT WINAPI joyGetPos( UINT uJoyID, LPJOYINFO pji) +	{ +		//OutputDebugString(L"joyGetPos\n"); +		return joyGetPos_orig( uJoyID, pji); +	} + +	MMRESULT WINAPI joyGetPosEx( UINT uJoyID, LPJOYINFOEX pji) +	{ +		//OutputDebugString(L"joyGetPosEx\n"); +		return joyGetPosEx_orig( uJoyID, pji); +	} + +	MMRESULT WINAPI joyGetThreshold( UINT uJoyID, LPUINT puThreshold) +	{ +		//OutputDebugString(L"joyGetThreshold\n"); +		return joyGetThreshold_orig( uJoyID, puThreshold); +	} + +	MMRESULT WINAPI joyReleaseCapture( UINT uJoyID) +	{ +		//OutputDebugString(L"joyReleaseCapture\n"); +		return joyReleaseCapture_orig( uJoyID); +	} + +	MMRESULT WINAPI joySetCapture( HWND hwnd, UINT uJoyID, UINT uPeriod, BOOL fChanged) +	{ +		//OutputDebugString(L"joySetCapture\n"); +		return joySetCapture_orig(hwnd, uJoyID, uPeriod, fChanged); +	} + +	MMRESULT WINAPI joySetThreshold( UINT uJoyID, UINT uThreshold) +	{ +		//OutputDebugString(L"joySetThreshold\n"); +		return joySetThreshold_orig( uJoyID, uThreshold); +	} + +	BOOL WINAPI  mciDriverNotify(HWND hwndCallback, UINT uDeviceID, UINT uStatus) +	{ +		//OutputDebugString(L"mciDriverNotify\n"); +		return mciDriverNotify_orig(hwndCallback, uDeviceID, uStatus); +	} + +	UINT WINAPI  mciDriverYield(UINT uDeviceID) +	{ +		//OutputDebugString(L"mciDriverYield\n"); +		return mciDriverYield_orig(uDeviceID); +	}	 + +	FOURCC WINAPI mmioStringToFOURCCA( LPCSTR sz, UINT uFlags) +	{ +		//OutputDebugString(L"mmioStringToFOURCCA\n"); +		return mmioStringToFOURCCA_orig( sz, uFlags); +	} + +	FOURCC WINAPI mmioStringToFOURCCW( LPCWSTR sz, UINT uFlags) +	{ +		//OutputDebugString(L"mmioStringToFOURCCW\n"); +		return mmioStringToFOURCCW_orig( sz, uFlags); +	} + +	LPMMIOPROC WINAPI mmioInstallIOProcA( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags) +	{ +		//OutputDebugString(L"mmioInstallIOProcA\n"); +		return mmioInstallIOProcA_orig( fccIOProc, pIOProc, dwFlags); +	} + +	LPMMIOPROC WINAPI mmioInstallIOProcW( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags) +	{ +		//OutputDebugString(L"mmioInstallIOProcW\n"); +		return mmioInstallIOProcW_orig( fccIOProc, pIOProc, dwFlags); +	} + +	HMMIO WINAPI mmioOpenA( LPSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen) +	{ +		//OutputDebugString(L"mmioOpenA\n"); +		return mmioOpenA_orig( pszFileName, pmmioinfo, fdwOpen); +	} + +	HMMIO WINAPI mmioOpenW( LPWSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen) +	{ +		//OutputDebugString(L"mmioOpenW\n"); +		return mmioOpenW_orig( pszFileName, pmmioinfo, fdwOpen); +	} + +	MMRESULT WINAPI mmioRenameA( LPCSTR pszFileName, LPCSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename) +	{ +		//OutputDebugString(L"mmioRenameA\n"); +		return mmioRenameA_orig( pszFileName, pszNewFileName, pmmioinfo, fdwRename); +	} + +	MMRESULT WINAPI mmioRenameW( LPCWSTR pszFileName, LPCWSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename) +	{ +		//OutputDebugString(L"mmioRenameW\n"); +		return mmioRenameW_orig( pszFileName, pszNewFileName, pmmioinfo, fdwRename); +	} + +	MMRESULT WINAPI mmioClose( HMMIO hmmio, UINT fuClose) +	{ +		//OutputDebugString(L"mmioClose\n"); +		return mmioClose_orig( hmmio, fuClose); +	} + +	LONG WINAPI mmioRead( HMMIO hmmio, HPSTR pch, LONG cch) +	{ +		//OutputDebugString(L"mmioRead\n"); +		return mmioRead_orig( hmmio, pch, cch); +	} + +	LONG WINAPI mmioWrite( HMMIO hmmio, const char _huge* pch, LONG cch) +	{ +		//OutputDebugString(L"mmioWrite\n"); +		return mmioWrite_orig( hmmio, pch, cch); +	} + +	LONG WINAPI mmioSeek( HMMIO hmmio, LONG lOffset, int iOrigin) +	{ +		//OutputDebugString(L"mmioSeek\n"); +		return mmioSeek_orig(hmmio, lOffset, iOrigin); +	} + +	MMRESULT WINAPI mmioGetInfo( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuInfo) +	{ +		//OutputDebugString(L"mmioGetInfo\n"); +		return mmioGetInfo_orig( hmmio, pmmioinfo, fuInfo); +	} + +	MMRESULT WINAPI mmioSetInfo( HMMIO hmmio, LPCMMIOINFO pmmioinfo, UINT fuInfo) +	{ +		//OutputDebugString(L"mmioSetInfo\n"); +		return mmioSetInfo_orig( hmmio, pmmioinfo, fuInfo); +	} + +	MMRESULT WINAPI mmioSetBuffer( HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer) +	{ +		//OutputDebugString(L"mmioSetBuffer\n"); +		return mmioSetBuffer_orig(hmmio, pchBuffer, cchBuffer, fuBuffer); +	} + +	MMRESULT WINAPI mmioFlush( HMMIO hmmio, UINT fuFlush) +	{ +		//OutputDebugString(L"mmioFlush\n"); +		return mmioFlush_orig( hmmio, fuFlush); +	} + +	MMRESULT WINAPI mmioAdvance( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuAdvance) +	{ +		//OutputDebugString(L"mmioAdvance\n"); +		return mmioAdvance_orig( hmmio, pmmioinfo, fuAdvance); +	} + +	LRESULT WINAPI mmioSendMessage( HMMIO hmmio, UINT uMsg, LPARAM lParam1, LPARAM lParam2) +	{ +		//OutputDebugString(L"mmioSendMessage\n"); +		return mmioSendMessage_orig(hmmio, uMsg, lParam1, lParam2); +	} + +	MMRESULT WINAPI mmioDescend( HMMIO hmmio, LPMMCKINFO pmmcki, const MMCKINFO FAR* pmmckiParent, UINT fuDescend) +	{ +		//OutputDebugString(L"mmioDescend\n"); +		return mmioDescend_orig(hmmio, pmmcki, pmmckiParent, fuDescend); +	} + +	MMRESULT WINAPI mmioAscend( HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuAscend) +	{ +		//OutputDebugString(L"mmioAscend\n"); +		return mmioAscend_orig( hmmio, pmmcki, fuAscend); +	} + +	MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuCreate) +	{ +		//OutputDebugString(L"mmioCreateChunk\n"); +		return mmioCreateChunk_orig(hmmio, pmmcki, fuCreate); +	} + +	MCIERROR WINAPI mciSendCommandA( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) +	{ +		//OutputDebugString(L"mciSendCommandA\n"); +		return mciSendCommandA_orig( mciId, uMsg, dwParam1, dwParam2); +	} + +	MCIERROR WINAPI mciSendCommandW( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) +	{ +		//OutputDebugString(L"mciSendCommandW\n"); +		return mciSendCommandW_orig( mciId, uMsg, dwParam1, dwParam2); +	} + +	MCIERROR  WINAPI mciSendStringA( LPCSTR lpstrCommand, LPSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback) +	{ +		//OutputDebugString(L"mciSendStringA\n"); +		return mciSendStringA_orig( lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback); +	} + +	MCIERROR  WINAPI mciSendStringW( LPCWSTR lpstrCommand, LPWSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback) +	{ +		//OutputDebugString(L"mciSendStringW\n"); +		return mciSendStringW_orig( lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback); +	} + +	MCIDEVICEID WINAPI mciGetDeviceIDA( LPCSTR pszDevice) +	{ +		//OutputDebugString(L"mciGetDeviceIDA\n"); +		return mciGetDeviceIDA_orig( pszDevice); +	} + +	MCIDEVICEID WINAPI mciGetDeviceIDW( LPCWSTR pszDevice) +	{ +		//OutputDebugString(L"mciGetDeviceIDW\n"); +		return mciGetDeviceIDW_orig( pszDevice); +	} + +	MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDA( DWORD dwElementID, LPCSTR lpstrType ) +	{ +		//OutputDebugString(L"mciGetDeviceIDFromElementIDA\n"); +		return mciGetDeviceIDFromElementIDA_orig( dwElementID, lpstrType ); +	} + +	MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDW( DWORD dwElementID, LPCWSTR lpstrType ) +	{ +		//OutputDebugString(L"mciGetDeviceIDFromElementIDW\n"); +		return mciGetDeviceIDFromElementIDW_orig( dwElementID, lpstrType ); +	} + +	DWORD_PTR WINAPI  mciGetDriverData(UINT uDeviceID) +	{ +		//OutputDebugString(L"mciGetDriverData\n"); +		return mciGetDriverData_orig(uDeviceID); +	} + +	BOOL WINAPI mciGetErrorStringA( MCIERROR mcierr, LPSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"mciGetErrorStringA\n"); +		return mciGetErrorStringA_orig( mcierr, pszText, cchText); +	} + +	BOOL WINAPI mciGetErrorStringW( MCIERROR mcierr, LPWSTR pszText, UINT cchText) +	{ +		//OutputDebugString(L"mciGetErrorStringW\n"); +		return mciGetErrorStringW_orig( mcierr, pszText, cchText); +	} + +	BOOL WINAPI  mciSetDriverData(UINT uDeviceID, DWORD_PTR dwData) +	{ +		//OutputDebugString(L"mciSetDriverData_type\n"); +		return mciSetDriverData_orig( uDeviceID, dwData ); +	} + +	BOOL WINAPI mciSetYieldProc( MCIDEVICEID mciId, YIELDPROC fpYieldProc, DWORD dwYieldData) +	{ +		//OutputDebugString(L"mciSetYieldProc\n"); +		return mciSetYieldProc_orig(mciId, fpYieldProc, dwYieldData); +	} + +	BOOL WINAPI  mciFreeCommandResource(UINT uTable) +	{ +		//OutputDebugString(L"mciFreeCommandResource\n"); +		return mciFreeCommandResource_orig(uTable); +	} + +	HTASK WINAPI mciGetCreatorTask( MCIDEVICEID mciId) +	{ +		//OutputDebugString(L"mciGetCreatorTask\n"); +		return mciGetCreatorTask_orig( mciId); +	} + +	YIELDPROC WINAPI mciGetYieldProc( MCIDEVICEID mciId, LPDWORD pdwYieldData) +	{ +		//OutputDebugString(L"mciGetYieldProc\n"); +		return mciGetYieldProc_orig( mciId, pdwYieldData); +	} + +	UINT WINAPI mciLoadCommandResource(HINSTANCE hInstance, LPCWSTR lpResName, UINT uType) +	{ +		//OutputDebugString(L"mciLoadCommandResource"); +		return mciLoadCommandResource_orig(hInstance, lpResName, uType); +	} +	 + +	BOOL WINAPI mciExecute(LPCSTR pszCommand) +	{ +		//OutputDebugString(L"mciExecute\n"); +		return mciExecute_orig(pszCommand); +	} +} diff --git a/indra/media_plugins/winmmshim/forwarding_api.h b/indra/media_plugins/winmmshim/forwarding_api.h new file mode 100644 index 0000000000..31e2186aa2 --- /dev/null +++ b/indra/media_plugins/winmmshim/forwarding_api.h @@ -0,0 +1,395 @@ +/**  + * @file forwarding_api.h + * @brief forwards winmm API calls to real winmm.dll + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// this turns off __declspec(dllimport) for the functions declared in mmsystem.h +#define _WINMM_ +#include <windows.h> +#include <mmsystem.h> + +void init_function_pointers(HMODULE winmm_handle); + +typedef VOID (*LPTASKCALLBACK)(DWORD_PTR dwInst); + +typedef LRESULT   (WINAPI *CloseDriver_type)( HDRVR hDriver, LPARAM lParam1, LPARAM lParam2); +extern CloseDriver_type CloseDriver_orig; +typedef HDRVR     (WINAPI *OpenDriver_type)( LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2); +extern OpenDriver_type OpenDriver_orig; +typedef LRESULT   (WINAPI *SendDriverMessage_type)( HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2); +extern SendDriverMessage_type SendDriverMessage_orig; +typedef HMODULE   (WINAPI *DrvGetModuleHandle_type)( HDRVR hDriver); +extern DrvGetModuleHandle_type DrvGetModuleHandle_orig; +typedef HMODULE   (WINAPI *GetDriverModuleHandle_type)( HDRVR hDriver); +extern GetDriverModuleHandle_type GetDriverModuleHandle_orig; +typedef LRESULT   (WINAPI *DefDriverProc_type)( DWORD_PTR dwDriverIdentifier, HDRVR hdrvr, UINT uMsg, LPARAM lParam1, LPARAM lParam2); +extern DefDriverProc_type DefDriverProc_orig; +typedef BOOL (WINAPI *DriverCallback_type)(DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2); +extern DriverCallback_type DriverCallback_orig; +typedef UINT (WINAPI *mmsystemGetVersion_type)(void); +extern mmsystemGetVersion_type mmsystemGetVersion_orig; +typedef BOOL (WINAPI *sndPlaySoundA_type)( LPCSTR pszSound, UINT fuSound); +extern sndPlaySoundA_type sndPlaySoundA_orig; +typedef BOOL (WINAPI *sndPlaySoundW_type)( LPCWSTR pszSound, UINT fuSound); +extern sndPlaySoundW_type sndPlaySoundW_orig; +typedef BOOL (WINAPI *PlaySoundA_type)( LPCSTR pszSound, HMODULE hmod, DWORD fdwSound); +extern PlaySoundA_type PlaySoundA_orig; +typedef BOOL (WINAPI *PlaySoundW_type)( LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound); +extern PlaySoundW_type PlaySoundW_orig; +typedef UINT (WINAPI *waveOutGetNumDevs_type)(void); +extern waveOutGetNumDevs_type waveOutGetNumDevs_orig; +typedef MMRESULT (WINAPI *waveOutGetDevCapsA_type)( UINT_PTR uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc); +extern waveOutGetDevCapsA_type waveOutGetDevCapsA_orig; +typedef MMRESULT (WINAPI *waveOutGetDevCapsW_type)( UINT_PTR uDeviceID, LPWAVEOUTCAPSW pwoc, UINT cbwoc); +extern waveOutGetDevCapsW_type waveOutGetDevCapsW_orig; +typedef MMRESULT (WINAPI *waveOutGetVolume_type)( HWAVEOUT hwo, LPDWORD pdwVolume); +extern waveOutGetVolume_type waveOutGetVolume_orig; +typedef MMRESULT (WINAPI *waveOutSetVolume_type)( HWAVEOUT hwo, DWORD dwVolume); +extern waveOutSetVolume_type waveOutSetVolume_orig; +typedef MMRESULT (WINAPI *waveOutGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText); +extern waveOutGetErrorTextA_type waveOutGetErrorTextA_orig; +typedef MMRESULT (WINAPI *waveOutGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText); +extern waveOutGetErrorTextW_type waveOutGetErrorTextW_orig; +typedef MMRESULT (WINAPI *waveOutOpen_type)( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern waveOutOpen_type waveOutOpen_orig; +typedef MMRESULT (WINAPI *waveOutClose_type)( HWAVEOUT hwo); +extern waveOutClose_type waveOutClose_orig; +typedef MMRESULT (WINAPI *waveOutPrepareHeader_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh); +extern waveOutPrepareHeader_type waveOutPrepareHeader_orig; +typedef MMRESULT (WINAPI *waveOutUnprepareHeader_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh); +extern waveOutUnprepareHeader_type waveOutUnprepareHeader_orig; +typedef MMRESULT (WINAPI *waveOutWrite_type)( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh); +extern waveOutWrite_type waveOutWrite_orig; +typedef MMRESULT (WINAPI *waveOutPause_type)( HWAVEOUT hwo); +extern waveOutPause_type waveOutPause_orig; +typedef MMRESULT (WINAPI *waveOutRestart_type)( HWAVEOUT hwo); +extern waveOutRestart_type waveOutRestart_orig; +typedef MMRESULT (WINAPI *waveOutReset_type)( HWAVEOUT hwo); +extern waveOutReset_type waveOutReset_orig; +typedef MMRESULT (WINAPI *waveOutBreakLoop_type)( HWAVEOUT hwo); +extern waveOutBreakLoop_type waveOutBreakLoop_orig; +typedef MMRESULT (WINAPI *waveOutGetPosition_type)( HWAVEOUT hwo, LPMMTIME pmmt, UINT cbmmt); +extern waveOutGetPosition_type waveOutGetPosition_orig; +typedef MMRESULT (WINAPI *waveOutGetPitch_type)( HWAVEOUT hwo, LPDWORD pdwPitch); +extern waveOutGetPitch_type waveOutGetPitch_orig; +typedef MMRESULT (WINAPI *waveOutSetPitch_type)( HWAVEOUT hwo, DWORD dwPitch); +extern waveOutSetPitch_type waveOutSetPitch_orig; +typedef MMRESULT (WINAPI *waveOutGetPlaybackRate_type)( HWAVEOUT hwo, LPDWORD pdwRate); +extern waveOutGetPlaybackRate_type waveOutGetPlaybackRate_orig; +typedef MMRESULT (WINAPI *waveOutSetPlaybackRate_type)( HWAVEOUT hwo, DWORD dwRate); +extern waveOutSetPlaybackRate_type waveOutSetPlaybackRate_orig; +typedef MMRESULT (WINAPI *waveOutGetID_type)( HWAVEOUT hwo, LPUINT puDeviceID); +extern waveOutGetID_type waveOutGetID_orig; +typedef MMRESULT (WINAPI *waveOutMessage_type)( HWAVEOUT hwo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2); +extern waveOutMessage_type waveOutMessage_orig; +typedef UINT (WINAPI *waveInGetNumDevs_type)(void); +extern waveInGetNumDevs_type waveInGetNumDevs_orig; +typedef MMRESULT (WINAPI *waveInGetDevCapsA_type)( UINT_PTR uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic); +extern waveInGetDevCapsA_type waveInGetDevCapsA_orig; +typedef MMRESULT (WINAPI *waveInGetDevCapsW_type)( UINT_PTR uDeviceID, LPWAVEINCAPSW pwic, UINT cbwic); +extern waveInGetDevCapsW_type waveInGetDevCapsW_orig; +typedef MMRESULT (WINAPI *waveInGetErrorTextA_type)(MMRESULT mmrError, LPSTR pszText, UINT cchText); +extern waveInGetErrorTextA_type waveInGetErrorTextA_orig; +typedef MMRESULT (WINAPI *waveInGetErrorTextW_type)(MMRESULT mmrError, LPWSTR pszText, UINT cchText); +extern waveInGetErrorTextW_type waveInGetErrorTextW_orig; +typedef MMRESULT (WINAPI *waveInOpen_type)( LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern waveInOpen_type waveInOpen_orig; +typedef MMRESULT (WINAPI *waveInClose_type)( HWAVEIN hwi); +extern waveInClose_type waveInClose_orig; +typedef MMRESULT (WINAPI *waveInPrepareHeader_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh); +extern waveInPrepareHeader_type waveInPrepareHeader_orig; +typedef MMRESULT (WINAPI *waveInUnprepareHeader_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh); +extern waveInUnprepareHeader_type waveInUnprepareHeader_orig; +typedef MMRESULT (WINAPI *waveInAddBuffer_type)( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh); +extern waveInAddBuffer_type waveInAddBuffer_orig; +typedef MMRESULT (WINAPI *waveInStart_type)( HWAVEIN hwi); +extern waveInStart_type waveInStart_orig; +typedef MMRESULT (WINAPI *waveInStop_type)( HWAVEIN hwi); +extern waveInStop_type waveInStop_orig; +typedef MMRESULT (WINAPI *waveInReset_type)( HWAVEIN hwi); +extern waveInReset_type waveInReset_orig; +typedef MMRESULT (WINAPI *waveInGetPosition_type)( HWAVEIN hwi, LPMMTIME pmmt, UINT cbmmt); +extern waveInGetPosition_type waveInGetPosition_orig; +typedef MMRESULT (WINAPI *waveInGetID_type)( HWAVEIN hwi, LPUINT puDeviceID); +extern waveInGetID_type waveInGetID_orig; +typedef MMRESULT (WINAPI *waveInMessage_type)( HWAVEIN hwi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2); +extern waveInMessage_type waveInMessage_orig; +typedef UINT (WINAPI *midiOutGetNumDevs_type)(void); +extern midiOutGetNumDevs_type midiOutGetNumDevs_orig; +typedef MMRESULT (WINAPI *midiStreamOpen_type)( LPHMIDISTRM phms, LPUINT puDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern midiStreamOpen_type midiStreamOpen_orig; +typedef MMRESULT (WINAPI *midiStreamClose_type)( HMIDISTRM hms); +extern midiStreamClose_type midiStreamClose_orig; +typedef MMRESULT (WINAPI *midiStreamProperty_type)( HMIDISTRM hms, LPBYTE lppropdata, DWORD dwProperty); +extern midiStreamProperty_type midiStreamProperty_orig; +typedef MMRESULT (WINAPI *midiStreamPosition_type)( HMIDISTRM hms, LPMMTIME lpmmt, UINT cbmmt); +extern midiStreamPosition_type midiStreamPosition_orig; +typedef MMRESULT (WINAPI *midiStreamOut_type)( HMIDISTRM hms, LPMIDIHDR pmh, UINT cbmh); +extern midiStreamOut_type midiStreamOut_orig; +typedef MMRESULT (WINAPI *midiStreamPause_type)( HMIDISTRM hms); +extern midiStreamPause_type midiStreamPause_orig; +typedef MMRESULT (WINAPI *midiStreamRestart_type)( HMIDISTRM hms); +extern midiStreamRestart_type midiStreamRestart_orig; +typedef MMRESULT (WINAPI *midiStreamStop_type)( HMIDISTRM hms); +extern midiStreamStop_type midiStreamStop_orig; +typedef MMRESULT (WINAPI *midiConnect_type)( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved); +extern midiConnect_type midiConnect_orig; +typedef MMRESULT (WINAPI *midiDisconnect_type)( HMIDI hmi, HMIDIOUT hmo, LPVOID pReserved); +extern midiDisconnect_type midiDisconnect_orig; +typedef MMRESULT (WINAPI *midiOutGetDevCapsA_type)( UINT_PTR uDeviceID, LPMIDIOUTCAPSA pmoc, UINT cbmoc); +extern midiOutGetDevCapsA_type midiOutGetDevCapsA_orig; +typedef MMRESULT (WINAPI *midiOutGetDevCapsW_type)( UINT_PTR uDeviceID, LPMIDIOUTCAPSW pmoc, UINT cbmoc); +extern midiOutGetDevCapsW_type midiOutGetDevCapsW_orig; +typedef MMRESULT (WINAPI *midiOutGetVolume_type)( HMIDIOUT hmo, LPDWORD pdwVolume); +extern midiOutGetVolume_type midiOutGetVolume_orig; +typedef MMRESULT (WINAPI *midiOutSetVolume_type)( HMIDIOUT hmo, DWORD dwVolume); +extern midiOutSetVolume_type midiOutSetVolume_orig; +typedef MMRESULT (WINAPI *midiOutGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText); +extern midiOutGetErrorTextA_type midiOutGetErrorTextA_orig; +typedef MMRESULT (WINAPI *midiOutGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText); +extern midiOutGetErrorTextW_type midiOutGetErrorTextW_orig; +typedef MMRESULT (WINAPI *midiOutOpen_type)( LPHMIDIOUT phmo, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern midiOutOpen_type midiOutOpen_orig; +typedef MMRESULT (WINAPI *midiOutClose_type)( HMIDIOUT hmo); +extern midiOutClose_type midiOutClose_orig; +typedef MMRESULT (WINAPI *midiOutPrepareHeader_type)( HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh); +extern midiOutPrepareHeader_type midiOutPrepareHeader_orig; +typedef MMRESULT (WINAPI *midiOutUnprepareHeader_type)(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh); +extern midiOutUnprepareHeader_type midiOutUnprepareHeader_orig; +typedef MMRESULT (WINAPI *midiOutShortMsg_type)( HMIDIOUT hmo, DWORD dwMsg); +extern midiOutShortMsg_type midiOutShortMsg_orig; +typedef MMRESULT (WINAPI *midiOutLongMsg_type)(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh); +extern midiOutLongMsg_type midiOutLongMsg_orig; +typedef MMRESULT (WINAPI *midiOutReset_type)( HMIDIOUT hmo); +extern midiOutReset_type midiOutReset_orig; +typedef MMRESULT (WINAPI *midiOutCachePatches_type)( HMIDIOUT hmo, UINT uBank, LPWORD pwpa, UINT fuCache); +extern midiOutCachePatches_type midiOutCachePatches_orig; +typedef MMRESULT (WINAPI *midiOutCacheDrumPatches_type)( HMIDIOUT hmo, UINT uPatch, LPWORD pwkya, UINT fuCache); +extern midiOutCacheDrumPatches_type midiOutCacheDrumPatches_orig; +typedef MMRESULT (WINAPI *midiOutGetID_type)( HMIDIOUT hmo, LPUINT puDeviceID); +extern midiOutGetID_type midiOutGetID_orig; +typedef MMRESULT (WINAPI *midiOutMessage_type)( HMIDIOUT hmo, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2); +extern midiOutMessage_type midiOutMessage_orig; +typedef UINT (WINAPI *midiInGetNumDevs_type)(void); +extern midiInGetNumDevs_type midiInGetNumDevs_orig; +typedef MMRESULT (WINAPI *midiInGetDevCapsA_type)( UINT_PTR uDeviceID, LPMIDIINCAPSA pmic, UINT cbmic); +extern midiInGetDevCapsA_type midiInGetDevCapsA_orig; +typedef MMRESULT (WINAPI *midiInGetDevCapsW_type)( UINT_PTR uDeviceID, LPMIDIINCAPSW pmic, UINT cbmic); +extern midiInGetDevCapsW_type midiInGetDevCapsW_orig; +typedef MMRESULT (WINAPI *midiInGetErrorTextA_type)( MMRESULT mmrError, LPSTR pszText, UINT cchText); +extern midiInGetErrorTextA_type midiInGetErrorTextA_orig; +typedef MMRESULT (WINAPI *midiInGetErrorTextW_type)( MMRESULT mmrError, LPWSTR pszText, UINT cchText); +extern midiInGetErrorTextW_type midiInGetErrorTextW_orig; +typedef MMRESULT (WINAPI *midiInOpen_type)( LPHMIDIIN phmi, UINT uDeviceID, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern midiInOpen_type midiInOpen_orig; +typedef MMRESULT (WINAPI *midiInClose_type)( HMIDIIN hmi); +extern midiInClose_type midiInClose_orig; +typedef MMRESULT (WINAPI *midiInPrepareHeader_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh); +extern midiInPrepareHeader_type midiInPrepareHeader_orig; +typedef MMRESULT (WINAPI *midiInUnprepareHeader_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh); +extern midiInUnprepareHeader_type midiInUnprepareHeader_orig; +typedef MMRESULT (WINAPI *midiInAddBuffer_type)( HMIDIIN hmi, LPMIDIHDR pmh, UINT cbmh); +extern midiInAddBuffer_type midiInAddBuffer_orig; +typedef MMRESULT (WINAPI *midiInStart_type)( HMIDIIN hmi); +extern midiInStart_type midiInStart_orig; +typedef MMRESULT (WINAPI *midiInStop_type)( HMIDIIN hmi); +extern midiInStop_type midiInStop_orig; +typedef MMRESULT (WINAPI *midiInReset_type)( HMIDIIN hmi); +extern midiInReset_type midiInReset_orig; +typedef MMRESULT (WINAPI *midiInGetID_type)( HMIDIIN hmi, LPUINT puDeviceID); +extern midiInGetID_type midiInGetID_orig; +typedef MMRESULT (WINAPI *midiInMessage_type)( HMIDIIN hmi, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2); +extern midiInMessage_type midiInMessage_orig; +typedef UINT (WINAPI *auxGetNumDevs_type)(void); +extern auxGetNumDevs_type auxGetNumDevs_orig; +typedef MMRESULT (WINAPI *auxGetDevCapsA_type)( UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac); +extern auxGetDevCapsA_type auxGetDevCapsA_orig; +typedef MMRESULT (WINAPI *auxGetDevCapsW_type)( UINT_PTR uDeviceID, LPAUXCAPSW pac, UINT cbac); +extern auxGetDevCapsW_type auxGetDevCapsW_orig; +typedef MMRESULT (WINAPI *auxSetVolume_type)( UINT uDeviceID, DWORD dwVolume); +extern auxSetVolume_type auxSetVolume_orig; +typedef MMRESULT (WINAPI *auxGetVolume_type)( UINT uDeviceID, LPDWORD pdwVolume); +extern auxGetVolume_type auxGetVolume_orig; +typedef MMRESULT (WINAPI *auxOutMessage_type)( UINT uDeviceID, UINT uMsg, DWORD_PTR dw1, DWORD_PTR dw2); +extern auxOutMessage_type auxOutMessage_orig; +typedef UINT (WINAPI *mixerGetNumDevs_type)(void); +extern mixerGetNumDevs_type mixerGetNumDevs_orig; +typedef MMRESULT (WINAPI *mixerGetDevCapsA_type)( UINT_PTR uMxId, LPMIXERCAPSA pmxcaps, UINT cbmxcaps); +extern mixerGetDevCapsA_type mixerGetDevCapsA_orig; +typedef MMRESULT (WINAPI *mixerGetDevCapsW_type)( UINT_PTR uMxId, LPMIXERCAPSW pmxcaps, UINT cbmxcaps); +extern mixerGetDevCapsW_type mixerGetDevCapsW_orig; +typedef MMRESULT (WINAPI *mixerOpen_type)( LPHMIXER phmx, UINT uMxId, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); +extern mixerOpen_type mixerOpen_orig; +typedef MMRESULT (WINAPI *mixerClose_type)( HMIXER hmx); +extern mixerClose_type mixerClose_orig; +typedef DWORD (WINAPI *mixerMessage_type)( HMIXER hmx, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); +extern mixerMessage_type mixerMessage_orig; +typedef MMRESULT (WINAPI *mixerGetLineInfoA_type)( HMIXEROBJ hmxobj, LPMIXERLINEA pmxl, DWORD fdwInfo); +extern mixerGetLineInfoA_type mixerGetLineInfoA_orig; +typedef MMRESULT (WINAPI *mixerGetLineInfoW_type)( HMIXEROBJ hmxobj, LPMIXERLINEW pmxl, DWORD fdwInfo); +extern mixerGetLineInfoW_type mixerGetLineInfoW_orig; +typedef MMRESULT (WINAPI *mixerGetID_type)( HMIXEROBJ hmxobj, UINT FAR *puMxId, DWORD fdwId); +extern mixerGetID_type mixerGetID_orig; +typedef MMRESULT (WINAPI *mixerGetLineControlsA_type)( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSA pmxlc, DWORD fdwControls); +extern mixerGetLineControlsA_type mixerGetLineControlsA_orig; +typedef MMRESULT (WINAPI *mixerGetLineControlsW_type)( HMIXEROBJ hmxobj, LPMIXERLINECONTROLSW pmxlc, DWORD fdwControls); +extern mixerGetLineControlsW_type mixerGetLineControlsW_orig; +typedef MMRESULT (WINAPI *mixerGetControlDetailsA_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails); +extern mixerGetControlDetailsA_type mixerGetControlDetailsA_orig; +typedef MMRESULT (WINAPI *mixerGetControlDetailsW_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails); +extern mixerGetControlDetailsW_type mixerGetControlDetailsW_orig; +typedef MMRESULT (WINAPI *mixerSetControlDetails_type)( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails); +extern mixerSetControlDetails_type mixerSetControlDetails_orig; +typedef DWORD    (WINAPI *mmGetCurrentTask_type)(void); +extern mmGetCurrentTask_type mmGetCurrentTask_orig; +typedef void (WINAPI *mmTaskBlock_type)(DWORD); +extern mmTaskBlock_type mmTaskBlock_orig; +typedef UINT (WINAPI *mmTaskCreate_type)(LPTASKCALLBACK, HANDLE*, DWORD_PTR); +extern mmTaskCreate_type mmTaskCreate_orig; +typedef BOOL (WINAPI *mmTaskSignal_type)(DWORD); +extern mmTaskSignal_type mmTaskSignal_orig; +typedef VOID (WINAPI *mmTaskYield_type)(VOID); +extern mmTaskYield_type mmTaskYield_orig; +typedef MMRESULT (WINAPI *timeGetSystemTime_type)( LPMMTIME pmmt, UINT cbmmt); +extern timeGetSystemTime_type timeGetSystemTime_orig; +typedef DWORD (WINAPI *timeGetTime_type)(void); +extern timeGetTime_type timeGetTime_orig; +typedef MMRESULT (WINAPI *timeSetEvent_type)( UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent); +extern timeSetEvent_type timeSetEvent_orig; +typedef MMRESULT (WINAPI *timeKillEvent_type)( UINT uTimerID); +extern timeKillEvent_type timeKillEvent_orig; +typedef MMRESULT (WINAPI *timeGetDevCaps_type)( LPTIMECAPS ptc, UINT cbtc); +extern timeGetDevCaps_type timeGetDevCaps_orig; +typedef MMRESULT (WINAPI *timeBeginPeriod_type)( UINT uPeriod); +extern timeBeginPeriod_type timeBeginPeriod_orig; +typedef MMRESULT (WINAPI *timeEndPeriod_type)( UINT uPeriod); +extern timeEndPeriod_type timeEndPeriod_orig; +typedef UINT (WINAPI *joyGetNumDevs_type)(void); +extern joyGetNumDevs_type joyGetNumDevs_orig; +typedef MMRESULT (WINAPI *joyConfigChanged_type)(DWORD dwFlags); +extern joyConfigChanged_type joyConfigChanged_orig; +typedef MMRESULT (WINAPI *joyGetDevCapsA_type)( UINT_PTR uJoyID, LPJOYCAPSA pjc, UINT cbjc); +extern joyGetDevCapsA_type joyGetDevCapsA_orig; +typedef MMRESULT (WINAPI *joyGetDevCapsW_type)( UINT_PTR uJoyID, LPJOYCAPSW pjc, UINT cbjc); +extern joyGetDevCapsW_type joyGetDevCapsW_orig; +typedef MMRESULT (WINAPI *joyGetPos_type)( UINT uJoyID, LPJOYINFO pji); +extern joyGetPos_type joyGetPos_orig; +typedef MMRESULT (WINAPI *joyGetPosEx_type)( UINT uJoyID, LPJOYINFOEX pji); +extern joyGetPosEx_type joyGetPosEx_orig; +typedef MMRESULT (WINAPI *joyGetThreshold_type)( UINT uJoyID, LPUINT puThreshold); +extern joyGetThreshold_type joyGetThreshold_orig; +typedef MMRESULT (WINAPI *joyReleaseCapture_type)( UINT uJoyID); +extern joyReleaseCapture_type joyReleaseCapture_orig; +typedef MMRESULT (WINAPI *joySetCapture_type)( HWND hwnd, UINT uJoyID, UINT uPeriod, BOOL fChanged); +extern joySetCapture_type joySetCapture_orig; +typedef MMRESULT (WINAPI *joySetThreshold_type)( UINT uJoyID, UINT uThreshold); +extern joySetThreshold_type joySetThreshold_orig; +typedef BOOL (WINAPI  *mciDriverNotify_type)(HWND hwndCallback, UINT uDeviceID, UINT uStatus); +extern mciDriverNotify_type mciDriverNotify_orig; +typedef UINT (WINAPI  *mciDriverYield_type)(UINT uDeviceID); +extern mciDriverYield_type mciDriverYield_orig; +typedef FOURCC (WINAPI *mmioStringToFOURCCA_type)( LPCSTR sz, UINT uFlags); +extern mmioStringToFOURCCA_type mmioStringToFOURCCA_orig; +typedef FOURCC (WINAPI *mmioStringToFOURCCW_type)( LPCWSTR sz, UINT uFlags); +extern mmioStringToFOURCCW_type mmioStringToFOURCCW_orig; +typedef LPMMIOPROC (WINAPI *mmioInstallIOProcA_type)( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags); +extern mmioInstallIOProcA_type mmioInstallIOProcA_orig; +typedef LPMMIOPROC (WINAPI *mmioInstallIOProcW_type)( FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags); +extern mmioInstallIOProcW_type mmioInstallIOProcW_orig; +typedef HMMIO (WINAPI *mmioOpenA_type)( LPSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen); +extern mmioOpenA_type mmioOpenA_orig; +typedef HMMIO (WINAPI *mmioOpenW_type)( LPWSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen); +extern mmioOpenW_type mmioOpenW_orig; +typedef MMRESULT (WINAPI *mmioRenameA_type)( LPCSTR pszFileName, LPCSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename); +extern mmioRenameA_type mmioRenameA_orig; +typedef MMRESULT (WINAPI *mmioRenameW_type)( LPCWSTR pszFileName, LPCWSTR pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename); +extern mmioRenameW_type mmioRenameW_orig; +typedef MMRESULT (WINAPI *mmioClose_type)( HMMIO hmmio, UINT fuClose); +extern mmioClose_type mmioClose_orig; +typedef LONG (WINAPI *mmioRead_type)( HMMIO hmmio, HPSTR pch, LONG cch); +extern mmioRead_type mmioRead_orig; +typedef LONG (WINAPI *mmioWrite_type)( HMMIO hmmio, const char _huge* pch, LONG cch); +extern mmioWrite_type mmioWrite_orig; +typedef LONG (WINAPI *mmioSeek_type)( HMMIO hmmio, LONG lOffset, int iOrigin); +extern mmioSeek_type mmioSeek_orig; +typedef MMRESULT (WINAPI *mmioGetInfo_type)( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuInfo); +extern mmioGetInfo_type mmioGetInfo_orig; +typedef MMRESULT (WINAPI *mmioSetInfo_type)( HMMIO hmmio, LPCMMIOINFO pmmioinfo, UINT fuInfo); +extern mmioSetInfo_type mmioSetInfo_orig; +typedef MMRESULT (WINAPI *mmioSetBuffer_type)( HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer); +extern mmioSetBuffer_type mmioSetBuffer_orig; +typedef MMRESULT (WINAPI *mmioFlush_type)( HMMIO hmmio, UINT fuFlush); +extern mmioFlush_type mmioFlush_orig; +typedef MMRESULT (WINAPI *mmioAdvance_type)( HMMIO hmmio, LPMMIOINFO pmmioinfo, UINT fuAdvance); +extern mmioAdvance_type mmioAdvance_orig; +typedef LRESULT (WINAPI *mmioSendMessage_type)( HMMIO hmmio, UINT uMsg, LPARAM lParam1, LPARAM lParam2); +extern mmioSendMessage_type mmioSendMessage_orig; +typedef MMRESULT (WINAPI *mmioDescend_type)( HMMIO hmmio, LPMMCKINFO pmmcki, const MMCKINFO FAR* pmmckiParent, UINT fuDescend); +extern mmioDescend_type mmioDescend_orig; +typedef MMRESULT (WINAPI *mmioAscend_type)( HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuAscend); +extern mmioAscend_type mmioAscend_orig; +typedef MMRESULT (WINAPI *mmioCreateChunk_type)(HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuCreate); +extern mmioCreateChunk_type mmioCreateChunk_orig; +typedef MCIERROR (WINAPI *mciSendCommandA_type)( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); +extern mciSendCommandA_type mciSendCommandA_orig; +typedef MCIERROR (WINAPI *mciSendCommandW_type)( MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); +extern mciSendCommandW_type mciSendCommandW_orig; +typedef MCIERROR  (WINAPI *mciSendStringA_type)( LPCSTR lpstrCommand, LPSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback); +extern mciSendStringA_type mciSendStringA_orig; +typedef MCIERROR  (WINAPI *mciSendStringW_type)( LPCWSTR lpstrCommand, LPWSTR lpstrReturnString, UINT uReturnLength, HWND hwndCallback); +extern mciSendStringW_type mciSendStringW_orig; +typedef MCIDEVICEID (WINAPI *mciGetDeviceIDA_type)( LPCSTR pszDevice); +extern mciGetDeviceIDA_type mciGetDeviceIDA_orig; +typedef MCIDEVICEID (WINAPI *mciGetDeviceIDW_type)( LPCWSTR pszDevice); +extern mciGetDeviceIDW_type mciGetDeviceIDW_orig; +typedef MCIDEVICEID (WINAPI *mciGetDeviceIDFromElementIDA_type)( DWORD dwElementID, LPCSTR lpstrType ); +extern mciGetDeviceIDFromElementIDA_type mciGetDeviceIDFromElementIDA_orig; +typedef MCIDEVICEID (WINAPI *mciGetDeviceIDFromElementIDW_type)( DWORD dwElementID, LPCWSTR lpstrType ); +extern mciGetDeviceIDFromElementIDW_type mciGetDeviceIDFromElementIDW_orig; +typedef DWORD_PTR (WINAPI  *mciGetDriverData_type)(UINT uDeviceID); +extern mciGetDriverData_type mciGetDriverData_orig; +typedef BOOL (WINAPI *mciGetErrorStringA_type)( MCIERROR mcierr, LPSTR pszText, UINT cchText); +extern mciGetErrorStringA_type mciGetErrorStringA_orig; +typedef BOOL (WINAPI *mciGetErrorStringW_type)( MCIERROR mcierr, LPWSTR pszText, UINT cchText); +extern mciGetErrorStringW_type mciGetErrorStringW_orig; +typedef BOOL (WINAPI  *mciSetDriverData_type)(UINT uDeviceID, DWORD_PTR dwData); +extern mciSetDriverData_type mciSetDriverData_orig; +typedef BOOL (WINAPI *mciSetYieldProc_type)( MCIDEVICEID mciId, YIELDPROC fpYieldProc, DWORD dwYieldData); +extern mciSetYieldProc_type mciSetYieldProc_orig; +typedef BOOL (WINAPI  *mciFreeCommandResource_type)(UINT uTable); +extern mciFreeCommandResource_type mciFreeCommandResource_orig; +typedef HTASK (WINAPI *mciGetCreatorTask_type)( MCIDEVICEID mciId); +extern mciGetCreatorTask_type mciGetCreatorTask_orig; +typedef YIELDPROC (WINAPI *mciGetYieldProc_type)( MCIDEVICEID mciId, LPDWORD pdwYieldData); +extern mciGetYieldProc_type mciGetYieldProc_orig; +typedef UINT (WINAPI *mciLoadCommandResource_type)(HINSTANCE hInstance, LPCWSTR lpResName, UINT uType); +extern mciLoadCommandResource_type mciLoadCommandResource_orig; +typedef BOOL (WINAPI *mciExecute_type)(LPCSTR pszCommand); +extern mciExecute_type mciExecute_orig; diff --git a/indra/media_plugins/winmmshim/winmm.def b/indra/media_plugins/winmmshim/winmm.def new file mode 100644 index 0000000000..c55a2845f8 --- /dev/null +++ b/indra/media_plugins/winmmshim/winmm.def @@ -0,0 +1,218 @@ +;  +;   winmm.def +; +;   Exports for WINMM DLL +; + +LIBRARY WINMM +EXPORTS +CloseDriver +DefDriverProc +DriverCallback +DrvGetModuleHandle +GetDriverModuleHandle +;MigrateAllDrivers +;MigrateSoundEvents +;NotifyCallbackData +OpenDriver +;PlaySound +PlaySoundA +PlaySoundW +SendDriverMessage +;WOW32DriverCallback +;WOW32ResolveMultiMediaHandle +;WOWAppExit +;WinmmLogoff +;WinmmLogon +;aux32Message +auxGetDevCapsA +auxGetDevCapsW +auxGetNumDevs +auxGetVolume +auxOutMessage +auxSetVolume +;gfxAddGfx +;gfxBatchChange +;gfxCreateGfxFactoriesList +;gfxCreateZoneFactoriesList +;gfxDestroyDeviceInterfaceList +;gfxEnumerateGfxs +;gfxLogoff +;gfxLogon +;gfxModifyGfx +;gfxOpenGfx +;gfxRemoveGfx +;joy32Message +joyConfigChanged +joyGetDevCapsA +joyGetDevCapsW +joyGetNumDevs +joyGetPos +joyGetPosEx +joyGetThreshold +joyReleaseCapture +joySetCapture +joySetThreshold +;mci32Message +mciDriverNotify +mciDriverYield +mciExecute +mciFreeCommandResource +mciGetCreatorTask +mciGetDeviceIDA +mciGetDeviceIDFromElementIDA +mciGetDeviceIDFromElementIDW +mciGetDeviceIDW +mciGetDriverData +mciGetErrorStringA +mciGetErrorStringW +mciGetYieldProc +mciLoadCommandResource +mciSendCommandA +mciSendCommandW +mciSendStringA +mciSendStringW +mciSetDriverData +mciSetYieldProc +;mid32Message +midiConnect +midiDisconnect +midiInAddBuffer +midiInClose +midiInGetDevCapsA +midiInGetDevCapsW +midiInGetErrorTextA +midiInGetErrorTextW +midiInGetID +midiInGetNumDevs +midiInMessage +midiInOpen +midiInPrepareHeader +midiInReset +midiInStart +midiInStop +midiInUnprepareHeader +midiOutCacheDrumPatches +midiOutCachePatches +midiOutClose +midiOutGetDevCapsA +midiOutGetDevCapsW +midiOutGetErrorTextA +midiOutGetErrorTextW +midiOutGetID +midiOutGetNumDevs +midiOutGetVolume +midiOutLongMsg +midiOutMessage +midiOutOpen +midiOutPrepareHeader +midiOutReset +midiOutSetVolume +midiOutShortMsg +midiOutUnprepareHeader +midiStreamClose +midiStreamOpen +midiStreamOut +midiStreamPause +midiStreamPosition +midiStreamProperty +midiStreamRestart +midiStreamStop +mixerClose +mixerGetControlDetailsA +mixerGetControlDetailsW +mixerGetDevCapsA +mixerGetDevCapsW +mixerGetID +mixerGetLineControlsA +mixerGetLineControlsW +mixerGetLineInfoA +mixerGetLineInfoW +mixerGetNumDevs +mixerMessage +mixerOpen +mixerSetControlDetails +;mmDrvInstall +mmGetCurrentTask +mmTaskBlock +mmTaskCreate +mmTaskSignal +mmTaskYield +mmioAdvance +mmioAscend +mmioClose +mmioCreateChunk +mmioDescend +mmioFlush +mmioGetInfo +mmioInstallIOProcA +mmioInstallIOProcW +mmioOpenA +mmioOpenW +mmioRead +mmioRenameA +mmioRenameW +mmioSeek +mmioSendMessage +mmioSetBuffer +mmioSetInfo +mmioStringToFOURCCA +mmioStringToFOURCCW +mmioWrite +mmsystemGetVersion +;mod32Message +;mxd32Message +sndPlaySoundA +sndPlaySoundW +;tid32Message +timeBeginPeriod +timeEndPeriod +timeGetDevCaps +timeGetSystemTime +timeGetTime +timeKillEvent +timeSetEvent +waveInAddBuffer +waveInClose +waveInGetDevCapsA +waveInGetDevCapsW +waveInGetErrorTextA +waveInGetErrorTextW +waveInGetID +waveInGetNumDevs +waveInGetPosition +waveInMessage +waveInOpen +waveInPrepareHeader +waveInReset +waveInStart +waveInStop +waveInUnprepareHeader +waveOutBreakLoop +waveOutClose +waveOutGetDevCapsA +waveOutGetDevCapsW +waveOutGetErrorTextA +waveOutGetErrorTextW +waveOutGetID +waveOutGetNumDevs +waveOutGetPitch +waveOutGetPlaybackRate +waveOutGetPosition +waveOutGetVolume +waveOutMessage +waveOutOpen +waveOutPause +waveOutPrepareHeader +waveOutReset +waveOutRestart +waveOutSetPitch +waveOutSetPlaybackRate +waveOutSetVolume +waveOutUnprepareHeader +waveOutWrite +;wid32Message +;winmmSetDebugLevel +;wod32Message +setPluginVolume +setPluginMute
\ No newline at end of file diff --git a/indra/media_plugins/winmmshim/winmm_shim.cpp b/indra/media_plugins/winmmshim/winmm_shim.cpp new file mode 100644 index 0000000000..54bfa652e9 --- /dev/null +++ b/indra/media_plugins/winmmshim/winmm_shim.cpp @@ -0,0 +1,193 @@ +/**  + * @file winmmshim.cpp + * @brief controls volume level of process by intercepting calls to winmm.dll + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "forwarding_api.h" +#include <xmmintrin.h> +#include <map> +#include <math.h> + +using std::wstring; + +static float sVolumeLevel = 1.f; +static bool sMute = false; + +BOOL APIENTRY DllMain( HMODULE hModule, +                       DWORD  ul_reason_for_call, +                       LPVOID lpReserved +					 ) +{ +	static bool initialized = false; +	// do this only once +	if (!initialized) +	{	// bind to original winmm.dll +		TCHAR system_path[MAX_PATH]; +		TCHAR dll_path[MAX_PATH]; +		::GetSystemDirectory(system_path, MAX_PATH); + +		// grab winmm.dll from system path, where it should live +		wsprintf(dll_path, "%s\\winmm.dll", system_path); +		HMODULE winmm_handle = ::LoadLibrary(dll_path); +		 +		if (winmm_handle != NULL) +		{	// we have a dll, let's get out pointers! +			initialized = true; +			init_function_pointers(winmm_handle); +			return true; +		} + +		// failed to initialize real winmm.dll +		return false; +	} +	return true; +} + + +extern "C"  +{ +	// tracks the requested format for a given waveout buffer +	struct WaveOutFormat +	{ +		WaveOutFormat(int bits_per_sample) +		:	mBitsPerSample(bits_per_sample) +		{} +		int	mBitsPerSample; +	}; +	typedef std::map<HWAVEOUT, WaveOutFormat*> wave_out_map_t; +	static wave_out_map_t sWaveOuts; + +	MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) +	{ +		if (pwfx->wFormatTag != WAVE_FORMAT_PCM +			|| (pwfx->wBitsPerSample != 8 && pwfx->wBitsPerSample != 16)) +		{ // uncompressed 8 and 16 bit sound are the only types we support +			return WAVERR_BADFORMAT; +		} + +		MMRESULT result = waveOutOpen_orig(phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen); +		if (result == MMSYSERR_NOERROR  +			&& ((fdwOpen & WAVE_FORMAT_QUERY) == 0)) // not just querying for format support +		{	// remember the requested bits per sample, and associate with the given handle +			WaveOutFormat* wave_outp = new WaveOutFormat(pwfx->wBitsPerSample); +			sWaveOuts.insert(std::make_pair(*phwo, wave_outp)); +		} +		return result; +	} + +	MMRESULT WINAPI waveOutClose( HWAVEOUT hwo) +	{ +		wave_out_map_t::iterator found_it = sWaveOuts.find(hwo); +		if (found_it != sWaveOuts.end()) +		{	// forget what we know about this handle +			delete found_it->second; +			sWaveOuts.erase(found_it); +		} +		return waveOutClose_orig( hwo); +	} + +	MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) +	{ +		MMRESULT result = MMSYSERR_NOERROR; + +		if (sMute) +		{ // zero out the audio buffer when muted +			memset(pwh->lpData, 0, pwh->dwBufferLength); +		} +		else +		{ +			wave_out_map_t::iterator found_it = sWaveOuts.find(hwo); +			if (found_it != sWaveOuts.end()) +			{ +				WaveOutFormat* formatp = found_it->second; +				switch (formatp->mBitsPerSample){ +				case 8: +					{ +						char volume = (char)(sVolumeLevel * 127.f); +						for (unsigned int i = 0; i < pwh->dwBufferLength; i++) +						{ +							// unsigned multiply doesn't use most significant bit, so shift by 7 bits +							// to get resulting value back into 8 bits +							pwh->lpData[i] = (pwh->lpData[i] * volume) >> 7; +						} +						break; +					} +				case 16: +					{ +						short volume_16 = (short)(sVolumeLevel * 32767.f); + +						// copy volume level 4 times into 64 bit MMX register +						__m64 volume_64 = _mm_set_pi16(volume_16, volume_16, volume_16, volume_16); +						__m64* sample_64; +						__m64* last_sample_64 =  (__m64*)(pwh->lpData + pwh->dwBufferLength - sizeof(__m64)); +						// for everything that can be addressed in 64 bit multiples... +						for (sample_64 = (__m64*)pwh->lpData; +							sample_64 <= last_sample_64; +							++sample_64) +						{ +							//...multiply the samples by the volume... +							__m64 scaled_sample = _mm_mulhi_pi16(*sample_64, volume_64); +							// ...and shift left 1 bit since an unsigned multiple loses the most significant bit +							// 0x7FFF * 0x7FFF = 0x3fff0001 +							// 0x3fff0001 << 1 = 0x7ffe0002 +							// notice that the LSB is always 0...should consider dithering +							*sample_64 =  _mm_slli_pi16(scaled_sample, 1);  +						} + +						// the captain has turned off the MMX sign, you are now free to use floating point registers +						_mm_empty(); + +						for (short* sample_16 = (short*)sample_64; +							sample_16 < (short*)(pwh->lpData + pwh->dwBufferLength); +							++sample_16) +						{	// finish remaining samples that didn't fit into 64 bit register +							*sample_16 = (*sample_16 * volume_16) >> 15; +						} + +						break; +					} +				default: +					// don't do anything +					break; +				} +			} +		} +		return waveOutWrite_orig( hwo, pwh, cbwh); +	} + +	void WINAPI setPluginVolume(float volume) +	{ +		sVolumeLevel = volume; +	} + +	void WINAPI setPluginMute(bool mute) +	{ +		sMute = mute; +	} +} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 75807cec95..3664a5f05c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1472,8 +1472,6 @@ if (WINDOWS)        ${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt        ${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll        ${CMAKE_CURRENT_SOURCE_DIR}/fmod.dll -      ${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}/media_plugin_quicktime.dll -      ${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}/media_plugin_webkit.dll        ${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll        ${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll        ${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll @@ -1513,6 +1511,7 @@ if (WINDOWS)        SLPlugin        media_plugin_quicktime        media_plugin_webkit +      winmm_shim        windows-crash-logger        windows-updater        ) @@ -1553,8 +1552,6 @@ if (WINDOWS)      add_dependencies(${VIEWER_BINARY_NAME}         SLPlugin  -      media_plugin_quicktime  -      media_plugin_webkit        windows-updater         windows-crash-logger        ) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a820d82f6f..c5602d1bcc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5596,6 +5596,19 @@        <key>Value</key>        <integer>8</integer>      </map> + +   <key>PluginUseReadThread</key> +    <map> +      <key>Comment</key> +      <string>Use a separate thread to read incoming messages from plugins</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +      <key>PrecachingDelay</key>      <map>        <key>Comment</key> @@ -5849,7 +5862,18 @@          <key>Value</key>              <real>1.0</real>          </map> -    <key>RecentItemsSortOrder</key> +  <key>MediaRollOffFactor</key> +  <map> +    <key>Comment</key> +    <string>Multiplier to change rate of media attenuation</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>F32</string> +    <key>Value</key> +    <real>10.0</real> +  </map> +  <key>RecentItemsSortOrder</key>      <map>        <key>Comment</key>        <string>Specifies sort key for recent inventory items (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top)</string> diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 1c29dae5f7..6e38caf5ef 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -14,14 +14,15 @@ varying vec3 vary_mat2;  void main()   { -	vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; +	vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb;  	vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0;  	vec3 tnorm = vec3(dot(norm,vary_mat0), -					  dot(norm,vary_mat1), -					  dot(norm,vary_mat2)); +			  dot(norm,vary_mat1), +			  dot(norm,vary_mat2)); -	gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); -	gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a); +	gl_FragData[0] = vec4(col, 0.0); +	gl_FragData[1] = gl_Color.aaaa; // spec +	//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested  	gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0);  } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 5895ebda84..112103956d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -11,8 +11,9 @@ varying vec3 vary_normal;  void main()   { -	vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; -	gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); -	gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); +	vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; +	gl_FragData[0] = vec4(col, 0.0); +	gl_FragData[1] = gl_Color.aaaa; // spec +	//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested  	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);  } diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 8a880e5ace..b5fde0baca 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1974,7 +1974,11 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra  		msg->nextBlockFast(_PREHASH_ObjectData );  		msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());  		msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); +#if ENABLE_MULTIATTACHMENTS +		msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD ); +#else  		msg->addU8Fast(_PREHASH_AttachmentPt, 0 );	// Wear at the previous or default attachment point +#endif  		pack_permissions_slam(msg, item->getFlags(), item->getPermissions());  		msg->addStringFast(_PREHASH_Name, item->getName());  		msg->addStringFast(_PREHASH_Description, item->getDescription()); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5586b3cd4d..e93e29ecde 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1092,7 +1092,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF()  	}  	//preparing the list of wearables in the correct order for LLAgentWearables -	std::sort(wear_items.begin(), wear_items.end(), sort_by_description); +	sortItemsByActualDescription(wear_items); +  	LLWearableHoldingPattern* holder = new LLWearableHoldingPattern; @@ -1910,6 +1911,13 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b  	return result;  } +//static +void LLAppearanceMgr::sortItemsByActualDescription(LLInventoryModel::item_array_t& items) +{ +	if (items.size() < 2) return; + +	std::sort(items.begin(), items.end(), sort_by_description); +}  //#define DUMP_CAT_VERBOSE diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index a308a3efa9..516dada39d 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -48,6 +48,8 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>  	friend class LLSingleton<LLAppearanceMgr>;  public: +	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t; +  	void updateAppearanceFromCOF();  	bool needToSaveCOF();  	void updateCOF(const LLUUID& category, bool append = false); @@ -143,17 +145,17 @@ public:  	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body); +	static void sortItemsByActualDescription(LLInventoryModel::item_array_t& items); + +	//Divvy items into arrays by wearable type +	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type); +  protected:  	LLAppearanceMgr();  	~LLAppearanceMgr();  private: -	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t; - -	//Divvy items into arrays by wearable type -	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type); -  	//Check ordering information on wearables stored in links' descriptions and update if it is invalid  	void updateClothingOrderingInfo(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7bfe6a46c9..8f14b8d782 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1548,6 +1548,9 @@ bool LLAppViewer::cleanup()  	LLViewerMedia::saveCookieFile(); +	// Stop the plugin read thread if it's running. +	LLPluginProcessParent::setUseReadThread(false); +  	llinfos << "Shutting down Threads" << llendflush;  	// Let threads finish diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index fd0b20281b..dfb213716c 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -177,13 +177,15 @@ void LLAvatarList::clear()  void LLAvatarList::setNameFilter(const std::string& filter)  { -	if (mNameFilter != filter) +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper)  	{ -		mNameFilter = filter; +		mNameFilter = filter_upper;  		// update message for empty state here instead of refresh() to avoid blinking when switch  		// between tabs. -		updateNoItemsMessage(!mNameFilter.empty()); +		updateNoItemsMessage(filter);  		setDirty();  	}  } diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 4f9434030f..fafa315a59 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -243,3 +243,19 @@ void LLChannelManager::killToastsFromChannel(const LLUUID& channel_id, const LLS  	}  } +// static +LLNotificationsUI::LLScreenChannel* LLChannelManager::getNotificationScreenChannel() +{ +	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> +	(LLNotificationsUI::LLChannelManager::getInstance()-> +										findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + +	if (channel == NULL) +	{ +		llwarns << "Can't find screen channel by NotificationChannelUUID" << llendl; +		llassert(!"Can't find screen channel by NotificationChannelUUID"); +	} + +	return channel; +} + diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index c2be39122f..8c725f2660 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -114,6 +114,11 @@ public:  	 */  	void killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher); +	/** +	 * Returns notification screen channel. +	 */ +	static LLNotificationsUI::LLScreenChannel* getNotificationScreenChannel(); +  private:  	LLScreenChannel* createChannel(LLChannelManager::Params& p); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 489c66be71..9d421b4f0b 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -921,6 +921,9 @@ protected:  class LLNotificationChiclet : public LLSysWellChiclet  {  	friend class LLUICtrlFactory; +public: +	struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{}; +  protected:  	LLNotificationChiclet(const Params& p); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index f0442ee3f6..b8222ebb18 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -89,52 +89,144 @@ void LLCOFWearables::onSelectionChange(LLFlatListView* selected_list)  	onCommit();  } +#include "llwearableitemslist.h"  void LLCOFWearables::refresh()  {  	clear();  	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; +	LLInventoryModel::item_array_t cof_items; + +	gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, cof_items, LLInventoryModel::EXCLUDE_TRASH); + +	populateAttachmentsAndBodypartsLists(cof_items); + + +	LLAppearanceMgr::wearables_by_type_t clothing_by_type(WT_COUNT); +	LLAppearanceMgr::getInstance()->divvyWearablesByType(cof_items, clothing_by_type); -	gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH); -	if (items.empty()) return; +	populateClothingList(clothing_by_type); +} + -	for (U32 i = 0; i < items.size(); ++i) +void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items) +{ +	for (U32 i = 0; i < cof_items.size(); ++i)  	{ -		LLViewerInventoryItem* item = items.get(i); +		LLViewerInventoryItem* item = cof_items.get(i);  		if (!item) continue; -		LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item); -		if (!item_panel) continue; - -		switch (item->getType()) +		const LLAssetType::EType item_type = item->getType(); +		if (item_type == LLAssetType::AT_CLOTHING) continue; +		LLPanelInventoryListItemBase* item_panel = NULL; +		if (item_type == LLAssetType::AT_OBJECT)  		{ -			case LLAssetType::AT_OBJECT: -				mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); -				break; +				item_panel = LLPanelInventoryListItemBase::create(item); +			mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); +		} +		else if (item_type == LLAssetType::AT_BODYPART) +		{ +			item_panel = LLPanelBodyPartsListItem::create(item); +			mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); +			addWearableTypeSeparator(mBodyParts); +		} +	} + +	if (mAttachments->size()) +	{ +		mAttachments->sort(); //*TODO by Name +		mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false) +	} -			case LLAssetType::AT_BODYPART: -				mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); -				break; +	if (mBodyParts->size()) +	{ +		mBodyParts->sort(); //*TODO by name +	} + +	addListButtonBar(mBodyParts, "panel_bodyparts_list_button_bar.xml"); +	mBodyParts->notify(REARRANGE); +} + + +void LLCOFWearables::populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type) +{ +	llassert(clothing_by_type.size() == WT_COUNT); + +	addListButtonBar(mClothing, "panel_clothing_list_button_bar.xml"); + +	for (U32 type = WT_SHIRT; type < WT_COUNT; ++type) +	{ +		U32 size = clothing_by_type[type].size(); +		if (!size) continue; + +		LLAppearanceMgr::sortItemsByActualDescription(clothing_by_type[type]); + +		for (U32 i = 0; i < size; i++) +		{ +			LLViewerInventoryItem* item = clothing_by_type[type][i]; -			case LLAssetType::AT_CLOTHING: -				mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); -				break; +			LLPanelInventoryListItemBase* item_panel = LLPanelClothingListItem::create(item); +			if (!item_panel) continue; -			default: break; +			mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);  		} + +		addWearableTypeSeparator(mClothing);  	} -	mAttachments->sort(); //*TODO by Name -	mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false) -	 -	mClothing->sort(); //*TODO by actual inventory item description +	addClothingTypesDummies(clothing_by_type); +  	mClothing->notify(REARRANGE); +} + +void LLCOFWearables::addListButtonBar(LLFlatListView* list, std::string xml_filename) +{ +	llassert(list); +	llassert(xml_filename.length()); -	mBodyParts->sort(); //*TODO by name -	mBodyParts->notify(REARRANGE); +	LLPanel::Params params; +	LLPanel* button_bar = LLUICtrlFactory::create<LLPanel>(params); +	LLUICtrlFactory::instance().buildPanel(button_bar, xml_filename); + +	LLRect rc = button_bar->getRect(); +	button_bar->reshape(list->getItemsRect().getWidth(), rc.getHeight()); + +	list->addItem(button_bar, LLUUID::null, ADD_TOP, false); +} + +//adding dummy items for missing wearable types +void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type) +{ +	llassert(clothing_by_type.size() == WT_COUNT); +	 +	for (U32 type = WT_SHIRT; type < WT_COUNT; type++) +	{ +		U32 size = clothing_by_type[type].size(); +		if (size) continue; + +		EWearableType w_type = static_cast<EWearableType>(type); +		LLPanelInventoryListItemBase* item_panel = LLPanelDummyClothingListItem::create(w_type); +		if(!item_panel) continue; +		mClothing->addItem(item_panel, LLUUID::null, ADD_BOTTOM, false); +		addWearableTypeSeparator(mClothing); +	}  } +void LLCOFWearables::addWearableTypeSeparator(LLFlatListView* list) +{ +	llassert(list); +	 +	static LLXMLNodePtr separator_xml_node = getXMLNode("panel_wearable_type_separator.xml"); +	if (separator_xml_node->isNull()) return; + +	LLPanel* separator = LLUICtrlFactory::defaultBuilder<LLPanel>(separator_xml_node, NULL, NULL); + +	LLRect rc = separator->getRect(); +	rc.setOriginAndSize(0, 0, list->getItemsRect().getWidth(), rc.getHeight()); +	separator->setRect(rc); + +	list->addItem(separator, LLUUID::null, ADD_BOTTOM, false); +}  LLUUID LLCOFWearables::getSelectedUUID()  { @@ -150,4 +242,17 @@ void LLCOFWearables::clear()  	mBodyParts->clear();  } +LLXMLNodePtr LLCOFWearables::getXMLNode(std::string xml_filename) +{ +	LLXMLNodePtr xmlNode = NULL; +	bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, xmlNode); +	if (!success) +	{ +		llwarning("Failed to read xml", 0); +		return NULL; +	} + +	return xmlNode; +} +  //EOF diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h index 58d67ed32f..fec6d34db2 100644 --- a/indra/newview/llcofwearables.h +++ b/indra/newview/llcofwearables.h @@ -34,6 +34,8 @@  #define LL_LLCOFWEARABLES_H  #include "llpanel.h" +#include "llinventorymodel.h" +#include "llappearancemgr.h"  class LLFlatListView; @@ -52,8 +54,16 @@ public:  protected: +	void populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items); +	void populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type); +	 +	void addListButtonBar(LLFlatListView* list, std::string xml_filename); +	void addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type); +	void addWearableTypeSeparator(LLFlatListView* list);  	void onSelectionChange(LLFlatListView* selected_list); +	LLXMLNodePtr getXMLNode(std::string xml_filename); +  	LLFlatListView* mAttachments;  	LLFlatListView* mClothing;  	LLFlatListView* mBodyParts; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index c492bfcef1..eba4cdfa31 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -946,7 +946,9 @@ void LLFolderView::draw()  		}  		else  		{ -			mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage()); +			LLStringUtil::format_map_t args; +			args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); +			mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);  			//font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL,  LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );  		}  		mStatusTextBox->setValue(mStatusText); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index f21b6e1085..252c34cf9c 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -131,9 +131,15 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  void LLGroupList::setNameFilter(const std::string& filter)  { -	if (mNameFilter != filter) +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper)  	{ -		mNameFilter = filter; +		mNameFilter = filter_upper; + +		// set no items message depend on filter state +		updateNoItemsMessage(filter); +  		setDirty();  	}  } @@ -151,9 +157,6 @@ void LLGroupList::refresh()  	LLUUID				id;  	bool				have_filter		= !mNameFilter.empty(); -	// set no items message depend on filter state & total count of groups -	updateNoItemsMessage(have_filter); -  	clear();  	for(S32 i = 0; i < count; ++i) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 19dbc564d1..c0cc3f1985 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -53,6 +53,7 @@  #include "llsyswellwindow.h"  #include "lltrans.h"  #include "llchathistory.h" +#include "llnotifications.h"  #include "llviewerwindow.h"  #include "llvoicechannel.h"  #include "lltransientfloatermgr.h" @@ -371,6 +372,8 @@ void LLIMFloater::onSlide()  //static  LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  { +	closeHiddenIMToasts(); +  	if (!gIMMgr->hasSession(session_id)) return NULL;  	if(!isChatMultiTab()) @@ -1084,6 +1087,26 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)  }  // static +void LLIMFloater::closeHiddenIMToasts() +{ +	class IMToastMatcher: public LLNotificationsUI::LLScreenChannel::Matcher +	{ +	public: +		bool matches(const LLNotificationPtr notification) const +		{ +			// "notifytoast" type of notifications is reserved for IM notifications +			return "notifytoast" == notification->getType(); +		} +	}; + +	LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); +	if (channel != NULL) +	{ +		channel->closeHiddenToasts(IMToastMatcher()); +	} +} + +// static  bool LLIMFloater::isChatMultiTab()  {  	// Restart is required in order to change chat window type. diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 763dd5655b..f9dd8b9b85 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -148,6 +148,8 @@ private:  	// Remove the "User is typing..." indicator.  	void removeTypingIndicator(const LLIMInfo* im_info = NULL); +	static void closeHiddenIMToasts(); +  	LLPanelChatControlPanel* mControlPanel;  	LLUUID mSessionID;  	S32 mLastMessageIndex; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f03026715d..15dbc03f70 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -257,9 +257,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)  { -	std::string you = LLTrans::getString("You"); -	std::string started_call = LLTrans::getString("started_call"); -	std::string joined_call = LLTrans::getString("joined_call"); +	std::string you_joined_call = LLTrans::getString("you_joined_call"); +	std::string you_started_call = LLTrans::getString("you_started_call");  	std::string other_avatar_name = "";  	std::string message; @@ -277,13 +276,15 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				message = other_avatar_name + " " + started_call; -				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); -				 -				break; +				{ +					LLStringUtil::format_map_t string_args; +					string_args["[NAME]"] = other_avatar_name; +					message = LLTrans::getString("name_started_call", string_args); +					LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);				 +					break; +				}  			case LLVoiceChannel::STATE_CONNECTED : -				message = you + " " + joined_call; -				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call);  			default:  				break;  			} @@ -293,8 +294,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				message = you + " " + started_call; -				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call);  				break;  			case LLVoiceChannel::STATE_CONNECTED :  				message = LLTrans::getString("answered_call"); @@ -312,8 +312,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CONNECTED : -				message = you + " " + joined_call; -				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call);  			default:  				break;  			} @@ -323,8 +322,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				message = you + " " + started_call; -				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call);  				break;  			default:  				break; @@ -2069,8 +2067,9 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  				// send notification message to the corresponding chat   				if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc")  				{ -					std::string started_call = LLTrans::getString("started_call"); -					std::string message = mPayload["caller_name"].asString() + " " + started_call; +					LLStringUtil::format_map_t string_args; +					string_args["[NAME]"] = mPayload["caller_name"].asString(); +					std::string message = LLTrans::getString("name_started_call", string_args);  					LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message);  				}  			} diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9a83d9d3b1..ea43670da0 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -212,10 +212,14 @@ BOOL LLInvFVBridge::isItemRemovable() const  		return FALSE;  	} -	// Disable delete from COF folder; have users explicitly choose "detach/take off". +	// Disable delete from COF folder; have users explicitly choose "detach/take off", +	// unless the item is not worn but in the COF (i.e. is bugged).  	if (LLAppearanceMgr::instance().getIsProtectedCOFItem(mUUID))  	{ -		return FALSE; +		if (get_is_item_worn(mUUID)) +		{ +			return FALSE; +		}  	}  	const LLInventoryObject *obj = model->getItem(mUUID); @@ -495,7 +499,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const  			}  		}  		const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); -		if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) +		if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))  		{  			return FALSE;  		} @@ -642,13 +646,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  		disabled_items.push_back(std::string("Paste"));  	} -	if (gAgent.isGodlike()) +	items.push_back(std::string("Paste As Link")); +	if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)  	{ -		items.push_back(std::string("Paste As Link")); -		if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) -		{ -			disabled_items.push_back(std::string("Paste As Link")); -		} +		disabled_items.push_back(std::string("Paste As Link"));  	}  	items.push_back(std::string("Paste Separator")); @@ -678,7 +679,8 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		{  			disabled_items.push_back(std::string("Share"));  		} -		items.push_back(std::string("Open")); +		 +		addOpenRightClickMenuOption(items);  		items.push_back(std::string("Properties"));  		getClipboardEntries(true, items, disabled_items, flags); @@ -713,7 +715,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,  	const LLInventoryObject *obj = getInventoryObject();  	// Don't allow delete as a direct option from COF folder. -	if (obj && obj->getIsLinkType() && isCOFFolder()) +	if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID))  	{  		return;  	} @@ -734,6 +736,17 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,  	}  } +void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) +{ +	const LLInventoryObject *obj = getInventoryObject(); +	const BOOL is_link = (obj && obj->getIsLinkType()); + +	if (is_link) +		items.push_back(std::string("Open Original")); +	else +		items.push_back(std::string("Open")); +} +  // *TODO: remove this  BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const  { @@ -841,21 +854,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,  									 const LLUUID& new_parent_id,  									 BOOL restamp)  { -	if (item->getParentUUID() != new_parent_id) -	{ -		LLInventoryModel::update_list_t update; -		LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); -		update.push_back(old_folder); -		LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); -		update.push_back(new_folder); -		gInventory.accountForUpdate(update); - -		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); -		new_item->setParent(new_parent_id); -		new_item->updateParentOnServer(restamp); -		model->updateItem(new_item); -		model->notifyObservers(); -	} +	change_item_parent(model, item, new_parent_id, restamp);  }  // static @@ -1108,7 +1107,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		gotoItem();  	} -	if ("open" == action) +	if ("open" == action || "open_original" == action)  	{  		openItem();  		return; @@ -1454,17 +1453,11 @@ BOOL LLItemBridge::isItemCopyable() const  			return FALSE;  		} -		if (gAgent.isGodlike()) -		{ -			// All items can be copied in god mode since you can -			// at least paste-as-link the item, though you  -			// still may not be able paste the item. -			return TRUE; -		} -		else -		{ -			return (item->getPermissions().allowCopyBy(gAgent.getID())); -		} +		// All items can be copied in god mode since you can +		// at least paste-as-link the item, though you  +		// still may not be able paste the item. +		return TRUE; +		// return (item->getPermissions().allowCopyBy(gAgent.getID()));  	}  	return FALSE;  } @@ -1605,7 +1598,8 @@ BOOL LLFolderBridge::isUpToDate() const  BOOL LLFolderBridge::isItemCopyable() const  { -	return FALSE; +	// Can copy folders to paste-as-link, but not for straight paste. +	return TRUE;  }  BOOL LLFolderBridge::copyToClipboard() const @@ -1836,11 +1830,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  					else  					{  						LLPointer<LLInventoryCallback> cb = NULL; +						const std::string empty_description = "";  						link_inventory_item(  							gAgent.getID(),  							inv_cat->getUUID(),  							mUUID,  							inv_cat->getName(), +							empty_description,  							LLAssetType::AT_LINK_FOLDER,  							cb);  					} @@ -2512,30 +2508,29 @@ void LLFolderBridge::pasteLinkFromClipboard()  			 ++iter)  		{  			const LLUUID &object_id = (*iter); -#if SUPPORT_ENSEMBLES  			if (LLInventoryCategory *cat = model->getCategory(object_id))  			{ +				const std::string empty_description = "";  				link_inventory_item(  					gAgent.getID(),  					cat->getUUID(),  					parent_id,  					cat->getName(), +					empty_description,  					LLAssetType::AT_LINK_FOLDER,  					LLPointer<LLInventoryCallback>(NULL));  			} -			else -#endif -				if (LLInventoryItem *item = model->getItem(object_id)) -				{ -					link_inventory_item( -						gAgent.getID(), -						item->getLinkedUUID(), -						parent_id, -						item->getName(), -						item->getDescription(), -						LLAssetType::AT_LINK, -						LLPointer<LLInventoryCallback>(NULL)); -				} +			else if (LLInventoryItem *item = model->getItem(object_id)) +			{ +				link_inventory_item( +					gAgent.getID(), +					item->getLinkedUUID(), +					parent_id, +					item->getName(), +					item->getDescription(), +					LLAssetType::AT_LINK, +					LLPointer<LLInventoryCallback>(NULL)); +			}  		}  	}  } @@ -3346,7 +3341,7 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  			disabled_items.push_back(std::string("Share"));  		} -		items.push_back(std::string("Open")); +		addOpenRightClickMenuOption(items);  		items.push_back(std::string("Properties"));  		getClipboardEntries(true, items, disabled_items, flags); @@ -3712,7 +3707,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		{  			disabled_items.push_back(std::string("Share"));  		} -		items.push_back(std::string("Open")); +		addOpenRightClickMenuOption(items);  		items.push_back(std::string("Properties"));  		getClipboardEntries(true, items, disabled_items, flags); @@ -3992,7 +3987,7 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		if (!is_sidepanel)  		{ -			items.push_back(std::string("Open")); +			addOpenRightClickMenuOption(items);  			items.push_back(std::string("Properties"));  		} @@ -4730,7 +4725,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		if (can_open && !is_sidepanel)  		{ -			items.push_back(std::string("Open")); +			addOpenRightClickMenuOption(items);  		}  		if (!is_sidepanel) @@ -5250,9 +5245,13 @@ const LLUUID &LLLinkFolderBridge::getFolderID() const  // static  void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, -								   const LLUUID& uuid,LLInventoryModel* model) +								   const LLUUID& uuid, +								   LLInventoryModel* model)  { -	LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); +	// Perform indirection in case of link. +	const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid); + +	LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model);  	if(action)  	{  		action->doIt(); @@ -5365,7 +5364,8 @@ protected:  }; -class LLNotecardBridgeAction: public LLInvFVBridgeAction +class LLNotecardBridgeAction +: public LLInvFVBridgeAction  {  	friend class LLInvFVBridgeAction;  public: diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 6248de4bd1..d0f743f388 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -136,7 +136,7 @@ protected:  											menuentry_vec_t &disabled_items);  	virtual void addDeleteContextMenuOptions(menuentry_vec_t &items,  											 menuentry_vec_t &disabled_items); - +	virtual void addOpenRightClickMenuOption(menuentry_vec_t &items);  protected:  	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 1a488175ac..901a570487 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -329,9 +329,10 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)  		// appending new characters  		const BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString); -		mFilterSubString = string; +		mFilterSubStringOrig = string; +		LLStringUtil::trimHead(mFilterSubStringOrig); +		mFilterSubString = mFilterSubStringOrig;  		LLStringUtil::toUpper(mFilterSubString); -		LLStringUtil::trimHead(mFilterSubString);  		if (less_restrictive)  		{  			setModified(FILTER_LESS_RESTRICTIVE); diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index b01554edc8..2376ba5d22 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -84,6 +84,7 @@ public:  	void 				setFilterSubString(const std::string& string);  	const std::string& 	getFilterSubString(BOOL trim = FALSE) const; +	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; }   	BOOL 				hasFilterString() const;  	void 				setFilterPermissions(PermissionMask perms); @@ -181,6 +182,7 @@ private:  	std::string::size_type	mSubStringMatchOffset;  	std::string				mFilterSubString; +	std::string				mFilterSubStringOrig;  	const std::string		mName;  	S32						mFilterGeneration; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 449b1b5b4d..6c7251579d 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -585,3 +585,26 @@ BOOL get_is_item_worn(const LLUUID& id)  	}  	return FALSE;  } + + +void change_item_parent(LLInventoryModel* model, +									 LLViewerInventoryItem* item, +									 const LLUUID& new_parent_id, +									 BOOL restamp) +{ +	if (item->getParentUUID() != new_parent_id) +	{ +		LLInventoryModel::update_list_t update; +		LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); +		update.push_back(old_folder); +		LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); +		update.push_back(new_folder); +		gInventory.accountForUpdate(update); + +		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); +		new_item->setParent(new_parent_id); +		new_item->updateParentOnServer(restamp); +		model->updateItem(new_item); +		model->notifyObservers(); +	} +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index e3cd988e39..6f373f7392 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -310,6 +310,12 @@ LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,  // Is this item or its baseitem is worn, attached, etc...  BOOL get_is_item_worn(const LLUUID& id); + +void change_item_parent(LLInventoryModel* model, +									 LLViewerInventoryItem* item, +									 const LLUUID& new_parent_id, +									 BOOL restamp); +  #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index dca130c672..8dfdb0788a 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -50,76 +50,224 @@  ////////////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////////// -// static -LLPanelInventoryListItem* LLPanelInventoryListItem::createItemPanel(const LLViewerInventoryItem* item) +static const S32 WIDGET_SPACING = 3; + +LLPanelInventoryListItemBase* LLPanelInventoryListItemBase::create(LLViewerInventoryItem* item)  { +	LLPanelInventoryListItemBase* list_item = NULL;  	if (item)  	{ -		return new LLPanelInventoryListItem(item); +		list_item = new LLPanelInventoryListItemBase(item); +		list_item->init();  	} -	else +	return list_item; +} + +void LLPanelInventoryListItemBase::updateItem() +{ +	setIconImage(mIconImage); +	setTitle(mItem->getName(), mHighlightedText); +} + +void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/) +{ +	LLUICtrl* ctrl = findChild<LLUICtrl>(name); +	if(ctrl)  	{ -		return NULL; +		addWidgetToLeftSide(ctrl, show_widget);  	}  } -LLPanelInventoryListItem::~LLPanelInventoryListItem() -{} +void LLPanelInventoryListItemBase::addWidgetToLeftSide(LLUICtrl* ctrl, bool show_widget/* = true*/) +{ +	mLeftSideWidgets.push_back(ctrl); +	setShowWidget(ctrl, show_widget); +} + +void LLPanelInventoryListItemBase::addWidgetToRightSide(const std::string& name, bool show_widget/* = true*/) +{ +	LLUICtrl* ctrl = findChild<LLUICtrl>(name); +	if(ctrl) +	{ +		addWidgetToRightSide(ctrl, show_widget); +	} +} + +void LLPanelInventoryListItemBase::addWidgetToRightSide(LLUICtrl* ctrl, bool show_widget/* = true*/) +{ +	mRightSideWidgets.push_back(ctrl); +	setShowWidget(ctrl, show_widget); +} + +void LLPanelInventoryListItemBase::setShowWidget(const std::string& name, bool show) +{ +	LLUICtrl* widget = findChild<LLUICtrl>(name); +	if(widget) +	{ +		setShowWidget(widget, show); +	} +} + +void LLPanelInventoryListItemBase::setShowWidget(LLUICtrl* ctrl, bool show) +{ +	// Enable state determines whether widget may become visible in setWidgetsVisible() +	ctrl->setEnabled(show); +} -//virtual -BOOL LLPanelInventoryListItem::postBuild() +BOOL LLPanelInventoryListItemBase::postBuild()  { -	mIcon = getChild<LLIconCtrl>("item_icon"); -	mTitle = getChild<LLTextBox>("item_name"); +	setIconCtrl(getChild<LLIconCtrl>("item_icon")); +	setTitleCtrl(getChild<LLTextBox>("item_name")); + +	mIconImage = get_item_icon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE);  	updateItem(); +	setWidgetsVisible(false); +	reshapeWidgets(); +  	return TRUE;  } -//virtual -void LLPanelInventoryListItem::setValue(const LLSD& value) +void LLPanelInventoryListItemBase::setValue(const LLSD& value)  {  	if (!value.isMap()) return;  	if (!value.has("selected")) return;  	childSetVisible("selected_icon", value["selected"]);  } -void LLPanelInventoryListItem::updateItem() +void LLPanelInventoryListItemBase::onMouseEnter(S32 x, S32 y, MASK mask)  { -	if (mItemIcon.notNull()) -		mIcon->setImage(mItemIcon); +	childSetVisible("hovered_icon", true); +	LLPanel::onMouseEnter(x, y, mask); +} +void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	childSetVisible("hovered_icon", false); +	LLPanel::onMouseLeave(x, y, mask); +} + +LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem* item) +: LLPanel() +, mItem(item) +, mIconCtrl(NULL) +, mTitleCtrl(NULL) +, mWidgetSpacing(WIDGET_SPACING) +, mLeftWidgetsWidth(0) +, mRightWidgetsWidth(0) +{ +} + +void LLPanelInventoryListItemBase::init() +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory_item.xml"); +} + +class WidgetVisibilityChanger +{ +public: +	WidgetVisibilityChanger(bool visible) : mVisible(visible){} +	void operator()(LLUICtrl* widget) +	{ +		// Disabled widgets never become visible. see LLPanelInventoryListItemBase::setShowWidget() +		widget->setVisible(mVisible && widget->getEnabled()); +	} +private: +	bool mVisible; +}; + +void LLPanelInventoryListItemBase::setWidgetsVisible(bool visible) +{ +	std::for_each(mLeftSideWidgets.begin(), mLeftSideWidgets.end(), WidgetVisibilityChanger(visible)); +	std::for_each(mRightSideWidgets.begin(), mRightSideWidgets.end(), WidgetVisibilityChanger(visible)); +} + +void LLPanelInventoryListItemBase::reshapeWidgets() +{ +	// disabled reshape left for now to reserve space for 'delete' button in LLPanelClothingListItem +	/*reshapeLeftWidgets();*/ +	reshapeRightWidgets(); +	reshapeMiddleWidgets(); +} + +void LLPanelInventoryListItemBase::setIconImage(const LLUIImagePtr& image) +{ +	if(image) +	{ +		mIconImage = image;  +		mIconCtrl->setImage(mIconImage); +	} +} + +void LLPanelInventoryListItemBase::setTitle(const std::string& title, const std::string& highlit_text) +{  	LLTextUtil::textboxSetHighlightedVal( -		mTitle, +		mTitleCtrl,  		LLStyle::Params(), -		mItemName, -		mHighlightedText); +		title, +		highlit_text);  } -void LLPanelInventoryListItem::onMouseEnter(S32 x, S32 y, MASK mask) +void LLPanelInventoryListItemBase::reshapeLeftWidgets()  { -	childSetVisible("hovered_icon", true); +	S32 widget_left = 0; +	mLeftWidgetsWidth = 0; -	LLPanel::onMouseEnter(x, y, mask); +	widget_array_t::const_iterator it = mLeftSideWidgets.begin(); +	const widget_array_t::const_iterator it_end = mLeftSideWidgets.end(); +	for( ; it_end != it; ++it) +	{ +		LLUICtrl* widget = *it; +		if(!widget->getVisible()) +		{ +			continue; +		} +		LLRect widget_rect(widget->getRect()); +		widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight()); +		widget->setShape(widget_rect); + +		widget_left += widget_rect.getWidth() + getWidgetSpacing(); +		mLeftWidgetsWidth = widget_rect.mRight; +	}  } -void LLPanelInventoryListItem::onMouseLeave(S32 x, S32 y, MASK mask) +void LLPanelInventoryListItemBase::reshapeRightWidgets()  { -	childSetVisible("hovered_icon", false); +	S32 widget_right = getLocalRect().getWidth(); +	S32 widget_left = widget_right; -	LLPanel::onMouseLeave(x, y, mask); +	widget_array_t::const_reverse_iterator it = mRightSideWidgets.rbegin(); +	const widget_array_t::const_reverse_iterator it_end = mRightSideWidgets.rend(); +	for( ; it_end != it; ++it) +	{ +		LLUICtrl* widget = *it; +		if(!widget->getVisible()) +		{ +			continue; +		} +		LLRect widget_rect(widget->getRect()); +		widget_left = widget_right - widget_rect.getWidth(); +		widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight()); +		widget->setShape(widget_rect); + +		widget_right = widget_left - getWidgetSpacing(); +	} +	mRightWidgetsWidth = getLocalRect().getWidth() - widget_left;  } -LLPanelInventoryListItem::LLPanelInventoryListItem(const LLViewerInventoryItem* item) -:	 LLPanel() -	,mIcon(NULL) -	,mTitle(NULL) +void LLPanelInventoryListItemBase::reshapeMiddleWidgets()  { -	mItemName = item->getName(); -	mItemIcon = get_item_icon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE); - -	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory_item.xml"); +	LLRect icon_rect(mIconCtrl->getRect()); +	icon_rect.setLeftTopAndSize(mLeftWidgetsWidth + getWidgetSpacing(), icon_rect.mTop,  +		icon_rect.getWidth(), icon_rect.getHeight()); +	mIconCtrl->setShape(icon_rect); + +	S32 name_left = icon_rect.mRight + getWidgetSpacing(); +	S32 name_right = getLocalRect().getWidth() - mRightWidgetsWidth - getWidgetSpacing(); +	LLRect name_rect(mTitleCtrl->getRect()); +	name_rect.set(name_left, name_rect.mTop, name_right, name_rect.mBottom); +	mTitleCtrl->setShape(name_rect);  }  //////////////////////////////////////////////////////////////////////////////// @@ -220,17 +368,18 @@ void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item)  	if (!item)  	{  		llwarns << "No inventory item. Couldn't create flat list item." << llendl; -		llassert(!"No inventory item. Couldn't create flat list item."); +		llassert(item != NULL);  	} -	LLPanelInventoryListItem *list_item = LLPanelInventoryListItem::createItemPanel(item); +	LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item);  	if (!list_item)  		return; -	if (!addItem(list_item, item->getUUID())) +	bool is_item_added = addItem(list_item, item->getUUID()); +	if (!is_item_added)  	{  		llwarns << "Couldn't add flat list item." << llendl; -		llassert(!"Couldn't add flat list item."); +		llassert(is_item_added);  	}  } diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index b496f4b9e9..152aafbd7e 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -47,33 +47,141 @@ class LLIconCtrl;  class LLTextBox;  class LLViewerInventoryItem; -class LLPanelInventoryListItem : public LLPanel +/** + * @class LLPanelInventoryListItemBase + * + * Base class for Inventory flat list item. Panel consists of inventory icon + * and inventory item name. + * This class is able to display widgets(buttons) on left(before icon) and right(after text-box) sides  + * of panel. + * + * How to use (see LLPanelClothingListItem for example): + * - implement init() to build panel from xml + * - create new xml file, fill it with widgets you want to dynamically show/hide/reshape on left/right sides + * - redefine postBuild()(call base implementation) and add needed widgets to needed sides, + * + */ +class LLPanelInventoryListItemBase : public LLPanel  {  public: -	static LLPanelInventoryListItem* createItemPanel(const LLViewerInventoryItem* item); -	virtual ~LLPanelInventoryListItem(); +	static LLPanelInventoryListItemBase* create(LLViewerInventoryItem* item); +	/** +	 * Called after inventory item was updated, update panel widgets to reflect inventory changes. +	 */ +	virtual void updateItem(); + +	/** +	 * Add widget to left side +	 */ +	void addWidgetToLeftSide(const std::string& name, bool show_widget = true); +	void addWidgetToLeftSide(LLUICtrl* ctrl, bool show_widget = true); + +	/** +	 * Add widget to right side, widget is supposed to be child of calling panel +	 */ +	void addWidgetToRightSide(const std::string& name, bool show_widget = true); +	void addWidgetToRightSide(LLUICtrl* ctrl, bool show_widget = true); + +	/** +	 * Mark widgets as visible. Only visible widgets take part in reshaping children +	 */ +	void setShowWidget(const std::string& name, bool show); +	void setShowWidget(LLUICtrl* ctrl, bool show); + +	/** +	 * Set spacing between widgets during reshape +	 */ +	void setWidgetSpacing(S32 spacing) { mWidgetSpacing = spacing; } + +	S32 getWidgetSpacing() { return mWidgetSpacing; } + +	/** +	 * Inheritors need to call base implementation of postBuild() +	 */  	/*virtual*/ BOOL postBuild(); + +	/** +	 * Handles item selection +	 */  	/*virtual*/ void setValue(const LLSD& value); -	void updateItem(); +	 /* Highlights item */ +	/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); +	/* Removes item highlight */ +	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); -	void onMouseEnter(S32 x, S32 y, MASK mask); -	void onMouseLeave(S32 x, S32 y, MASK mask); +	virtual ~LLPanelInventoryListItemBase(){}  protected: -	LLPanelInventoryListItem(const LLViewerInventoryItem* item); + +	LLPanelInventoryListItemBase(LLViewerInventoryItem* item); + +	typedef std::vector<LLUICtrl*> widget_array_t; + +	/** +	 * Use it from a factory function to build panel, do not build panel in constructor +	 */ +	virtual void init(); + +	/** setter for mIconCtrl */ +	void setIconCtrl(LLIconCtrl* icon) { mIconCtrl = icon; } +	/** setter for MTitleCtrl */ +	void setTitleCtrl(LLTextBox* tb) { mTitleCtrl = tb; } + +	void setLeftWidgetsWidth(S32 width) { mLeftWidgetsWidth = width; } +	void setRightWidgetsWidth(S32 width) { mRightWidgetsWidth = width; } + +	/** +	 * Set all widgets from both side visible/invisible. Only enabled widgets +	 * (see setShowWidget()) can become visible +	 */ +	virtual void setWidgetsVisible(bool visible); + +	/** +	 * Reshape all child widgets - icon, text-box and side widgets +	 */ +	virtual void reshapeWidgets(); + +	/** set wearable type icon image */ +	void setIconImage(const LLUIImagePtr& image); + +	/** Set item title - inventory item name usually */ +	void setTitle(const std::string& title, const std::string& highlit_text);  private: -	LLIconCtrl*		mIcon; -	LLTextBox*		mTitle; -	LLUIImagePtr	mItemIcon; -	std::string		mItemName; +	/** reshape left side widgets +	 * Deprecated for now. Disabled reshape left for now to reserve space for 'delete'  +	 * button in LLPanelClothingListItem according to Neal's comment (https://codereview.productengine.com/secondlife/r/325/) +	 */ +	void reshapeLeftWidgets(); + +	/** reshape right side widgets */ +	void reshapeRightWidgets(); + +	/** reshape remaining widgets */ +	void reshapeMiddleWidgets(); + +	LLViewerInventoryItem* mItem; + +	LLIconCtrl*		mIconCtrl; +	LLTextBox*		mTitleCtrl; + +	LLUIImagePtr	mIconImage;  	std::string		mHighlightedText; + +	widget_array_t	mLeftSideWidgets; +	widget_array_t	mRightSideWidgets; +	S32				mWidgetSpacing; + +	S32				mLeftWidgetsWidth; +	S32				mRightWidgetsWidth;  }; +////////////////////////////////////////////////////////////////////////// +  class LLInventoryItemsList : public LLFlatListView  {  public: @@ -117,7 +225,7 @@ protected:  	/**  	 * Add an item to the list  	 */ -	void addNewItem(LLViewerInventoryItem* item); +	virtual void addNewItem(LLViewerInventoryItem* item);  private:  	uuid_vec_t mIDs; // IDs of items that were added in refreshList(). diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 214b5d317a..86147d65e6 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -215,7 +215,7 @@ void LLInventoryFetchItemsObserver::changed(U32 mask)  void fetch_items_from_llsd(const LLSD& items_llsd)  { -	if (!items_llsd.size()) return; +	if (!items_llsd.size() || gDisconnected) return;  	LLSD body;  	body[0]["cap_name"] = "FetchInventory";  	body[1]["cap_name"] = "FetchLib"; @@ -235,6 +235,11 @@ void fetch_items_from_llsd(const LLSD& items_llsd)  	for (S32 i=0; i<body.size(); i++)  	{ +		if(!gAgent.getRegion()) +		{ +			llwarns<<"Agent's region is null"<<llendl; +			break; +		}  		if (0 >= body[i].size()) continue;  		std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); @@ -664,36 +669,87 @@ void LLInventoryCategoriesObserver::changed(U32 mask)  		if (!category)  			continue; -		S32 version = category->getVersion(); -		if (version != (*iter).second.mVersion) +		const S32 version = category->getVersion(); +		const S32 expected_num_descendents = category->getDescendentCount(); +		if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) || +			(expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN))  		{ -			// Update category version in map. -			(*iter).second.mVersion = version; -			(*iter).second.mCallback(); +			continue; +		} + +		// Check number of known descendents to find out whether it has changed. +		LLInventoryModel::cat_array_t* cats; +		LLInventoryModel::item_array_t* items; +		gInventory.getDirectDescendentsOf((*iter).first, cats, items); +		if (!cats || !items) +		{ +			llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl; +			// NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean +			// that the cat just doesn't have any items or subfolders). +			// Unrecoverable, so just skip this category. + +			llassert(cats != NULL && items != NULL); +		} +		const S32 current_num_known_descendents = cats->count() + items->count(); + +		LLCategoryData cat_data = (*iter).second; + +		// If category version or descendents count has changed +		// update category data in mCategoryMap and fire a callback. +		if (version != cat_data.mVersion || current_num_known_descendents != cat_data.mDescendentsCount) +		{ +			cat_data.mVersion = version; +			cat_data.mDescendentsCount = current_num_known_descendents; + +			cat_data.mCallback();  		}  	}  } -void LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb) +bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb)  {  	S32 version; +	S32 current_num_known_descendents; +	bool can_be_added = true; +  	LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);  	if (category)  	{  		// Inventory category version is used to find out if some changes  		// to a category have been made.  		version = category->getVersion(); + +		LLInventoryModel::cat_array_t* cats; +		LLInventoryModel::item_array_t* items; +		gInventory.getDirectDescendentsOf(cat_id, cats, items); +		if (!cats || !items) +		{ +			llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl; +			// NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean +			// that the cat just doesn't have any items or subfolders). +			// Unrecoverable, so just return "false" meaning that the category can't be observed. +			can_be_added = false; + +			llassert(cats != NULL && items != NULL); +		} +		current_num_known_descendents = cats->count() + items->count();  	}  	else  	{  		// If category could not be retrieved it might mean that  		// inventory is unusable at the moment so the category is -		// stored with VERSION_UNKNOWN and it may be updated later. +		// stored with VERSION_UNKNOWN and DESCENDENT_COUNT_UNKNOWN, +		// it may be updated later.  		version = LLViewerInventoryCategory::VERSION_UNKNOWN; +		current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN; +	} + +	if (can_be_added) +	{ +		mCategoryMap.insert(category_map_value_t(cat_id, LLCategoryData(cb, version, current_num_known_descendents)));  	} -	version = category->getVersion(); -	mCategoryMap.insert(category_map_value_t(cat_id, LLCategoryData(cb, version))); +	return can_be_added;  }  void LLInventoryCategoriesObserver::removeCategory(const LLUUID& cat_id) diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index e63b67d2ad..036e6ca40d 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -276,19 +276,28 @@ public:  	LLInventoryCategoriesObserver() {};  	virtual void changed(U32 mask); -	void addCategory(const LLUUID& cat_id, callback_t cb); +	/** +	 * Add cat_id to the list of observed categories with a +	 * callback fired on category being changed. +	 * +	 * @return "true" if category was added, "false" if it could +	 * not be found. +	 */ +	bool addCategory(const LLUUID& cat_id, callback_t cb);  	void removeCategory(const LLUUID& cat_id);  protected:  	struct LLCategoryData  	{ -		LLCategoryData(callback_t cb, S32 version) +		LLCategoryData(callback_t cb, S32 version, S32 num_descendents)  		: mCallback(cb)  		, mVersion(version) +		, mDescendentsCount(num_descendents)  		{}  		callback_t	mCallback;  		S32			mVersion; +		S32			mDescendentsCount;  	};  	typedef	std::map<LLUUID, LLCategoryData>	category_map_t; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 1215272685..b103ec45d0 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -41,6 +41,7 @@  #include "llaccordionctrl.h"  #include "llaccordionctrltab.h" +#include "llappearancemgr.h"  #include "llinventoryfunctions.h"  #include "llinventorymodel.h"  #include "llwearableitemslist.h" @@ -51,6 +52,7 @@ LLOutfitsList::LLOutfitsList()  	:	LLPanel()  	,	mAccordion(NULL)  	,	mListCommands(NULL) +	,	mSelectedList(NULL)  {  	mCategoriesObserver = new LLInventoryCategoriesObserver();  	gInventory.addObserver(mCategoriesObserver); @@ -135,30 +137,37 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)  	{  		const LLUUID cat_id = (*iter);  		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); -		if (!cat) -			continue; +		if (!cat) continue;  		std::string name = cat->getName();  		static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode(); - -		accordionXmlNode->setAttributeString("name", name); -		accordionXmlNode->setAttributeString("title", name);  		LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder<LLAccordionCtrlTab>(accordionXmlNode, NULL, NULL); +		tab->setName(name); +		tab->setTitle(name); +  		// *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.  		tab->setDisplayChildren(false);  		mAccordion->addCollapsibleCtrl(tab); +		// Start observing the new outfit category. +		LLWearableItemsList* list  = tab->getChild<LLWearableItemsList>("wearable_items_list"); +		if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) +		{ +			// Remove accordion tab if category could not be added to observer. +			mAccordion->removeCollapsibleCtrl(tab); +			continue; +		} +  		// Map the new tab with outfit category UUID.  		mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); -		// Start observing the new outfit category. -		LLWearableItemsList* list  = tab->getChild<LLWearableItemsList>("wearable_items_list"); -		mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)); +		// Setting tab focus callback to monitor currently selected outfit. +		tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id)); -		// Setting drop down callback to monitor currently selected outfit. -		tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::onTabExpandedCollapsed, this, list)); +		// Setting list commit callback to monitor currently selected wearable item. +		list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1));  		// Fetch the new outfit contents.  		cat->fetch(); @@ -178,10 +187,18 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)  			// 1. Remove outfit accordion tab from accordion.  			mAccordion->removeCollapsibleCtrl(outfits_iter->second); +			const LLUUID& outfit_id = outfits_iter->first; +  			// 2. Remove outfit category from observer to stop monitoring its changes. -			mCategoriesObserver->removeCategory(outfits_iter->first); +			mCategoriesObserver->removeCategory(outfit_id); -			// 3. Remove category UUID to accordion tab mapping. +			// 3. Reset selection if selected outfit is being removed. +			if (mSelectedOutfitUUID == outfit_id) +			{ +				changeOutfitSelection(NULL, LLUUID()); +			} + +			// 4. Remove category UUID to accordion tab mapping.  			mOutfitsMap.erase(outfits_iter);  		}  	} @@ -199,40 +216,30 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)  	mAccordion->arrange();  } -void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) +void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)  { -	outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id); -	if (outfits_iter != mOutfitsMap.end()) -	{ -		LLViewerInventoryCategory *cat = gInventory.getCategory(category_id); -		if (!cat) -			return; +	LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl); +	if (!list) return; -		std::string name = cat->getName(); +	LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID()); +	if (!item) return; -		// Update tab name with the new category name. -		LLAccordionCtrlTab* tab = outfits_iter->second; -		if (tab) -		{ -			tab->setName(name); -		} - -		// Update tab title with the new category name using textbox -		// in accordion tab header. -		LLTextBox* tab_title = tab->findChild<LLTextBox>("dd_textbox"); -		if (tab_title) -		{ -			tab_title->setText(name); -		} -	} +	changeOutfitSelection(list, item->getParentUUID());  } -void LLOutfitsList::onTabExpandedCollapsed(LLWearableItemsList* list) +void LLOutfitsList::performAction(std::string action)  { -	if (!list) -		return; +	LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedOutfitUUID); +	if (!cat) return; -	// TODO: Add outfit selection handling. +	if ("replaceoutfit" == action) +	{ +		LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, FALSE ); +	} +	else if ("addtooutfit" == action) +	{ +		LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, TRUE ); +	}  }  void LLOutfitsList::setFilterSubString(const std::string& string) @@ -240,7 +247,6 @@ void LLOutfitsList::setFilterSubString(const std::string& string)  	mFilterSubString = string;  } -  //////////////////////////////////////////////////////////////////////////  // Private methods  ////////////////////////////////////////////////////////////////////////// @@ -283,4 +289,37 @@ void LLOutfitsList::computeDifference(  	LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);  } +void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) +{ +	outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id); +	if (outfits_iter != mOutfitsMap.end()) +	{ +		LLViewerInventoryCategory *cat = gInventory.getCategory(category_id); +		if (!cat) return; + +		std::string name = cat->getName(); + +		// Update tab name with the new category name. +		LLAccordionCtrlTab* tab = outfits_iter->second; +		if (tab) +		{ +			tab->setName(name); +			tab->setTitle(name); +		} +	} +} + +void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +{ +	// Reset selection in previously selected tab +	// if a new one is selected. +	if (list && mSelectedList && mSelectedList != list) +	{ +		mSelectedList->resetSelection(); +	} + +	mSelectedList = list; +	mSelectedOutfitUUID = category_id; +} +  // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 2d103ea356..d86cf5a703 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -65,10 +65,9 @@ public:  	void refreshList(const LLUUID& category_id); -	// Update tab displaying outfit identified by category_id. -	void updateOutfitTab(const LLUUID& category_id); +	void onSelectionChange(LLUICtrl* ctrl); -	void onTabExpandedCollapsed(LLWearableItemsList* list); +	void performAction(std::string action);  	void setFilterSubString(const std::string& string); @@ -85,12 +84,24 @@ private:  	 */  	void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); +	/** +	 * Updates tab displaying outfit identified by category_id. +	 */ +	void updateOutfitTab(const LLUUID& category_id); + +	/** +	 * Resets previous selection and stores newly selected list and outfit id. +	 */ +	void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);  	LLInventoryCategoriesObserver* 	mCategoriesObserver;  	LLAccordionCtrl*				mAccordion;  	LLPanel*						mListCommands; +	LLWearableItemsList*			mSelectedList; +	LLUUID							mSelectedOutfitUUID; +  	std::string 					mFilterSubString;  	typedef	std::map<LLUUID, LLAccordionCtrlTab*>		outfits_map_t; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index da74295f9e..3c112b8b5e 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -51,6 +51,12 @@  #include "llagentwearables.h"  #include "llscrollingpanelparam.h" +#include "llcolorswatch.h" +#include "lltexturectrl.h" +#include "lltextureentry.h" +#include "llviewercontrol.h"	// gSavedSettings +#include "llviewertexturelist.h" +  // register panel with appropriate XML  static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable"); @@ -88,6 +94,8 @@ enum ESubpart {  	SUBPART_TATTOO   }; +using namespace LLVOAvatarDefines; +  typedef std::vector<ESubpart> subpart_vec_t;  // Locally defined classes @@ -110,14 +118,17 @@ public:  		WearableEntry(EWearableType type,  					  const std::string &title,  					  const std::string &desc_title, -					  U8 num_subparts, ... ); // number of subparts followed by a list of ESubparts +					  U8 num_color_swatches,  // number of 'color_swatches' +					  U8 num_texture_pickers, // number of 'texture_pickers' +					  U8 num_subparts, ... ); // number of subparts followed by a list of ETextureIndex and ESubparts  		const EWearableType mWearableType;  		const std::string   mTitle;  		const std::string	mDescTitle;  		subpart_vec_t		mSubparts; - +		texture_vec_t		mColorSwatchCtrls; +		texture_vec_t		mTextureCtrls;  	};  	struct Wearables : public LLDictionary<EWearableType, WearableEntry> @@ -158,6 +169,35 @@ public:  	} mSubparts;  	const SubpartEntry*  getSubpart(ESubpart subpart) const { return mSubparts.lookup(subpart); } + +	//-------------------------------------------------------------------- +	// Picker Control Entries +	//-------------------------------------------------------------------- +public: +	struct PickerControlEntry : public LLDictionaryEntry +	{ +		PickerControlEntry(ETextureIndex tex_index, +						   const std::string name, +						   const LLUUID default_image_id = LLUUID::null, +						   const bool allow_no_texture = false); +		ETextureIndex		mTextureIndex; +		const std::string	mControlName; +		const LLUUID		mDefaultImageId; +		const bool			mAllowNoTexture; +	}; + +	struct ColorSwatchCtrls : public LLDictionary<ETextureIndex, PickerControlEntry> +	{ +		ColorSwatchCtrls(); +	} mColorSwatchCtrls; + +	struct TextureCtrls : public LLDictionary<ETextureIndex, PickerControlEntry> +	{ +		TextureCtrls(); +	} mTextureCtrls; + +	const PickerControlEntry* getTexturePicker(ETextureIndex index) const { return mTextureCtrls.lookup(index); } +	const PickerControlEntry* getColorSwatch(ETextureIndex index) const { return mColorSwatchCtrls.lookup(index); }  };  LLEditWearableDictionary::LLEditWearableDictionary() @@ -172,26 +212,28 @@ LLEditWearableDictionary::~LLEditWearableDictionary()  LLEditWearableDictionary::Wearables::Wearables()  { -	addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",9,	SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE)); -	addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",4, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL)); -	addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",4, SUBPART_HAIR_COLOR,	SUBPART_HAIR_STYLE,	SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL)); -	addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",1, SUBPART_EYES)); -	addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1, SUBPART_SHIRT)); -	addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1, SUBPART_PANTS)); -	addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1, SUBPART_SHOES)); -	addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1, SUBPART_SOCKS)); -	addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1, SUBPART_JACKET)); -	addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1, SUBPART_GLOVES)); -	addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1, SUBPART_UNDERSHIRT)); -	addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1, SUBPART_UNDERPANTS)); -	addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1, SUBPART_SKIRT)); -	addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",1, SUBPART_ALPHA)); -	addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1, SUBPART_TATTOO)); +	addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9,	SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE)); +	addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",0,3,4, TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL)); +	addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",0,1,4, TEX_HAIR, SUBPART_HAIR_COLOR,	SUBPART_HAIR_STYLE,	SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL)); +	addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",0,1,1, TEX_EYES_IRIS, SUBPART_EYES)); +	addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1,1,1, TEX_UPPER_SHIRT, TEX_UPPER_SHIRT, SUBPART_SHIRT)); +	addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1,1,1, TEX_LOWER_PANTS, TEX_LOWER_PANTS, SUBPART_PANTS)); +	addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1,1,1, TEX_LOWER_SHOES, TEX_LOWER_SHOES, SUBPART_SHOES)); +	addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1,1,1, TEX_LOWER_SOCKS, TEX_LOWER_SOCKS, SUBPART_SOCKS)); +	addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1,2,1, TEX_UPPER_JACKET, TEX_UPPER_JACKET, TEX_LOWER_JACKET, SUBPART_JACKET)); +	addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1,1,1, TEX_UPPER_GLOVES, TEX_UPPER_GLOVES, SUBPART_GLOVES)); +	addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1,1,1, TEX_UPPER_UNDERSHIRT, TEX_UPPER_UNDERSHIRT, SUBPART_UNDERSHIRT)); +	addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1,1,1, TEX_LOWER_UNDERPANTS, TEX_LOWER_UNDERPANTS, SUBPART_UNDERPANTS)); +	addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT)); +	addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA)); +	addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",0,3,1, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO));  }  LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type,  					  const std::string &title,  					  const std::string &desc_title, +					  U8 num_color_swatches, +					  U8 num_texture_pickers,  					  U8 num_subparts, ... ) :  	LLDictionaryEntry(title),  	mWearableType(type), @@ -201,6 +243,18 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type,  	va_list argp;  	va_start(argp, num_subparts); +	for (U8 i = 0; i < num_color_swatches; ++i) +	{ +		ETextureIndex index = (ETextureIndex)va_arg(argp,int); +		mColorSwatchCtrls.push_back(index); +	} + +	for (U8 i = 0; i < num_texture_pickers; ++i) +	{ +		ETextureIndex index = (ETextureIndex)va_arg(argp,int); +		mTextureCtrls.push_back(index); +	} +  	for (U8 i = 0; i < num_subparts; ++i)  	{  		ESubpart part = (ESubpart)va_arg(argp,int); @@ -265,6 +319,268 @@ LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,  {  } +LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls() +{ +	addEntry ( TEX_UPPER_SHIRT,  new PickerControlEntry (TEX_UPPER_SHIRT, "Color/Tint" )); +	addEntry ( TEX_LOWER_PANTS,  new PickerControlEntry (TEX_LOWER_PANTS, "Color/Tint" )); +	addEntry ( TEX_LOWER_SHOES,  new PickerControlEntry (TEX_LOWER_SHOES, "Color/Tint" )); +	addEntry ( TEX_LOWER_SOCKS,  new PickerControlEntry (TEX_LOWER_SOCKS, "Color/Tint" )); +	addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Color/Tint" )); +	addEntry ( TEX_SKIRT,  new PickerControlEntry (TEX_SKIRT, "Color/Tint" )); +	addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Color/Tint" )); +	addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" )); +	addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" )); +} + +LLEditWearableDictionary::TextureCtrls::TextureCtrls() +{ +	addEntry ( TEX_HEAD_BODYPAINT,  new PickerControlEntry (TEX_HEAD_BODYPAINT,  "Head Tattoos", LLUUID::null, TRUE )); +	addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Tattoos", LLUUID::null, TRUE )); +	addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Tattoos", LLUUID::null, TRUE )); +	addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE )); +	addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE )); +	addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ), FALSE )); +	addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Upper Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_JACKET, new PickerControlEntry (TEX_LOWER_JACKET, "Lower Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); +	addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ), FALSE )); +	addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ), FALSE )); +	addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); +	addEntry ( TEX_LOWER_ALPHA, new PickerControlEntry (TEX_LOWER_ALPHA, "Lower Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); +	addEntry ( TEX_UPPER_ALPHA, new PickerControlEntry (TEX_UPPER_ALPHA, "Upper Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); +	addEntry ( TEX_HEAD_ALPHA, new PickerControlEntry (TEX_HEAD_ALPHA, "Head Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); +	addEntry ( TEX_EYES_ALPHA, new PickerControlEntry (TEX_EYES_ALPHA, "Eye Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); +	addEntry ( TEX_HAIR_ALPHA, new PickerControlEntry (TEX_HAIR_ALPHA, "Hair Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); +	addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE )); +	addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE )); +	addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE )); +} + +LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index, +					 const std::string name, +					 const LLUUID default_image_id, +					 const bool allow_no_texture) : +	LLDictionaryEntry(name), +	mTextureIndex(tex_index), +	mControlName(name), +	mDefaultImageId(default_image_id), +	mAllowNoTexture(allow_no_texture) +{ +} + +// Helper functions. +static const texture_vec_t null_texture_vec; + +// Specializations of this template function return a vector of texture indexes of particular control type +// (i.e. LLColorSwatchCtrl or LLTextureCtrl) which are contained in given WearableEntry. +template <typename T> +const texture_vec_t& +get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entry) { return null_texture_vec; } + +// Specializations of this template function return picker control entry for particular control type. +template <typename T> +const LLEditWearableDictionary::PickerControlEntry* +get_picker_entry (const ETextureIndex index) { return NULL; } + +typedef boost::function<void(LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry*)> function_t; + +typedef struct PickerControlEntryNamePredicate +{ +	PickerControlEntryNamePredicate(const std::string name) : mName (name) {}; +	bool operator()(const LLEditWearableDictionary::PickerControlEntry* entry) const +	{ +		return (entry && entry->mName == mName); +	} +private: +	const std::string mName; +} PickerControlEntryNamePredicate; + +// A full specialization of get_pickers_indexes for LLColorSwatchCtrl +template <> +const texture_vec_t& +get_pickers_indexes<LLColorSwatchCtrl> (const LLEditWearableDictionary::WearableEntry *wearable_entry) +{ +	if (!wearable_entry) +	{ +		llwarns << "could not get LLColorSwatchCtrl indexes for null wearable entry." << llendl; +		return null_texture_vec; +	} +	return wearable_entry->mColorSwatchCtrls; +} + +// A full specialization of get_pickers_indexes for LLTextureCtrl +template <> +const texture_vec_t& +get_pickers_indexes<LLTextureCtrl> (const LLEditWearableDictionary::WearableEntry *wearable_entry) +{ +	if (!wearable_entry) +	{ +		llwarns << "could not get LLTextureCtrl indexes for null wearable entry." << llendl; +		return null_texture_vec; +	} +	return wearable_entry->mTextureCtrls; +} + +// A full specialization of get_picker_entry for LLColorSwatchCtrl +template <> +const LLEditWearableDictionary::PickerControlEntry* +get_picker_entry<LLColorSwatchCtrl> (const ETextureIndex index) +{ +	return LLEditWearableDictionary::getInstance()->getColorSwatch(index); +} + +// A full specialization of get_picker_entry for LLTextureCtrl +template <> +const LLEditWearableDictionary::PickerControlEntry* +get_picker_entry<LLTextureCtrl> (const ETextureIndex index) +{ +	return LLEditWearableDictionary::getInstance()->getTexturePicker(index); +} + +template <typename CtrlType, class Predicate> +const LLEditWearableDictionary::PickerControlEntry* +find_picker_ctrl_entry_if(EWearableType type, const Predicate pred) +{ +	const LLEditWearableDictionary::WearableEntry *wearable_entry +		= LLEditWearableDictionary::getInstance()->getWearable(type); +	if (!wearable_entry) +	{ +		llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl; +		return NULL; +	} +	const texture_vec_t& indexes = get_pickers_indexes<CtrlType>(wearable_entry); +	for (texture_vec_t::const_iterator +			 iter = indexes.begin(), +			 iter_end = indexes.end(); +		 iter != iter_end; ++iter) +	{ +		const ETextureIndex te = *iter; +		const LLEditWearableDictionary::PickerControlEntry*	entry +			= get_picker_entry<CtrlType>(te); +		if (!entry) +		{ +			llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl; +			continue; +		} +		if (pred(entry)) +		{ +			return entry; +		} +	} +	return NULL; +} + +template <typename CtrlType> +void +for_each_picker_ctrl_entry(LLPanel* panel, EWearableType type, function_t fun) +{ +	if (!panel) +	{ +		llwarns << "the panel wasn't passed for wearable of type: " << type << llendl; +		return; +	} +	const LLEditWearableDictionary::WearableEntry *wearable_entry +		= LLEditWearableDictionary::getInstance()->getWearable(type); +	if (!wearable_entry) +	{ +		llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl; +		return; +	} +	const texture_vec_t& indexes = get_pickers_indexes<CtrlType>(wearable_entry); +	for (texture_vec_t::const_iterator +			 iter = indexes.begin(), +			 iter_end = indexes.end(); +		 iter != iter_end; ++iter) +	{ +		const ETextureIndex te = *iter; +		const LLEditWearableDictionary::PickerControlEntry*	entry +			= get_picker_entry<CtrlType>(te); +		if (!entry) +		{ +			llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl; +			continue; +		} +		fun (panel, entry); +	} +} + +// The helper functions for pickers management +static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName); +	if (color_swatch_ctrl) +	{ +		color_swatch_ctrl->setOriginal(self->getWearable()->getClothesColor(entry->mTextureIndex)); +	} +} + +static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName); +	if (texture_ctrl) +	{ +		texture_ctrl->setDefaultImageAssetID(entry->mDefaultImageId); +		texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture); +		// Don't allow (no copy) or (notransfer) textures to be selected. +		texture_ctrl->setImmediateFilterPermMask(PERM_NONE); +		texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE); +	} +} + +static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName); +	if (color_swatch_ctrl) +	{ +		color_swatch_ctrl->set(self->getWearable()->getClothesColor(entry->mTextureIndex)); +	} +} + +static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName); +	if (texture_ctrl) +	{ +		LLUUID new_id; +		LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex); +		if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) ) +		{ +			new_id = lto->getID(); +		} +		else +		{ +			new_id = LLUUID::null; +		} +		LLUUID old_id = texture_ctrl->getImageAssetID(); +		if (old_id != new_id) +		{ +			// texture has changed, close the floater to avoid DEV-22461 +			texture_ctrl->closeDependentFloater(); +		} +		texture_ctrl->setImageAssetID(new_id); +	} +} + +static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName); +	if (color_swatch_ctrl) +	{ +		color_swatch_ctrl->setEnabled(enabled); +	} +} + +static void set_enabled_texture_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) +{ +	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName); +	if (texture_ctrl) +	{ +		texture_ctrl->setEnabled(enabled); +	} +}  // LLPanelEditWearable @@ -273,6 +589,8 @@ LLPanelEditWearable::LLPanelEditWearable()  	, mWearablePtr(NULL)  	, mWearableItem(NULL)  { +	mCommitCallbackRegistrar.add("ColorSwatch.Commit", boost::bind(&LLPanelEditWearable::onColorSwatchCommit, this, _1)); +	mCommitCallbackRegistrar.add("TexturePicker.Commit", boost::bind(&LLPanelEditWearable::onTexturePickerCommit, this, _1));  }  //virtual @@ -341,6 +659,10 @@ BOOL LLPanelEditWearable::isDirty() const  void LLPanelEditWearable::draw()  {  	updateVerbs(); +	if (getWearable()) +	{ +		updatePanelPickerControls(getWearable()->getType()); +	}  	LLPanel::draw();  } @@ -361,6 +683,102 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata)  	panel->revertChanges();  } +void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl) +{ +	const LLTextureCtrl* texture_ctrl = dynamic_cast<const LLTextureCtrl*>(ctrl); +	if (!texture_ctrl) +	{ +		llwarns << "got commit signal from not LLTextureCtrl." << llendl; +		return; +	} + +	if (getWearable()) +	{ +		EWearableType type = getWearable()->getType(); +		const PickerControlEntryNamePredicate name_pred(texture_ctrl->getName()); +		const LLEditWearableDictionary::PickerControlEntry* entry +			= find_picker_ctrl_entry_if<LLTextureCtrl, PickerControlEntryNamePredicate>(type, name_pred); +		if (entry) +		{ +			// Set the new version +			LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID()); +			if( image->getID().isNull() ) +			{ +				image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); +			} +			if (getWearable()) +			{ +				U32 index = gAgentWearables.getWearableIndex(getWearable()); +				gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); +				LLVisualParamHint::requestHintUpdates(); +				gAgentAvatarp->wearableUpdated(type, FALSE); +			} +		} +		else +		{ +			llwarns << "could not get texture picker dictionary entry for wearable of type: " << type << llendl; +		} +	} +} + +void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl) +{ +	if (getWearable()) +	{ +		EWearableType type = getWearable()->getType(); +		const PickerControlEntryNamePredicate name_pred(ctrl->getName()); +		const LLEditWearableDictionary::PickerControlEntry* entry +			= find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred); +		if (entry) +		{ +			const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex); +			const LLColor4& new_color = LLColor4(ctrl->getValue()); +			if( old_color != new_color ) +			{ +				getWearable()->setClothesColor(entry->mTextureIndex, new_color, TRUE); +				LLVisualParamHint::requestHintUpdates(); +				gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE); +			} +		} +		else +		{ +			llwarns << "could not get color swatch dictionary entry for wearable of type: " << type << llendl; +		} +	} +} + +void LLPanelEditWearable::updatePanelPickerControls(EWearableType type) +{ +	LLPanel* panel = getPanel(type); +	if (!panel) +		return; + +	bool is_modifiable = false; +	bool is_complete   = false; +	bool is_copyable   = false; + +	if(mWearableItem) +	{ +		const LLPermissions& perm = mWearableItem->getPermissions(); +		is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); +		is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()); +		is_complete = mWearableItem->isFinished(); +	} + +	if (is_modifiable && is_complete) +	{ +		// Update picker controls +		for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(update_color_swatch_ctrl, this, _1, _2)); +		for_each_picker_ctrl_entry <LLTextureCtrl>     (panel, type, boost::bind(update_texture_ctrl, this, _1, _2)); +	} + +	if (!is_modifiable || !is_complete || !is_copyable) +	{ +		// Disable controls +		for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(set_enabled_color_swatch_ctrl, false, _1, _2)); +		for_each_picker_ctrl_entry <LLTextureCtrl>     (panel, type, boost::bind(set_enabled_texture_ctrl, false, _1, _2)); +	} +}  void LLPanelEditWearable::saveChanges()  { @@ -428,6 +846,9 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)  		mDescTitle->setText(description_title);  	} +	// Update picker controls state +	for_each_picker_ctrl_entry <LLColorSwatchCtrl> (targetPanel, type, boost::bind(set_enabled_color_swatch_ctrl, show, _1, _2)); +	for_each_picker_ctrl_entry <LLTextureCtrl>     (targetPanel, type, boost::bind(set_enabled_texture_ctrl, show, _1, _2));  }  void LLPanelEditWearable::initializePanel() @@ -493,6 +914,11 @@ void LLPanelEditWearable::initializePanel()  		updateScrollingPanelUI();  	} + +	// initialize texture and color picker controls +	for_each_picker_ctrl_entry <LLColorSwatchCtrl> (getPanel(type), type, boost::bind(init_color_swatch_ctrl, this, _1, _2)); +	for_each_picker_ctrl_entry <LLTextureCtrl>     (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2)); +  	updateVerbs();  } diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 8b63685177..76b0ddb3cc 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -77,6 +77,10 @@ private:  	// update bottom bar buttons ("Save", "Revert", etc)  	void				updateVerbs(); +	void				onColorSwatchCommit(const LLUICtrl*); +	void				onTexturePickerCommit(const LLUICtrl*); +	void				updatePanelPickerControls(EWearableType type); +  	// the pointer to the wearable we're editing. NULL means we're not editing a wearable.  	LLWearable *mWearablePtr;  	LLViewerInventoryItem* mWearableItem; @@ -112,7 +116,6 @@ private:  	LLPanel *mPanelSkirt;  	LLPanel *mPanelAlpha;  	LLPanel *mPanelTattoo; -  };  #endif diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 67d40a39b1..0a978d1b26 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -583,6 +583,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list  	if (!inventory_list->getFilter())  		return; +	inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems");  	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);  	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 789e85b46f..80964938f5 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -188,19 +188,37 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)  void LLPanelOutfitsInventory::onWearButtonClick()  { -	LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); -	if (listenerp) +	// TODO: Remove if/else, add common interface +	// for "My Outfits" and "Wearing" tabs. +	if (!isCOFPanelActive()) +	{ +		mMyOutfitsPanel->performAction("replaceoutfit"); +	} +	else  	{ -		listenerp->performAction(NULL, "replaceoutfit"); +		LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); +		if (listenerp) +		{ +			listenerp->performAction(NULL, "replaceoutfit"); +		}  	}  }  void LLPanelOutfitsInventory::onAdd()  { -	LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); -	if (listenerp) +	// TODO: Remove if/else, add common interface +	// for "My Outfits" and "Wearing" tabs. +	if (!isCOFPanelActive()) +	{ +		mMyOutfitsPanel->performAction("addtooutfit"); +	} +	else  	{ -		listenerp->performAction(NULL, "addtooutfit"); +		LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); +		if (listenerp) +		{ +			listenerp->performAction(NULL, "addtooutfit"); +		}  	}  } diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f60951ca66..f2c0f92f9b 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -443,6 +443,7 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(),  		mFilterSubString(LLStringUtil::null), +		mFilterSubStringOrig(LLStringUtil::null),  		mFilterEditor(NULL),  		mTabContainer(NULL),  		mOnlineFriendList(NULL), @@ -658,7 +659,9 @@ void LLPanelPeople::updateFriendListHelpText()  	{  		//update help text for empty lists  		std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; -		no_friends_text->setText(getString(message_name)); +		LLStringUtil::format_map_t args; +		args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); +		no_friends_text->setText(getString(message_name, args));  	}  } @@ -981,10 +984,11 @@ bool LLPanelPeople::isRealGroup()  void LLPanelPeople::onFilterEdit(const std::string& search_string)  { -	std::string search_upper = search_string; +	mFilterSubStringOrig = search_string; +	LLStringUtil::trimHead(mFilterSubStringOrig);  	// Searches are case-insensitive +	std::string search_upper = mFilterSubStringOrig;  	LLStringUtil::toUpper(search_upper); -	LLStringUtil::trimHead(search_upper);  	if (mFilterSubString == search_upper)  		return; @@ -999,11 +1003,11 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	// Apply new filter. -	mNearbyList->setNameFilter(mFilterSubString); -	mOnlineFriendList->setNameFilter(mFilterSubString); -	mAllFriendList->setNameFilter(mFilterSubString); -	mRecentList->setNameFilter(mFilterSubString); -	mGroupList->setNameFilter(mFilterSubString); +	mNearbyList->setNameFilter(mFilterSubStringOrig); +	mOnlineFriendList->setNameFilter(mFilterSubStringOrig); +	mAllFriendList->setNameFilter(mFilterSubStringOrig); +	mRecentList->setNameFilter(mFilterSubStringOrig); +	mGroupList->setNameFilter(mFilterSubStringOrig);  	setAccordionCollapsedByUser("tab_online", false);  	setAccordionCollapsedByUser("tab_all", false); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 1bd3ea471c..17c45a034b 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -169,6 +169,7 @@ private:  	Updater*				mRecentListUpdater;  	std::string				mFilterSubString; +	std::string				mFilterSubStringOrig;  };  #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 89293d0e50..51a11e97e4 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -528,8 +528,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_fi  		std::string string = search_string;  		// Searches are case-insensitive -		LLStringUtil::toUpper(string); -		LLStringUtil::trimHead(string); +		// but we don't convert the typed string to upper-case so that it can be fed to the web search as-is.  		mActivePanel->onSearchEdit(string);  	} diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 75702dc8e5..fb7ac0d86b 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -35,6 +35,7 @@  #include "llpreviewnotecard.h"  #include "llinventory.h" +#include "llinventoryfunctions.h" // for change_item_parent()  #include "llagent.h"  #include "llassetuploadresponders.h" @@ -92,11 +93,17 @@ BOOL LLPreviewNotecard::postBuild()  	childSetAction("Save", onClickSave, this);  	childSetVisible("lock", FALSE);	 +	childSetAction("Delete", onClickDelete, this); +	childSetEnabled("Delete", false); +  	const LLInventoryItem* item = getItem();  	childSetCommitCallback("desc", LLPreview::onText, this);  	if (item) +	{  		childSetText("desc", item->getDescription()); +		childSetEnabled("Delete", true); +	}  	childSetPrevalidate("desc", &LLTextValidate::validateASCIIPrintableNoPipe);  	return LLPreview::postBuild(); @@ -374,6 +381,17 @@ void LLPreviewNotecard::onClickSave(void* user_data)  	}  } + +// static +void LLPreviewNotecard::onClickDelete(void* user_data) +{ +	LLPreviewNotecard* preview = (LLPreviewNotecard*)user_data; +	if(preview) +	{ +		preview->deleteNotecard(); +	} +} +  struct LLSaveNotecardInfo  {  	LLPreviewNotecard* mSelf; @@ -466,6 +484,18 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)  	return true;  } +void LLPreviewNotecard::deleteNotecard() +{ +	LLViewerInventoryItem* item = gInventory.getItem(mItemUUID); +	if (item != NULL) +	{ +		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); +		change_item_parent(&gInventory, item, trash_id, FALSE); +	} + +	closeFloater(); +} +  // static  void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)  { diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index e0363eef54..98de99aa33 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -83,6 +83,8 @@ protected:  	virtual void loadAsset();  	bool saveIfNeeded(LLInventoryItem* copyitem = NULL); +	void deleteNotecard(); +  	static void onLoadComplete(LLVFS *vfs,  							   const LLUUID& asset_uuid,  							   LLAssetType::EType type, @@ -90,6 +92,8 @@ protected:  	static void onClickSave(void* data); +	static void onClickDelete(void* data); +  	static void onSaveComplete(const LLUUID& asset_uuid,  							   void* user_data,  							   S32 status, LLExtStat ext_status); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index af440a3689..de1da248c1 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -706,6 +706,31 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)  	}  } +void LLScreenChannel::closeHiddenToasts(const Matcher& matcher) +{ +	// since we can't guarantee that close toast operation doesn't change mToastList +	// we collect matched toasts that should be closed into separate list +	std::list<ToastElem> toasts; +	for (std::vector<ToastElem>::iterator it = mToastList.begin(); it +			!= mToastList.end(); it++) +	{ +		LLToast * toast = it->toast; +		// add to list valid toast that match to provided matcher criteria +		if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL +				&& !toast->getVisible() && matcher.matches(toast->getNotification())) +		{ +			toasts.push_back(*it); +		} +	} + +	// close collected toasts +	for (std::list<ToastElem>::iterator it = toasts.begin(); it +			!= toasts.end(); it++) +	{ +		it->toast->closeFloater(); +	} +} +  //--------------------------------------------------------------------------  void LLScreenChannel::removeToastsFromChannel()  { diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 88053d87d9..46c5fed7b6 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -173,6 +173,12 @@ public:  	void		hideToastsFromScreen();  	// hide toast by notification id  	void		hideToast(const LLUUID& notification_id); + +	/** +	 * Closes hidden matched toasts from channel. +	 */ +	void closeHiddenToasts(const Matcher& matcher); +  	// removes all toasts from a channel  	void		removeToastsFromChannel();  	// show all toasts in a channel diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index cfa05987ab..e66be1023d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -3624,14 +3624,14 @@ void LLSelectMgr::sendAttach(U8 attachment_point)  		return;  	} -#if ENABLE_MULTIATTACHMENTS -	attachment_point |= ATTACHMENT_ADD; -#endif  	BOOL build_mode = LLToolMgr::getInstance()->inEdit();  	// Special case: Attach to default location for this object.  	if (0 == attachment_point ||  		get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))  	{ +#if ENABLE_MULTIATTACHMENTS +		attachment_point |= ATTACHMENT_ADD; +#endif  		sendListToRegions(  			"ObjectAttach",  			packAgentIDAndSessionAndAttachment,  diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 87494daaa9..f38df19de0 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -197,8 +197,7 @@ void LLSidepanelAppearance::onFilterEdit(const std::string& search_string)  		mFilterSubString = search_string;  		// Searches are case-insensitive -		LLStringUtil::toUpper(mFilterSubString); -		LLStringUtil::trimHead(mFilterSubString); +		// but we don't convert the typed string to upper-case so that it can be fed to the web search as-is.  		mPanelOutfitsInventory->onSearchEdit(mFilterSubString);  	} diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index e64696b120..3d447dd411 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -167,8 +167,6 @@ public:  	}  protected: -	LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host, -						 F32 priority, S32 discard, S32 size);  	LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,  						 F32 priority, S32 discard, S32 size); @@ -215,8 +213,15 @@ private:  		QUEUED = 1,  		SENT_SIM = 2  	}; +	enum e_write_to_cache_state //mWriteToCacheState +	{ +		NOT_WRITE = 0, +		CAN_WRITE = 1, +		SHOULD_WRITE = 2 +	};  	static const char* sStateDescs[];  	e_state mState; +	e_write_to_cache_state mWriteToCacheState;  	LLTextureFetch* mFetcher;  	LLPointer<LLImageFormatted> mFormattedImage;  	LLPointer<LLImageRaw> mRawImage; @@ -377,6 +382,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  										   S32 size)			// Desired size  	: LLWorkerClass(fetcher, "TextureFetch"),  	  mState(INIT), +	  mWriteToCacheState(NOT_WRITE),  	  mFetcher(fetcher),  	  mID(id),  	  mHost(host), @@ -595,7 +601,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	}  	if (mState == INIT) -	{ +	{		  		mRawImage = NULL ;  		mRequestedDiscard = -1;  		mLoadedDiscard = -1; @@ -636,17 +642,18 @@ bool LLTextureFetchWorker::doWork(S32 param)  			mFileSize = 0;  			mLoaded = FALSE;  			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it - -			CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); +			  			if (mUrl.compare(0, 7, "file://") == 0)  			{  				// read file from local disk  				std::string filename = mUrl.substr(7, std::string::npos); +				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,  																		  offset, size, responder);  			}  			else if (mUrl.empty())  			{ +				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,  																		  offset, size, responder);  			} @@ -659,8 +666,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  				}  				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  				mState = SEND_HTTP_REQ; -				delete responder; -				responder = NULL;  			}  		} @@ -694,6 +699,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  			llassert_always(mFormattedImage->getDataSize() > 0);  			mLoadedDiscard = mDesiredDiscard;  			mState = DECODE_IMAGE; +			mWriteToCacheState = NOT_WRITE ;  			LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()  								 << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())  								 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; @@ -735,6 +741,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				if (!http_url.empty())  				{  					mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); +					mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.  				}  			}  			else @@ -747,12 +754,17 @@ bool LLTextureFetchWorker::doWork(S32 param)  		{  			mState = LLTextureFetchWorker::SEND_HTTP_REQ;  			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +			if(mWriteToCacheState != NOT_WRITE) +			{ +				mWriteToCacheState = CAN_WRITE ; +			}  			// don't return, fall through to next state  		}  		else if (mSentRequest == UNSENT)  		{  			// Add this to the network queue and sit here.  			// LLTextureFetch::update() will send off a request which will change our state +			mWriteToCacheState = CAN_WRITE ;  			mRequestedSize = mDesiredSize;  			mRequestedDiscard = mDesiredDiscard;  			mSentRequest = QUEUED; @@ -789,6 +801,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  			}  			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  			mState = DECODE_IMAGE; +			mWriteToCacheState = SHOULD_WRITE ;  		}  		else  		{ @@ -850,7 +863,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  				mState = WAIT_HTTP_REQ;	  				mFetcher->addToHTTPQueue(mID); -				mSentRequest = QUEUED;  				// Will call callbackHttpGet when curl request completes  				std::vector<std::string> headers;  				headers.push_back("Accept: image/x-j2c"); @@ -933,15 +945,15 @@ bool LLTextureFetchWorker::doWork(S32 param)  			}  			llassert_always(mBufferSize == cur_size + mRequestedSize); -			if (mHaveAllData) +			if (mHaveAllData && mRequestedDiscard == 0) //the image file is fully loaded.  			{  				mFileSize = mBufferSize;  			} -			else //the file size is unknown +			else //the file size is unknown.  			{ -				mFileSize = S32_MAX ; //flag the file is not fully loaded. +				mFileSize = mBufferSize + 1 ; //flag the file is not fully loaded.  			} - +			  			U8* buffer = new U8[mBufferSize];  			if (cur_size > 0)  			{ @@ -956,6 +968,10 @@ bool LLTextureFetchWorker::doWork(S32 param)  			mBufferSize = 0;  			mLoadedDiscard = mRequestedDiscard;  			mState = DECODE_IMAGE; +			if(mWriteToCacheState != NOT_WRITE) +			{ +				mWriteToCacheState = SHOULD_WRITE ; +			}  			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  			return false;  		} @@ -1055,7 +1071,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WRITE_TO_CACHE)  	{ -		if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull()) +		if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull())  		{  			// If we're in a local cache or we didn't actually receive any new data,  			// or we failed to load anything, skip @@ -1063,6 +1079,17 @@ bool LLTextureFetchWorker::doWork(S32 param)  			return false;  		}  		S32 datasize = mFormattedImage->getDataSize(); +		if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed. +		{ +			if(mHaveAllData) +			{ +				mFileSize = datasize ; +			} +			else +			{ +				mFileSize = datasize + 1 ; //flag not fully loaded. +			} +		}  		llassert_always(datasize);  		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it  		U32 cache_priority = mWorkPriority; diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 2661c9f32b..9559311e3c 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -145,7 +145,7 @@ void audio_update_volume(bool force_update)  	{		  		F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");  		BOOL music_muted = gSavedSettings.getBOOL("MuteMusic"); -		music_volume = mute_volume * master_volume * (music_volume*music_volume); +		music_volume = mute_volume * master_volume * music_volume;  		gAudiop->setInternetStreamGain ( music_muted ? 0.f : music_volume );  	} @@ -153,7 +153,7 @@ void audio_update_volume(bool force_update)  	// Streaming Media  	F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");  	BOOL media_muted = gSavedSettings.getBOOL("MuteMedia"); -	media_volume = mute_volume * master_volume * (media_volume*media_volume); +	media_volume = mute_volume * master_volume * media_volume;  	LLViewerMedia::setVolume( media_muted ? 0.0f : media_volume );  	// Voice diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 3c0345df90..a4d8dddfe4 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -732,10 +732,17 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi  	}  } +static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media"); +  //////////////////////////////////////////////////////////////////////////////////////////  // static  void LLViewerMedia::updateMedia(void *dummy_arg)  { +	LLFastTimer t1(FTM_MEDIA_UPDATE); +	 +	// Enable/disable the plugin read thread +	LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); +	  	sAnyMediaShowing = false;  	sUpdatedCookies = getCookieStore()->getChangedCookies();  	if(!sUpdatedCookies.empty()) @@ -1914,7 +1921,15 @@ void LLViewerMediaImpl::updateVolume()  {  	if(mMediaSource)  	{ -		mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume()); +		F32 attenuation_multiplier = 1.0; + +		if (mProximityDistance > 0) +		{ +			// the attenuation multiplier should never be more than one since that would increase volume +			attenuation_multiplier = llmin(1.0, gSavedSettings.getF32("MediaRollOffFactor")/mProximityDistance); +		} + +		mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume() * attenuation_multiplier);  	}  } @@ -2427,6 +2442,8 @@ void LLViewerMediaImpl::update()  	}  	else  	{ +		updateVolume(); +  		// If we didn't just create the impl, it may need to get cookie updates.  		if(!sUpdatedCookies.empty())  		{ diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 78be6bdfd0..8e82725bb7 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1091,7 +1091,7 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)  		////////////////////////////////////////////////////////////////////////////////  		// Special handling for various types. -		const LLAssetType::EType asset_type = item->getType(); +		const LLAssetType::EType asset_type = item->getActualType();  		if (check_offer_throttle(from_name, false)) // If we are throttled, don't display  		{  			LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID()  << LL_ENDL; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 3d110dcc78..56b2791993 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -33,8 +33,11 @@  #include "llwearableitemslist.h" +#include "lliconctrl.h" +  #include "llinventoryfunctions.h"  #include "llinventorymodel.h" +#include "lltransutil.h"  class LLFindOutfitItems : public LLInventoryCollectFunctor  { @@ -60,6 +63,239 @@ bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,  	return FALSE;  } +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void LLPanelWearableListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	LLPanelInventoryListItemBase::onMouseEnter(x, y, mask); +	setWidgetsVisible(true); +	reshapeWidgets(); +} + +void LLPanelWearableListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	LLPanelInventoryListItemBase::onMouseLeave(x, y, mask); +	setWidgetsVisible(false); +	reshapeWidgets(); +} + +LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item) +: LLPanelInventoryListItemBase(item) +{ +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +// static +LLPanelClothingListItem* LLPanelClothingListItem::create(LLViewerInventoryItem* item) +{ +	LLPanelClothingListItem* list_item = NULL; +	if(item) +	{ +		list_item = new LLPanelClothingListItem(item); +		list_item->init(); +	} +	return list_item; +} + +LLPanelClothingListItem::LLPanelClothingListItem(LLViewerInventoryItem* item) + : LLPanelWearableListItem(item) +{ +} + +LLPanelClothingListItem::~LLPanelClothingListItem() +{ +} + +void LLPanelClothingListItem::init() +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_clothing_list_item.xml"); +} + +BOOL LLPanelClothingListItem::postBuild() +{ +	LLPanelInventoryListItemBase::postBuild(); + +	addWidgetToLeftSide("btn_delete"); +	addWidgetToRightSide("btn_move_up"); +	addWidgetToRightSide("btn_move_down"); +	addWidgetToRightSide("btn_lock"); +	addWidgetToRightSide("btn_edit"); + +	LLButton* delete_btn = getChild<LLButton>("btn_delete"); +	// Reserve space for 'delete' button event if it is invisible. +	setLeftWidgetsWidth(delete_btn->getRect().mRight); + +	setWidgetsVisible(false); +	reshapeWidgets(); + +	return TRUE; +} + +void LLPanelClothingListItem::setShowDeleteButton(bool show) +{ +	setShowWidget("btn_delete", show); +} + +void LLPanelClothingListItem::setShowMoveUpButton(bool show) +{ +	setShowWidget("btn_move_up", show); +} + +void LLPanelClothingListItem::setShowMoveDownButton(bool show) +{ +	setShowWidget("btn_move_down", show); +} + +void LLPanelClothingListItem::setShowLockButton(bool show) +{ +	setShowWidget("btn_lock", show); +} + +void LLPanelClothingListItem::setShowEditButton(bool show) +{ +	setShowWidget("btn_edit", show); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +// static +LLPanelBodyPartsListItem* LLPanelBodyPartsListItem::create(LLViewerInventoryItem* item) +{ +	LLPanelBodyPartsListItem* list_item = NULL; +	if(item) +	{ +		list_item = new LLPanelBodyPartsListItem(item); +		list_item->init(); +	} +	return list_item; +} + +LLPanelBodyPartsListItem::LLPanelBodyPartsListItem(LLViewerInventoryItem* item) +: LLPanelWearableListItem(item) +{ +} + +LLPanelBodyPartsListItem::~LLPanelBodyPartsListItem() +{ +} + +void LLPanelBodyPartsListItem::init() +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_body_parts_list_item.xml"); +} + +BOOL LLPanelBodyPartsListItem::postBuild() +{ +	LLPanelInventoryListItemBase::postBuild(); + +	addWidgetToRightSide("btn_lock"); +	addWidgetToRightSide("btn_edit"); + +	return TRUE; +} + +void LLPanelBodyPartsListItem::setShowLockButton(bool show) +{ +	setShowWidget("btn_lock", show); +} + +void LLPanelBodyPartsListItem::setShowEditButton(bool show) +{ +	setShowWidget("btn_edit", show); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelDummyClothingListItem* LLPanelDummyClothingListItem::create(EWearableType w_type) +{ +	LLPanelDummyClothingListItem* list_item = new LLPanelDummyClothingListItem(w_type); +	list_item->init(); +	return list_item; +} + +void LLPanelDummyClothingListItem::updateItem() +{ +	std::string title = wearableTypeToString(mWearableType); +	setTitle(title, LLStringUtil::null); +} + +BOOL LLPanelDummyClothingListItem::postBuild() +{ +	LLIconCtrl* icon = getChild<LLIconCtrl>("item_icon"); +	setIconCtrl(icon); +	setTitleCtrl(getChild<LLTextBox>("item_name")); + +	addWidgetToRightSide("btn_add"); + +	setIconImage(get_item_icon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, mWearableType, FALSE)); +	updateItem(); + +	// Make it look loke clothing item - reserve space for 'delete' button +	setLeftWidgetsWidth(icon->getRect().mLeft); + +	setWidgetsVisible(false); +	reshapeWidgets(); + +	return TRUE; +} + +LLPanelDummyClothingListItem::LLPanelDummyClothingListItem(EWearableType w_type) + : LLPanelWearableListItem(NULL) + , mWearableType(w_type) +{ +} + +void LLPanelDummyClothingListItem::init() +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_dummy_clothing_list_item.xml"); +} + +typedef std::map<EWearableType, std::string> clothing_to_string_map_t; + +clothing_to_string_map_t init_clothing_string_map() +{ +	clothing_to_string_map_t w_map; +	w_map.insert(std::make_pair(WT_SHIRT, "shirt_not_worn")); +	w_map.insert(std::make_pair(WT_PANTS, "pants_not_worn")); +	w_map.insert(std::make_pair(WT_SHOES, "shoes_not_worn")); +	w_map.insert(std::make_pair(WT_SOCKS, "socks_not_worn")); +	w_map.insert(std::make_pair(WT_JACKET, "jacket_not_worn")); +	w_map.insert(std::make_pair(WT_GLOVES, "gloves_not_worn")); +	w_map.insert(std::make_pair(WT_UNDERSHIRT, "undershirt_not_worn")); +	w_map.insert(std::make_pair(WT_UNDERPANTS, "underpants_not_worn")); +	w_map.insert(std::make_pair(WT_SKIRT, "skirt_not_worn")); +	w_map.insert(std::make_pair(WT_ALPHA, "alpha_not_worn")); +	w_map.insert(std::make_pair(WT_TATTOO, "tattoo_not_worn")); +	return w_map; +} + +std::string LLPanelDummyClothingListItem::wearableTypeToString(EWearableType w_type) +{ +	static const clothing_to_string_map_t w_map = init_clothing_string_map(); +	static const std::string invalid_str = LLTrans::getString("invalid_not_worn"); +	 +	std::string type_str = invalid_str; +	clothing_to_string_map_t::const_iterator it = w_map.find(w_type); +	if(w_map.end() != it) +	{ +		type_str = LLTrans::getString(it->second); +	} +	return type_str; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +  static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list");  LLWearableItemsList::Params::Params() @@ -89,3 +325,5 @@ void LLWearableItemsList::updateList(const LLUUID& category_id)  	refreshList(item_array);  } + +// EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index e7ccba8e6c..c4a415dfbf 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -36,6 +36,115 @@  // newview  #include "llinventoryitemslist.h" +#include "llinventorymodel.h" +#include "llwearabledictionary.h" + +/** + * @class LLPanelWearableListItem + * + * Extends LLPanelInventoryListItemBase: + * - makes side widgets show on mouse_enter and hide on  + *   mouse_leave events. + * - provides callback for button clicks + */ +class LLPanelWearableListItem : public LLPanelInventoryListItemBase +{ +	LOG_CLASS(LLPanelWearableListItem); +public: + +	/** +	* Shows buttons when mouse is over +	*/ +	/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + +	/** +	* Hides buttons when mouse is out +	*/ +	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + +protected: + +	LLPanelWearableListItem(LLViewerInventoryItem* item); +}; + +/** + * @class LLPanelClothingListItem + * + * Provides buttons for editing, moving, deleting a wearable. + */ +class LLPanelClothingListItem : public LLPanelWearableListItem +{ +	LOG_CLASS(LLPanelClothingListItem); +public: + +	static LLPanelClothingListItem* create(LLViewerInventoryItem* item); + +	virtual ~LLPanelClothingListItem(); + +	/*virtual*/ BOOL postBuild(); + +	/** +	 * Make button visible during mouse over event. +	 */ +	inline void setShowDeleteButton(bool show); +	inline void setShowMoveUpButton(bool show); +	inline void setShowMoveDownButton(bool show); +	inline void setShowLockButton(bool show); +	inline void setShowEditButton(bool show); + +protected: + +	LLPanelClothingListItem(LLViewerInventoryItem* item); +	 +	/*virtual*/ void init(); +}; + +class LLPanelBodyPartsListItem : public LLPanelWearableListItem +{ +	LOG_CLASS(LLPanelBodyPartsListItem); +public: + +	static LLPanelBodyPartsListItem* create(LLViewerInventoryItem* item); + +	virtual ~LLPanelBodyPartsListItem(); + +	/*virtual*/ BOOL postBuild(); + +	/** +	* Make button visible during mouse over event. +	*/ +	inline void setShowLockButton(bool show); +	inline void setShowEditButton(bool show); + +protected: +	LLPanelBodyPartsListItem(LLViewerInventoryItem* item); + +	/*virtual*/ void init(); +}; + +/** + * @class LLPanelDummyClothingListItem + * + * A dummy item panel - displays grayed clothing icon, grayed title '<clothing> not worn' and 'add' button + */ +class LLPanelDummyClothingListItem : public LLPanelWearableListItem +{ +public: +	static LLPanelDummyClothingListItem* create(EWearableType w_type); + +	/*virtual*/ void updateItem(); +	/*virtual*/ BOOL postBuild(); + +protected: +	LLPanelDummyClothingListItem(EWearableType w_type); + +	/*virtual*/ void init(); + +	static std::string wearableTypeToString(EWearableType w_type); + +private: +	EWearableType mWearableType; +};  /**   * @class LLWearableItemsList diff --git a/indra/newview/skins/default/textures/icons/Progress_1.png b/indra/newview/skins/default/textures/icons/Progress_1.pngBinary files differ index 58b56003c4..5d6efbfa2a 100644 --- a/indra/newview/skins/default/textures/icons/Progress_1.png +++ b/indra/newview/skins/default/textures/icons/Progress_1.png diff --git a/indra/newview/skins/default/textures/icons/Progress_10.png b/indra/newview/skins/default/textures/icons/Progress_10.pngBinary files differ index 07fe0be8a3..28203324f1 100644 --- a/indra/newview/skins/default/textures/icons/Progress_10.png +++ b/indra/newview/skins/default/textures/icons/Progress_10.png diff --git a/indra/newview/skins/default/textures/icons/Progress_11.png b/indra/newview/skins/default/textures/icons/Progress_11.pngBinary files differ index 215d68cc46..6b87be0c3f 100644 --- a/indra/newview/skins/default/textures/icons/Progress_11.png +++ b/indra/newview/skins/default/textures/icons/Progress_11.png diff --git a/indra/newview/skins/default/textures/icons/Progress_12.png b/indra/newview/skins/default/textures/icons/Progress_12.pngBinary files differ index d755588621..089d58b090 100644 --- a/indra/newview/skins/default/textures/icons/Progress_12.png +++ b/indra/newview/skins/default/textures/icons/Progress_12.png diff --git a/indra/newview/skins/default/textures/icons/Progress_2.png b/indra/newview/skins/default/textures/icons/Progress_2.pngBinary files differ index 6640ee227b..94cb73b1f7 100644 --- a/indra/newview/skins/default/textures/icons/Progress_2.png +++ b/indra/newview/skins/default/textures/icons/Progress_2.png diff --git a/indra/newview/skins/default/textures/icons/Progress_3.png b/indra/newview/skins/default/textures/icons/Progress_3.pngBinary files differ index 5decbe977e..a04a5b5263 100644 --- a/indra/newview/skins/default/textures/icons/Progress_3.png +++ b/indra/newview/skins/default/textures/icons/Progress_3.png diff --git a/indra/newview/skins/default/textures/icons/Progress_4.png b/indra/newview/skins/default/textures/icons/Progress_4.pngBinary files differ index 56e81c17aa..a467098d82 100644 --- a/indra/newview/skins/default/textures/icons/Progress_4.png +++ b/indra/newview/skins/default/textures/icons/Progress_4.png diff --git a/indra/newview/skins/default/textures/icons/Progress_5.png b/indra/newview/skins/default/textures/icons/Progress_5.pngBinary files differ index a89bf2ac62..ea64f1d907 100644 --- a/indra/newview/skins/default/textures/icons/Progress_5.png +++ b/indra/newview/skins/default/textures/icons/Progress_5.png diff --git a/indra/newview/skins/default/textures/icons/Progress_6.png b/indra/newview/skins/default/textures/icons/Progress_6.pngBinary files differ index 233c479540..fe4447935f 100644 --- a/indra/newview/skins/default/textures/icons/Progress_6.png +++ b/indra/newview/skins/default/textures/icons/Progress_6.png diff --git a/indra/newview/skins/default/textures/icons/Progress_7.png b/indra/newview/skins/default/textures/icons/Progress_7.pngBinary files differ index 631d7a6819..64fa294771 100644 --- a/indra/newview/skins/default/textures/icons/Progress_7.png +++ b/indra/newview/skins/default/textures/icons/Progress_7.png diff --git a/indra/newview/skins/default/textures/icons/Progress_8.png b/indra/newview/skins/default/textures/icons/Progress_8.pngBinary files differ index ac0e3f13f7..a1c9a7f2eb 100644 --- a/indra/newview/skins/default/textures/icons/Progress_8.png +++ b/indra/newview/skins/default/textures/icons/Progress_8.png diff --git a/indra/newview/skins/default/textures/icons/Progress_9.png b/indra/newview/skins/default/textures/icons/Progress_9.pngBinary files differ index 17fb4a0335..f3e9723184 100644 --- a/indra/newview/skins/default/textures/icons/Progress_9.png +++ b/indra/newview/skins/default/textures/icons/Progress_9.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index d72fb7144a..90388c7177 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -583,17 +583,17 @@ with the same filename but different name    <texture name="default_profile_picture.j2c" />    <texture name="locked_image.j2c" /> -  <texture name="Progress_1" file_name="icons/Progress_1.png" preload="false" /> -  <texture name="Progress_2" file_name="icons/Progress_2.png" preload="false" /> -  <texture name="Progress_3" file_name="icons/Progress_3.png" preload="false" /> -  <texture name="Progress_4" file_name="icons/Progress_4.png" preload="false" /> -  <texture name="Progress_5" file_name="icons/Progress_5.png" preload="false" /> -  <texture name="Progress_6" file_name="icons/Progress_6.png" preload="false" /> -  <texture name="Progress_7" file_name="icons/Progress_7.png" preload="false" /> -  <texture name="Progress_8" file_name="icons/Progress_8.png" preload="false" /> -  <texture name="Progress_9" file_name="icons/Progress_9.png" preload="false" /> -  <texture name="Progress_10" file_name="icons/Progress_10.png" preload="false" /> -  <texture name="Progress_11" file_name="icons/Progress_11.png" preload="false" /> -  <texture name="Progress_12" file_name="icons/Progress_12.png" preload="false" /> +  <texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" /> +  <texture name="Progress_2" file_name="icons/Progress_2.png" preload="true" /> +  <texture name="Progress_3" file_name="icons/Progress_3.png" preload="true" /> +  <texture name="Progress_4" file_name="icons/Progress_4.png" preload="true" /> +  <texture name="Progress_5" file_name="icons/Progress_5.png" preload="true" /> +  <texture name="Progress_6" file_name="icons/Progress_6.png" preload="true" /> +  <texture name="Progress_7" file_name="icons/Progress_7.png" preload="true" /> +  <texture name="Progress_8" file_name="icons/Progress_8.png" preload="true" /> +  <texture name="Progress_9" file_name="icons/Progress_9.png" preload="true" /> +  <texture name="Progress_10" file_name="icons/Progress_10.png" preload="true" /> +  <texture name="Progress_11" file_name="icons/Progress_11.png" preload="true" /> +  <texture name="Progress_12" file_name="icons/Progress_12.png" preload="true" />  </textures> diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index 14c0081c0d..0e8eef2a21 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -84,8 +84,18 @@       label="Save"       label_selected="Save"       layout="topleft" -     left="288" +     left="178"       name="Save"       top="332"       width="100" /> +    <button +     follows="right|bottom" +     height="22" +     label="Delete" +     label_selected="Delete" +     layout="topleft" +     left="288" +     name="Delete" +     top="332" +     width="100" />  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 5e1f6b58e8..11459ad0e6 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -410,6 +410,14 @@           parameter="open" />      </menu_item_call>      <menu_item_call +     label="Open Original" +     layout="topleft" +     name="Open Original"> +        <menu_item_call.on_click +         function="Inventory.DoToSelected" +         parameter="open_original" /> +    </menu_item_call> +    <menu_item_call       label="Properties"       layout="topleft"       name="Properties"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 6a5f9ed8f8..19b6b1b22e 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1339,6 +1339,16 @@               function="ToggleControl"               parameter="RunMultipleThreads" />          </menu_item_check> +        <menu_item_check +         label="Use Plugin Read Thread" +         name="Use Plugin Read Thread"> +            <menu_item_check.on_check +             function="CheckControl" +             parameter="PluginUseReadThread" /> +            <menu_item_check.on_click +             function="ToggleControl" +             parameter="PluginUseReadThread" /> +        </menu_item_check>          <menu_item_call           label="Clear Group Cache"           name="ClearGroupCache"> diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 8e1e5ff062..a585069faa 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -120,7 +120,7 @@  			none  		</widgettype>  		<impl> -			media_plugin_quicktime +			media_plugin_webkit  		</impl>  	</mimetype>  	<mimetype name="none/none"> @@ -130,6 +130,9 @@  		<widgettype>  			none  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/*">  		<label name="audio2_label"> @@ -160,6 +163,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">  		<label name="vnd.secondlife.qt.legacy_label"> @@ -179,6 +185,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/ogg">  		<label name="application/ogg_label"> @@ -187,6 +196,9 @@  		<widgettype>  			audio  		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl>  	</mimetype>  	<mimetype name="application/pdf">  		<label name="application/pdf_label"> @@ -195,6 +207,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/postscript">  		<label name="application/postscript_label"> @@ -203,6 +218,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/rtf">  		<label name="application/rtf_label"> @@ -211,6 +229,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/smil">  		<label name="application/smil_label"> @@ -219,6 +240,9 @@  		<widgettype>  			movie  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/xhtml+xml">  		<label name="application/xhtml+xml_label"> @@ -227,6 +251,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/x-director">  		<label name="application/x-director_label"> @@ -235,6 +262,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/mid">  		<label name="audio/mid_label"> diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml index 4748c14554..e95b371d00 100644 --- a/indra/newview/skins/default/xui/en/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -120,7 +120,7 @@  			none  		</widgettype>  		<impl> -			media_plugin_gstreamer +			media_plugin_webkit  		</impl>  	</mimetype>  	<mimetype name="none/none"> @@ -130,6 +130,9 @@  		<widgettype>  			none  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/*">  		<label name="audio2_label"> @@ -160,6 +163,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">  		<label name="vnd.secondlife.qt.legacy_label"> @@ -179,6 +185,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/ogg">  		<label name="application/ogg_label"> @@ -187,6 +196,9 @@  		<widgettype>  			audio  		</widgettype> +		<impl> +			media_plugin_gstreamer +		</impl>  	</mimetype>  	<mimetype name="application/pdf">  		<label name="application/pdf_label"> @@ -195,6 +207,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/postscript">  		<label name="application/postscript_label"> @@ -203,6 +218,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/rtf">  		<label name="application/rtf_label"> @@ -211,6 +229,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/smil">  		<label name="application/smil_label"> @@ -219,6 +240,9 @@  		<widgettype>  			movie  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/xhtml+xml">  		<label name="application/xhtml+xml_label"> @@ -227,6 +251,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/x-director">  		<label name="application/x-director_label"> @@ -235,6 +262,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/mid">  		<label name="audio/mid_label"> diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml index 8e1e5ff062..7931e55c0a 100644 --- a/indra/newview/skins/default/xui/en/mime_types_mac.xml +++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml @@ -130,6 +130,9 @@  		<widgettype>  			none  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/*">  		<label name="audio2_label"> @@ -160,6 +163,9 @@  		<widgettype>  			image  		</widgettype> +        <impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">  		<label name="vnd.secondlife.qt.legacy_label"> @@ -179,6 +185,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/ogg">  		<label name="application/ogg_label"> @@ -187,6 +196,9 @@  		<widgettype>  			audio  		</widgettype> +		<impl> +			media_plugin_quicktime +		</impl>  	</mimetype>  	<mimetype name="application/pdf">  		<label name="application/pdf_label"> @@ -195,6 +207,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/postscript">  		<label name="application/postscript_label"> @@ -203,6 +218,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/rtf">  		<label name="application/rtf_label"> @@ -211,6 +229,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/smil">  		<label name="application/smil_label"> @@ -219,6 +240,9 @@  		<widgettype>  			movie  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/xhtml+xml">  		<label name="application/xhtml+xml_label"> @@ -227,6 +251,9 @@  		<widgettype>  			web  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="application/x-director">  		<label name="application/x-director_label"> @@ -235,6 +262,9 @@  		<widgettype>  			image  		</widgettype> +		<impl> +			media_plugin_webkit +		</impl>  	</mimetype>  	<mimetype name="audio/mid">  		<label name="audio/mid_label"> diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index b3150bb98b..5fcc9b012b 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -1,6 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <!-- *NOTE: mantipov: this xml is intended to be used inside panel_outfits_list.xml for each outfit folder-->  <!-- All accordion tabs in the My Appearance/My Outfits panel will be created from this one at runtime--> +<!-- Non of string values of controls below are visible to user. They are not need to be translated. -->  <accordion_tab   display_children="false"   follows="all" @@ -8,11 +9,13 @@   layout="topleft"   name="Mockup Tab"   title="Mockup Tab" + translate="false"   width="0">      <wearable_items_list       allow_select="true"       follows="all"       keep_one_selected="true"       name="wearable_items_list" +     translate="false"      />  </accordion_tab> diff --git a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml new file mode 100644 index 0000000000..4313d450fb --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="20" + layout="topleft" + left="0" + name="wearable_item" + top="0" + width="380"> +    <icon +     follows="top|right|left" +     height="20" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     height="20" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     height="16" +     follows="top|left" +     image_name="Inv_Object" +     layout="topleft" +     left="0" +     name="item_icon" +     top="2" +     width="16" /> +    <text +     follows="left|right" +     height="16" +     layout="topleft" +     left_pad="5" +     allow_html="false" +     use_ellipses="true" +     name="item_name" +     text_color="white" +     top="4" +     value="..." +     width="359" /> +    <icon  +     name="btn_lock" +     layout="topleft" +     follows="top|right" +     image_name="Lock2" +     top="0" +     left="0" +     height="20" +     width="20" +     tab_stop="false" /> +    <button  +     name="btn_edit" +     layout="topleft" +     follows="top|right" +     image_unselected="Icon_Gear_Background" +     image_selected="Icon_Gear_Background" +     top="0" +     left_pad="3" +     height="20" +     width="20" +     tab_stop="false" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..9d19b89a61 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> + +<panel + follows="left|right|top" + height="35" + layout="topleft" + left="0" + name="clothing_list_button_bar_panel" + top="0" + visible="true" + width="300"> +    <button +     follows="top|left" +     height="25" +     image_hover_unselected="Toolbar_Middle_Over" +     image_selected="Toolbar_Middle_Selected" +     image_unselected="Toolbar_Middle_Off" +     label="Switch" +     layout="topleft" +     left="5" +     name="switch_btn" +     top="5" +     width="45" /> +    <button +     follows="top|right" +     height="25" +     image_hover_unselected="Toolbar_Middle_Over" +     image_selected="Toolbar_Middle_Selected" +     image_unselected="Toolbar_Middle_Off" +     label="Shop >"  +     layout="topleft" +     right="-5" +     name="bodyparts_shop_btn" +     top="5" +     width="61" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..2359719c2a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> + +<panel + follows="left|right|top" + height="35" + layout="topleft" + left="0" + name="clothing_list_button_bar_panel" + top="0" + visible="true" + width="500"> +    <button +     follows="top|left" +     height="25" +     image_hover_unselected="Toolbar_Middle_Over" +     image_selected="Toolbar_Middle_Selected" +     image_unselected="Toolbar_Middle_Off" +     is_toggle="true" +     label="Add +" +     layout="topleft" +     left="5" +     name="add_btn" +     top="5" +     width="45" /> +    <button +     follows="top|right" +     height="25" +     image_hover_unselected="Toolbar_Middle_Over" +     image_selected="Toolbar_Middle_Selected" +     image_unselected="Toolbar_Middle_Off" +     label="Shop >"  +     layout="topleft" +     right="-5" +     name="clothing_shop_btn" +     top="5" +     width="61" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml new file mode 100644 index 0000000000..8dc67de06f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="20" + layout="topleft" + left="0" + name="wearable_item" + top="0" + width="380"> +    <icon +     follows="top|right|left" +     height="20" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     height="20" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <button  +     name="btn_delete" +     layout="topleft" +     follows="top|left" +     image_unselected="Toast_CloseBtn" +     image_selected="Toast_CloseBtn" +     top="0" +     left="0" +     height="20" +     width="20" +     tab_stop="false" /> +    <icon +     height="16" +     follows="top|left" +     image_name="Inv_Object" +     layout="topleft" +     left_pad="3" +     name="item_icon" +     top="2" +     width="16" /> +    <text +     follows="left|right" +     height="16" +     layout="topleft" +     left_pad="5" +     allow_html="false" +     use_ellipses="true" +     name="item_name" +     text_color="white" +     top="4" +     value="..." +     width="359" /> +    <button  +     name="btn_move_up" +     layout="topleft" +     follows="top|right" +     image_unselected="Movement_Up_Off" +     image_selected="Movement_Up_Off" +     top="0" +     left="0" +     height="20" +     width="20" +     tab_stop="false" /> +    <button  +     name="btn_move_down" +     layout="topleft" +     follows="top|right" +     image_unselected="Movement_Down_Off" +     image_selected="Movement_Down_Off" +     top="0" +     left_pad="3" +     height="20" +     width="20" +     tab_stop="false" /> +    <icon +     name="btn_lock" +     layout="topleft" +     follows="top|right" +     image_name="Lock2" +     top="0" +     left_pad="3" +     height="20" +     width="20" /> +    <button  +     name="btn_edit" +     layout="topleft" +     follows="top|right" +     image_unselected="Icon_Gear_Background" +     image_selected="Icon_Gear_Background" +     top="0" +     left_pad="3" +     height="20" +     width="20" +     tab_stop="false" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 01c7ae61d2..d8a8dbbea4 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -14,6 +14,7 @@       height="373"       layout="topleft"       left="3" +     single_expansion="true"       top="0"       name="cof_wearables_accordion"       background_visible="true" diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml new file mode 100644 index 0000000000..dbbfa8f2e2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="20" + layout="topleft" + left="0" + name="dummy_clothing_item" + top="0" + width="380"> +    <icon +     follows="top|right|left" +     height="20" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     height="20" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     height="16" +     color="0.75 0.75 0.75 1" +     follows="top|left" +     image_name="Inv_Object" +     layout="topleft" +     left="20" +     name="item_icon" +     top="2" +     width="16" /> +    <text +     follows="left|right" +     height="16" +     layout="topleft" +     left_pad="5" +     allow_html="false" +     use_ellipses="true" +     name="item_name" +     text_color="LtGray_50" +     top="4" +     value="..." +     width="359" /> +    <button  +     name="btn_add" +     layout="topleft" +     follows="top|right" +     label="+" +     top="0" +     left="0" +     height="20" +     width="20" +     tab_stop="false" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml index 1d0c0a02b0..cfcdc25f81 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml @@ -32,7 +32,10 @@          name="Lower Alpha"          tool_tip="Click to choose a picture"          top="10" -        width="94" /> +        width="94" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <check_box          control_name="LowerAlphaTextureInvisible"          follows="left" @@ -53,7 +56,10 @@          name="Upper Alpha"          tool_tip="Click to choose a picture"          top="10" -        width="94" /> +        width="94"> +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <check_box          control_name="UpperAlphaTextureInvisible"          follows="left" @@ -74,7 +80,10 @@          name="Head Alpha"          tool_tip="Click to choose a picture"          top="120" -        width="94" /> +        width="94" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <check_box          control_name="HeadAlphaTextureInvisible"          follows="left" @@ -95,7 +104,10 @@          name="Eye Alpha"          tool_tip="Click to choose a picture"          top="120" -        width="94" /> +        width="94" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <check_box          control_name="Eye AlphaTextureInvisible"          follows="left" @@ -116,7 +128,10 @@          name="Hair Alpha"          tool_tip="Click to choose a picture"          top="230" -        width="94" /> +        width="94" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <check_box          control_name="HairAlphaTextureInvisible"          follows="left" diff --git a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml index f11ef43c76..4149a0b06f 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml @@ -32,8 +32,11 @@               name="Iris"               tool_tip="Click to choose a picture"               top="10" -             width="64" /> -	 </panel> +             width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker> +     </panel>       <panel           border="false"           bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml index 7d8eed5085..94fd2f9080 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,9 +46,12 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> -	 </panel> -	 <panel +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch> +     </panel> +     <panel           border="false"           bg_alpha_color="DkGray2"           bg_opaque_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_edit_hair.xml b/indra/newview/skins/default/xui/en/panel_edit_hair.xml index cd81aa2c4f..9b60e83387 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_hair.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_hair.xml @@ -32,8 +32,11 @@               name="Texture"               tool_tip="Click to choose a picture"               top="10" -             width="64" /> -	 </panel> +             width="64" > +              <texture_picker.commit_callback +                  function="TexturePicker.Commit" /> +            </texture_picker> +     </panel>     <panel           border="false"           bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml index ba03865937..248ae9fe04 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml @@ -32,7 +32,10 @@          name="Upper Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="74" /> +        width="74" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <texture_picker          can_apply_immediately="true"          default_image_name="Default" @@ -44,7 +47,10 @@          name="Lower Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="74" /> +        width="74" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -55,7 +61,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="74" /> +        width="74" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>  	 <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_pants.xml b/indra/newview/skins/default/xui/en/panel_edit_pants.xml index 5b02d1f968..3ed1df2399 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>       <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml index 7da8de4c0b..e088aa05ac 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>       <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml index 84fe26f7f6..e079047a86 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>       <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml index b5c8c95473..9158685c40 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skin.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml @@ -33,7 +33,10 @@          name="Head Tattoos"          tool_tip="Click to choose a picture"          top="10" -        width="74" /> +        width="74" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <texture_picker          allow_no_texture="true"          can_apply_immediately="true" @@ -46,7 +49,10 @@          name="Upper Tattoos"          tool_tip="Click to choose a picture"          top="10" -        width="74" /> +        width="74" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <texture_picker          allow_no_texture="true"          can_apply_immediately="true" @@ -59,8 +65,11 @@          name="Lower Tattoos"          tool_tip="Click to choose a picture"          top="10" -        width="74" /> -	 </panel> +        width="74" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker> +     </panel>       <panel           border="false"           bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml index 16f6950bd5..87f3270b31 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>  	 <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_socks.xml b/indra/newview/skins/default/xui/en/panel_edit_socks.xml index e4f916703b..5bd99969a2 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_socks.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open color picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>  	 </panel>  	 <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml index d43497c943..bbe5230341 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml @@ -32,7 +32,10 @@               name="Fabric"               tool_tip="Click to choose a picture"               top="10" -             width="64" /> +             width="64" > +              <texture_picker.commit_callback +                  function="TexturePicker.Commit" /> +            </texture_picker>              <color_swatch               can_apply_immediately="true"               follows="left|top" @@ -43,7 +46,10 @@               name="Color/Tint"               tool_tip="Click to open color picker"               top="10" -             width="64" /> +             width="64" > +              <color_swatch.commit_callback +                  function="ColorSwatch.Commit" /> +            </color_swatch>  	 </panel>  	 <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml index 45c6ef4526..a79c1b9eaa 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml @@ -32,7 +32,10 @@          name="Fabric"          tool_tip="Click to choose a picture"          top="10" -        width="64" /> +        width="64" > +         <texture_picker.commit_callback +             function="TexturePicker.Commit" /> +       </texture_picker>         <color_swatch          can_apply_immediately="true"          follows="left|top" @@ -43,7 +46,10 @@          name="Color/Tint"          tool_tip="Click to open Color Picker"          top="10" -        width="64" /> +        width="64" > +         <color_swatch.commit_callback +             function="ColorSwatch.Commit" /> +       </color_swatch>         </panel>  	 <panel           border="false" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 27d66945d9..46625144e1 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -3,7 +3,7 @@   background_visible="true"   default_tab_group="1"   follows="all" - height="408" + height="423"   label="Things"   layout="topleft"   min_height="350" @@ -48,7 +48,7 @@     left="10"     max_length="300"     name="inventory search editor" -   top="3" +   top="18"     width="303" />    <tab_container       bg_alpha_color="DkGray" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 73181392c9..a9f588698a 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -234,6 +234,14 @@                   name="move_further_btn"                   top="1"                   width="31" /> +                <icon +                 follows="bottom|left" +                 height="25" +                 image_name="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="1" +                 name="dummy_icon" +                 width="105" />                  <button                   follows="bottom|right"                   height="25" @@ -440,6 +448,22 @@                   name="add_to_outfit_btn"                   top="1"                   width="31" /> +                <icon +                 follows="bottom|left" +                 height="25" +                 image_name="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="1" +                 name="dummy_middle_icon" +                 width="140" /> +                <icon +                 follows="bottom|left" +                 height="25" +                 image_name="Toolbar_Right_Off" +                 layout="topleft" +                 left_pad="1" +                 name="dummy_right_icon" +                 width="31" />              </panel>          </layout_panel>      </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index fa4213667b..7e212c9383 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -16,13 +16,13 @@       value="No recent people. Looking for people to hang out with? Try [secondlife:///app/search/people Search] or the [secondlife:///app/worldmap World Map]." />      <string       name="no_filtered_recent_people" -     value="Didn't find what you're looking for? Try [secondlife:///app/search/people Search]." /> +     value="Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]." />      <string       name="no_one_near"       value="No one nearby. Looking for people to hang out with? Try [secondlife:///app/search/people Search] or the [secondlife:///app/worldmap World Map]." />      <string       name="no_one_filtered_near" -     value="Didn't find what you're looking for? Try [secondlife:///app/search/people Search]." /> +     value="Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]." />      <string       name="no_friends_online"       value="No friends online" /> @@ -36,7 +36,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M      </string>      <string       name="no_filtered_friends_msg"> -         Didn't find what you're looking for? Try [secondlife:///app/search/people Search]. +         Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search].      </string>      <string       name="people_filter_label" @@ -50,7 +50,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       -->      <string       name="no_filtered_groups_msg" -     value="Didn't find what you're looking for? Try [secondlife:///app/search/groups Search]." /> +     value="Didn't find what you're looking for? Try [secondlife:///app/search/groups/[SEARCH_TERM] Search]." />      <string       name="no_groups_msg"       value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." /> @@ -490,6 +490,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M           label="Share"           layout="topleft"           name="share_btn" +         tool_tip="Share an inventory item"           width="62" />          <button           follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 3ef16d2dec..ba967d3e2c 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -330,7 +330,7 @@      <check_box       enabled="false"       height="16" -     label="Enable plain text chat history" +     label="Enable plain text IM and chat history"       layout="topleft"       left_delta="0"       name="plain_text_chat_history" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index af87934c87..73df41b776 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1802,6 +1802,20 @@ Clears (deletes) the media and all params from the given face.  	<string name="alpha">Alpha</string>  	<string name="tattoo">Tattoo</string>  	<string name="invalid">invalid</string> +   +  <!-- Not Worn Wearable Types --> +	<string name="shirt_not_worn">Shirt not worn</string> +	<string name="pants_not_worn">Pants not worn</string> +	<string name="shoes_not_worn">Shoes not worn</string> +	<string name="socks_not_worn">Socks not worn</string> +	<string name="jacket_not_worn">Jacket not worn</string> +	<string name="gloves_not_worn">Gloves not worn</string> +	<string name="undershirt_not_worn">Undershirt not worn</string> +	<string name="underpants_not_worn">Underpants not worn</string> +	<string name="skirt_not_worn">Skirt not worn</string> +	<string name="alpha_not_worn">Alpha not worn</string> +	<string name="tattoo_not_worn">Tattoo not worn</string> +	<string name="invalid_not_worn">invalid</string>    <!-- Wearable List-->    <string name="NewWearable">New [WEARABLE_ITEM]</string> @@ -1842,7 +1856,8 @@ Clears (deletes) the media and all params from the given face.  	<string name="LeaveMouselook">Press ESC to return to World View</string>  	<!-- inventory --> -	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all Search].</string> +	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string> +	<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>  	<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>  	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>      <!-- use value="" because they have preceding spaces --> @@ -2951,8 +2966,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string> -	<string name="started_call">Started a voice call</string> -	<string name="joined_call">Joined the voice call</string> +	<string name="you_started_call">You started a voice call</string> +	<string name="you_joined_call">You joined the voice call</string> +	<string name="name_started_call">[NAME] started a voice call</string>    <string name="ringing-im">      Joining voice call... diff --git a/indra/newview/skins/default/xui/it/menu_participant_list.xml b/indra/newview/skins/default/xui/it/menu_participant_list.xml index e641d38508..0da1d116b4 100644 --- a/indra/newview/skins/default/xui/it/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/it/menu_participant_list.xml @@ -15,6 +15,6 @@  		<menu_item_call label="Disattiva audio di questo participante" name="ModerateVoiceMuteSelected"/>  		<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceMuteOthers"/>  		<menu_item_call label="Riattiva audio di questo participante" name="ModerateVoiceUnMuteSelected"/> -		<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/> +		<menu_item_call label="Riattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/>  	</context_menu>  </context_menu> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 6736c6a6f1..f1b87bc002 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -898,7 +898,7 @@ Unisci il terreno?  In genere si tratta di un problema temporaneo. Attendi alcuni minuti per modificare e salvare nuovamente gli elementi indossabili.  	</notification>  	<notification name="YouHaveBeenLoggedOut"> -		Accidenti. Sei stato scollegato da [SECOND_LIFE] +		Sei stato scollegato da [SECOND_LIFE].              [MESSAGE]  		<usetemplate name="okcancelbuttons" notext="Esci" yestext="Vedi IM & Chat"/>  	</notification> diff --git a/indra/newview/skins/default/xui/it/panel_edit_pick.xml b/indra/newview/skins/default/xui/it/panel_edit_pick.xml index d2d97cfc71..f93b953eac 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_pick.xml @@ -1,10 +1,10 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Modifica scelta" name="panel_edit_pick"> +<panel label="Modifica preferito" name="panel_edit_pick">  	<panel.string name="location_notice">  		(si aggiornerà dopo il salvataggio)  	</panel.string>  	<text name="title"> -		Modifica scelta +		Modifica preferito  	</text>  	<scroll_container name="profile_scroll">  		<panel name="scroll_content_panel"> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml index c24d3f656a..1d05f28d46 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml @@ -13,10 +13,10 @@  	</text>  	<check_box label="Costruire/Modificare" name="edit_camera_movement" tool_tip="Utilizza il posizionamento automatico della fotocamera entrando o uscendo dalla modalità modifica"/>  	<check_box label="Aspetto fisico" name="appearance_camera_movement" tool_tip="Utilizza il posizionamento automatico della camera in modalità modifica"/> -	<check_box label="Mostra in modalità Mouselook" name="first_person_avatar_visible"/> +	<check_box label="Visualizzami in modalità soggettiva" name="first_person_avatar_visible"/>  	<check_box label="Le frecce di direzione mi fanno sempre spostare" name="arrow_keys_move_avatar_check"/>  	<check_box label="Doppio click e tieni premuto per correre" name="tap_tap_hold_to_run"/> -	<check_box label="Consente il movimento delle labbra dell'avatar quando parla" name="enable_lip_sync"/> +	<check_box label="Movimento delle labbra dell'avatar quando parla" name="enable_lip_sync"/>  	<check_box label="Chat a bolla" name="bubble_text_chat"/>  	<slider label="Opacità" name="bubble_chat_opacity"/>  	<color_swatch name="background" tool_tip="Scegli il colore delle vignette della chat"/> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index a1b570d716..de9c5ba45b 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -886,13 +886,13 @@  		Alto  	</string>  	<string name="LeaveMouselook"> -		Premi ESC per tornare in visulizzazione normale +		Premi ESC per tornare in visualizzazione normale  	</string>  	<string name="InventoryNoMatchingItems">  		Nessun oggetto corrispondente trovato in inventario.  Prova [secondlife:///app/search/groups "Cerca"].  	</string>  	<string name="FavoritesNoMatchingItems"> -		Trascina qui un punto di riferimento per aggiungerlo ai tuoi preferiti. +		Trascina qui un punto di riferimento per aggiungerlo ai Preferiti.  	</string>  	<string name="InventoryNoTexture">  		Non hai una copia di questa texture nel tuo inventario @@ -1566,7 +1566,7 @@  		(si aggiornerà dopo la pubblicazione)  	</string>  	<string name="NoPicksClassifiedsText"> -		Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante più qui sotto per creare un luogo preferito o un'inserzione. +		Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante + qui sotto per creare un luogo preferito o un'inserzione.  	</string>  	<string name="NoAvatarPicksClassifiedsText">  		L'utente non ha luoghi preferiti né inserzioni diff --git a/indra/newview/skins/default/xui/it/teleport_strings.xml b/indra/newview/skins/default/xui/it/teleport_strings.xml index c11d41f6b9..7a1046abd3 100644 --- a/indra/newview/skins/default/xui/it/teleport_strings.xml +++ b/indra/newview/skins/default/xui/it/teleport_strings.xml @@ -66,7 +66,7 @@ Se si continua a visualizzare questo messaggio, consulta la pagina [SUPPORT_SITE  			Elaborazione della destinazione in corso...  		</message>  		<message name="contacting"> -			Contattando la nuova regione. +			Contatto in corso con la nuova regione.  		</message>  		<message name="arriving">  			In arrivo a destinazione... diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 044dbc9ed7..63437365f9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -341,6 +341,12 @@ class WindowsManifest(ViewerManifest):              self.path("media_plugin_webkit.dll")              self.end_prefix() +        # winmm.dll shim +        if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst="llplugin"): +            self.path("winmm.dll") +            self.end_prefix() + +          if self.args['configuration'].lower() == 'debug':              if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'debug'),                             dst="llplugin"): diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 7e9a8336e7..7a544debb2 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -241,6 +241,9 @@ LLMediaPluginTest::~LLMediaPluginTest()  	{  		remMediaPanel( mMediaPanels[ i ] );  	}; +	 +	// Stop the plugin read thread if it's running. +	LLPluginProcessParent::setUseReadThread(false);  }  //////////////////////////////////////////////////////////////////////////////// @@ -1047,6 +1050,11 @@ void LLMediaPluginTest::gluiCallback( int control_id )  		}  	}  	else +	if ( control_id == mIdUsePluginReadThread ) +	{ +		LLPluginProcessParent::setUseReadThread(mUsePluginReadThread); +	} +	else  	if ( control_id == mIdControlCrashPlugin )  	{  		// send message to plugin and ask it to crash @@ -1431,6 +1439,12 @@ void LLMediaPluginTest::makeChrome()  	glui_window_misc_control->set_main_gfx_window( mAppWindow );  	glui_window_misc_control->add_column( true ); +	mIdUsePluginReadThread = start_id++; +	mUsePluginReadThread = 0; +	glui_window_misc_control->add_checkbox( "Use plugin read thread", &mUsePluginReadThread, mIdUsePluginReadThread, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); +  	mIdLargePanelSpacing = start_id++;  	mLargePanelSpacing = 0;  	glui_window_misc_control->add_checkbox( "Large Panel Spacing", &mLargePanelSpacing, mIdLargePanelSpacing, gluiCallbackWrapper ); diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h index e7c7699343..5d08e42148 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.h +++ b/indra/test_apps/llplugintest/llmediaplugintest.h @@ -164,6 +164,8 @@ class LLMediaPluginTest : public LLPluginClassMediaOwner  		int mRandomBookmarks;  		int mIdDisableTimeout;  		int mDisableTimeout; +		int mIdUsePluginReadThread; +		int mUsePluginReadThread;  		int mIdLargePanelSpacing;  		int mLargePanelSpacing;  		int mIdControlCrashPlugin; | 
