Commits

Anonymous committed ba9624d Merge

Automated merge with file:///e:\code\viewer-experience

Comments (0)

Files changed (123)

 6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
 e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
+493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
+493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
+2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
+2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
 54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
+493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
+ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
 mesh-development.build_viewer_update_version_manager = false
 
 # ========================================
+# mesh-development-release-1-candidate
+# ========================================
+mesh-development-release-1-candidate.viewer_channel = "Project Viewer - Mesh"
+mesh-development-release-1-candidate.login_channel = "Project Viewer - Mesh"
+mesh-development-release-1-candidate.viewer_grid = agni
+mesh-development-release-1-candidate.build_debug_release_separately = true
+mesh-development-release-1-candidate.build_CYGWIN_Debug = false
+mesh-development-release-1-candidate.build_viewer_update_version_manager = false
+
+# ========================================
+# mesh-development-rc
+# ========================================
+mesh-development-rc.viewer_channel = "Project Viewer - Mesh"
+mesh-development-rc.login_channel = "Project Viewer - Mesh"
+mesh-development-rc.viewer_grid = agni
+mesh-development-rc.build_debug_release_separately = true
+mesh-development-rc.build_CYGWIN_Debug = false
+mesh-development-rc.build_viewer_update_version_manager = false
+
+# ========================================
 # mesh-asset-deprecation
 # ========================================
 mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation"
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d05be8fc196e9ce7b6636b931cf13dff</string>
+              <string>be7321370b69b6d66938b82a9230a067</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/226716/arch/Linux/installer/colladadom-2.2-linux-20110415.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/233450/arch/Linux/installer/colladadom-2.2-linux-20110621.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>6e45ad68506cd1ba49fd35a3201f0478</string>
+              <string>0db10480362168f075c2af0ae302cb74</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110504.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110707.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>00ff5144612c2e261a0811a4503ce3ba</string>
+              <string>f3c667dc159c0537a9122ce6e72e16db</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110504.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110707.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a4635dcbbe0915ce023dd41d3b848d4c</string>
+              <string>46cac4d667446bbbc9b5023f2848a5ac</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110504.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110707.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
         <key>license</key>
         <string>lgpl</string>
         <key>license_file</key>
-        <string>LICENSES/lgpl.txt</string>
+        <string>LICENSES/LLConvexDecompositionStubLicense.txt</string>
         <key>name</key>
         <string>llconvexdecompositionstub</string>
         <key>platforms</key>

indra/llcommon/llfasttimer_class.cpp

File contents unchanged.

indra/llcommon/llversionviewer.h

 
 const S32 LL_VERSION_MAJOR = 2;
 const S32 LL_VERSION_MINOR = 8;
-const S32 LL_VERSION_PATCH = 3;
+const S32 LL_VERSION_PATCH = 4;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";

indra/llcrashlogger/llcrashlogger.cpp

 
 bool LLCrashLogger::init()
 {
-	LLCurl::initClass();
+	LLCurl::initClass(false);
 
 	// We assume that all the logs we're looking for reside on the current drive
 	gDirUtilp->initAppDirs("SecondLife");

indra/llmath/llvolume.cpp

 #if !LL_WINDOWS
 #include <stdint.h>
 #endif
+#include <cmath>
 
 #include "llerror.h"
 #include "llmemtype.h"
 bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const
 {
 	bool retval = false;
-	if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord)
+
+	const F32 epsilon = 0.00001f;
+
+	if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && 
+		fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon &&
+		fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon)
 	{
 		if (angle_cutoff > 1.f)
 		{
-			retval = (mData[NORMAL].equals3(rhs.mData[NORMAL]));
+			retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon));
 		}
 		else
 		{
 			}
 
 			{
-				U16* n = (U16*) &(norm[0]);
-				if(n)
+				if (!norm.empty())
 				{
+					U16* n = (U16*) &(norm[0]);
 					for (U32 j = 0; j < num_verts; ++j)
 					{
 						norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]);
 						n += 3;
 					}
 				}
+				else
+				{
+					memset(norm_out, 0, sizeof(LLVector4a)*num_verts);
+				}
 			}
 
 			{
-				U16* t = (U16*) &(tc[0]);
-				if(t)
+				if (!tc.empty())
 				{
+					U16* t = (U16*) &(tc[0]);
 					for (U32 j = 0; j < num_verts; j+=2)
 					{
 						if (j < num_verts-1)
 						tc_out++;
 					}
 				}
+				else
+				{
+					memset(tc_out, 0, sizeof(LLVector2)*num_verts);
+				}
 			}
 
 			if (mdl[i].has("Weights"))
 					min.setMin(min, face.mPositions[i]);
 					max.setMax(max, face.mPositions[i]);
 				}
+
+				if (face.mTexCoords)
+				{
+					LLVector2& min_tc = face.mTexCoordExtents[0];
+					LLVector2& max_tc = face.mTexCoordExtents[1];
+
+					min_tc = face.mTexCoords[0];
+					max_tc = face.mTexCoords[0];
+
+					for (U32 j = 1; j < face.mNumVertices; ++j)
+					{
+						update_min_max(min_tc, max_tc, face.mTexCoords[j]);
+					}
+				}
+				else
+				{
+					face.mTexCoordExtents[0].set(0,0);
+					face.mTexCoordExtents[1].set(1,1);
+				}
 			}
 		}
 	}
 	n[2] = cv[2].getNormal();
 	n += 3;
 
-	tc[0] = cv[0].mTexCoord;
-	tc[1] = cv[1].mTexCoord;
-	tc[2] = cv[2].mTexCoord;
-	tc += 3;
-
+	if(tc)
+	{
+		tc[0] = cv[0].mTexCoord;
+		tc[1] = cv[1].mTexCoord;
+		tc[2] = cv[2].mTexCoord;
+		tc += 3;
+	}
 	
 	//side 2
 	cv[0].setPosition(p[3]);
 	n[2] = cv[2].getNormal();
 	n += 3;
 
-	tc[0] = cv[0].mTexCoord;
-	tc[1] = cv[1].mTexCoord;
-	tc[2] = cv[2].mTexCoord;
-	tc += 3;
-	
+	if(tc)
+	{
+		tc[0] = cv[0].mTexCoord;
+		tc[1] = cv[1].mTexCoord;
+		tc[2] = cv[2].mTexCoord;
+		tc += 3;
+	}
+
 	//side 3
 	cv[0].setPosition(p[3]);
 	cv[1].setPosition(p[1]);
 	n[2] = cv[2].getNormal();
 	n += 3;
 
-	tc[0] = cv[0].mTexCoord;
-	tc[1] = cv[1].mTexCoord;
-	tc[2] = cv[2].mTexCoord;
-	tc += 3;
+	if(tc)
+	{
+		tc[0] = cv[0].mTexCoord;
+		tc[1] = cv[1].mTexCoord;
+		tc[2] = cv[2].mTexCoord;
+		tc += 3;
+	}
 	
 	//side 4
 	cv[0].setPosition(p[2]);
 	n[2] = cv[2].getNormal();
 	n += 3;
 
-	tc[0] = cv[0].mTexCoord;
-	tc[1] = cv[1].mTexCoord;
-	tc[2] = cv[2].mTexCoord;
-	tc += 3;
+	if(tc)
+	{
+		tc[0] = cv[0].mTexCoord;
+		tc[1] = cv[1].mTexCoord;
+		tc[2] = cv[2].mTexCoord;
+		tc += 3;
+	}
 	
 	//set index buffer
 	for (U16 i = 0; i < 12; i++)
 			
 		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
 		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
-		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
+
+		if(src.mTexCoords)
+		{
+			LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
+		}
+		else
+		{
+			ll_aligned_free_16(mTexCoords) ;
+			mTexCoords = NULL ;
+		}
 
 
 		if (src.mBinormals)
 void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv)
 {
 	cv.setPosition(mPositions[index]);
-	cv.setNormal(mNormals[index]);
-	cv.mTexCoord = mTexCoords[index];
+	if (mNormals)
+	{
+		cv.setNormal(mNormals[index]);
+	}
+	else
+	{
+		cv.getNormal().clear();
+	}
+
+	if (mTexCoords)
+	{
+		cv.mTexCoord = mTexCoords[index];
+	}
+	else
+	{
+		cv.mTexCoord.clear();
+	}
 }
 
 bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const
 	LLVolumeFace new_face;
 
 	//map of points to vector of vertices at that point
-	VertexMapData::PointMap point_map;
+	std::map<U64, std::vector<VertexMapData> > point_map;
+
+	LLVector4a range;
+	range.setSub(mExtents[1],mExtents[0]);
 
 	//remove redundant vertices
 	for (U32 i = 0; i < mNumIndices; ++i)
 		getVertexData(index, cv);
 		
 		BOOL found = FALSE;
-		VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
+
+		LLVector4a pos;
+		pos.setSub(mPositions[index], mExtents[0]);
+		pos.div(range);
+
+		U64 pos64 = 0;
+
+		pos64 = (U16) (pos[0]*65535);
+		pos64 = pos64 | (((U64) (pos[1]*65535)) << 16);
+		pos64 = pos64 | (((U64) (pos[2]*65535)) << 32);
+
+		std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64);
+		
 		if (point_iter != point_map.end())
 		{ //duplicate point might exist
 			for (U32 j = 0; j < point_iter->second.size(); ++j)
 			}
 			else
 			{
-				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
-			}
-		}
+				point_map[pos64].push_back(d);
+			}
+		}
+	}
+
+	llassert(new_face.mNumIndices == mNumIndices);
+	llassert(new_face.mNumVertices <= mNumVertices);
+
+	if (angle_cutoff > 1.f && !mNormals)
+	{
+		ll_aligned_free_16(new_face.mNormals);
+		new_face.mNormals = NULL;
+	}
+
+	if (!mTexCoords)
+	{
+		ll_aligned_free_16(new_face.mTexCoords);
+		new_face.mTexCoords = NULL;
 	}
 
 	swapData(new_face);

indra/llmessage/llcurl.cpp

  * $/LicenseInfo$
  */
 
+
 #if LL_WINDOWS
 #define SAFE_SSL 1
 #elif LL_DARWIN
 static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds
 static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
 
+static 
 // DEBUG //
 S32 gCurlEasyCount = 0;
 S32 gCurlMultiCount = 0;
 std::string LLCurl::sCAPath;
 std::string LLCurl::sCAFile;
 
+bool LLCurl::sMultiThreaded = false;
+static U32 sMainThreadID = 0;
+
 void check_curl_code(CURLcode code)
 {
 	if (code != CURLE_OK)
 	U32 report(CURLcode);
 	void getTransferInfo(LLCurl::TransferInfo* info);
 
-	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false);
+	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false);
 	
 	const char* getErrorBuffer();
 
 
 void LLCurl::Easy::prepRequest(const std::string& url,
 							   const std::vector<std::string>& headers,
-							   ResponderPtr responder, bool post)
+							   ResponderPtr responder, S32 time_out, bool post)
 {
 	resetState();
 	
 	
 	//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
 	setopt(CURLOPT_SSL_VERIFYHOST, 0);
-	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
+	setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
 
 	setoptString(CURLOPT_URL, url);
 
 
 	S32 process();
 	void perform();
+	void doPerform();
 	
 	virtual void run();
 
 
 	LLCondition* mSignal;
 	bool mQuitting;
+	bool mThreaded;
 
 private:
 	void easyFree(Easy*);
 	  mPerformState(PERFORM_STATE_READY)
 {
 	mQuitting = false;
-	mSignal = new LLCondition(NULL);
+
+	mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID;
+	if (mThreaded)
+	{
+		mSignal = new LLCondition(NULL);
+	}
+	else
+	{
+		mSignal = NULL;
+	}
 
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
 
 void LLCurl::Multi::perform()
 {
-	if (mPerformState == PERFORM_STATE_READY)
+	if (mThreaded)
 	{
-		mSignal->signal();
+		if (mPerformState == PERFORM_STATE_READY)
+		{
+			mSignal->signal();
+		}
+	}
+	else
+	{
+		doPerform();
 	}
 }
 
 void LLCurl::Multi::run()
 {
+	llassert(mThreaded);
+
 	while (!mQuitting)
 	{
 		mSignal->wait();
 		mPerformState = PERFORM_STATE_PERFORMING;
 		if (!mQuitting)
 		{
-			S32 q = 0;
-			for (S32 call_count = 0;
-				 call_count < MULTI_PERFORM_CALL_REPEAT;
-				 call_count += 1)
-			{
-				CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
-				if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
-				{
-					check_curl_multi_code(code);
-					break;
-				}
-	
-			}
-			mQueued = q;
-			mPerformState = PERFORM_STATE_COMPLETED;
+			doPerform();
 		}
 	}
 }
 
+void LLCurl::Multi::doPerform()
+{
+	S32 q = 0;
+	for (S32 call_count = 0;
+			call_count < MULTI_PERFORM_CALL_REPEAT;
+			call_count += 1)
+	{
+		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
+		if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+		{
+			check_curl_multi_code(code);
+			break;
+		}
+	
+	}
+	mQueued = q;
+	mPerformState = PERFORM_STATE_COMPLETED;
+}
+
 S32 LLCurl::Multi::process()
 {
 	perform();
 	{
 		LLCurl::Multi* multi = *iter;
 		multi->mQuitting = true;
-		while (!multi->isStopped())
+		if (multi->mThreaded)
 		{
-			multi->mSignal->signal();
-			apr_sleep(1000);
+			while (!multi->isStopped())
+			{
+				multi->mSignal->signal();
+				apr_sleep(1000);
+			}
 		}
 	}
 	for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
 {
 	llassert_always(mThreadID == LLThread::currentID());
 	LLCurl::Multi* multi = new LLCurl::Multi();
-	multi->start();
+	if (multi->mThreaded)
+	{
+		multi->start();
+	}
 	mMultiSet.insert(multi);
 	mActiveMulti = multi;
 	mActiveRequestCount = 0;
 bool LLCurlRequest::post(const std::string& url,
 						 const headers_t& headers,
 						 const LLSD& data,
-						 LLCurl::ResponderPtr responder)
+						 LLCurl::ResponderPtr responder, S32 time_out)
 {
 	LLCurl::Easy* easy = allocEasy();
 	if (!easy)
 	{
 		return false;
 	}
-	easy->prepRequest(url, headers, responder);
+	easy->prepRequest(url, headers, responder, time_out);
 
 	LLSDSerialize::toXML(data, easy->getInput());
 	S32 bytes = easy->getInput().str().length();
 bool LLCurlRequest::post(const std::string& url,
 						 const headers_t& headers,
 						 const std::string& data,
-						 LLCurl::ResponderPtr responder)
+						 LLCurl::ResponderPtr responder, S32 time_out)
 {
 	LLCurl::Easy* easy = allocEasy();
 	if (!easy)
 	{
 		return false;
 	}
-	easy->prepRequest(url, headers, responder);
+	easy->prepRequest(url, headers, responder, time_out);
 
 	easy->getInput().write(data.data(), data.size());
 	S32 bytes = easy->getInput().str().length();
 		{
 			mMultiSet.erase(curiter);
 			multi->mQuitting = true;
-			while (!multi->isStopped())
+			if (multi->mThreaded)
 			{
-				multi->mSignal->signal();
-				apr_sleep(1000);
+				while (!multi->isStopped())
+				{
+					multi->mSignal->signal();
+					apr_sleep(1000);
+				}
 			}
 
 			delete multi;
 		curlmulti_set_t::iterator curiter = iter++;
 		LLCurl::Multi* multi = *curiter;
 		queued += multi->mQueued;
+		if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY)
+		{
+			++queued;
+		}
 	}
 	return queued;
 }
 	  mResultReturned(false)
 {
 	mMulti = new LLCurl::Multi();
-	mMulti->start();
+	if (mMulti->mThreaded)
+	{
+		mMulti->start();
+	}
 	mEasy = mMulti->allocEasy();
 	if (mEasy)
 	{
 LLCurlEasyRequest::~LLCurlEasyRequest()
 {
 	mMulti->mQuitting = true;
-	while (!mMulti->isStopped())
+	if (mMulti->mThreaded)
 	{
-		mMulti->mSignal->signal();
-		apr_sleep(1000);
+		while (!mMulti->isStopped())
+		{
+			mMulti->mSignal->signal();
+			apr_sleep(1000);
+		}
 	}
 	delete mMulti;
 }
 }
 #endif
 
-void LLCurl::initClass()
+void LLCurl::initClass(bool multi_threaded)
 {
+	sMainThreadID = LLThread::currentID();
+	sMultiThreaded = multi_threaded;
 	// Do not change this "unless you are familiar with and mean to control 
 	// internal operations of libcurl"
 	// - http://curl.haxx.se/libcurl/c/curl_global_init.html

indra/llmessage/llcurl.h

 #include "llbuffer.h"
 #include "lliopipe.h"
 #include "llsd.h"
+#include "llthread.h"
 
 class LLMutex;
 
 	class Easy;
 	class Multi;
 
+	static bool sMultiThreaded;
+
 	struct TransferInfo
 	{
 		TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
 	/**
 	 * @ brief Initialize LLCurl class
 	 */
-	static void initClass();
+	static void initClass(bool multi_threaded = false);
 
 	/**
 	 * @ brief Cleanup LLCurl class
 
 	void get(const std::string& url, LLCurl::ResponderPtr responder);
 	bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
-	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
-	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder);
+	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
+	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
 	
 	S32  process();
 	S32  getQueued();

indra/llplugin/llpluginclassmedia.cpp

-/** 
- * @file llpluginclassmedia.cpp
- * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llpluginclassmedia.h"
-#include "llpluginmessageclasses.h"
-
-#include "llqtwebkit.h"
-
-static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
-
-static int nextPowerOf2( int value )
-{
-	int next_power_of_2 = 1;
-	while ( next_power_of_2 < value )
-	{
-		next_power_of_2 <<= 1;
-	}
-	
-	return next_power_of_2;
-}
-
-LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
-{
-	mOwner = owner;
-	mPlugin = NULL;
-	reset();
-
-	//debug use
-	mDeleteOK = true ;
-}
-
-
-LLPluginClassMedia::~LLPluginClassMedia()
-{
-	llassert_always(mDeleteOK) ;
-	reset();
-}
-
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{	
-	LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
-	LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
-	LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-	
-	mPlugin = new LLPluginProcessParent(this);
-	mPlugin->setSleepTime(mSleepTime);
-	
-	// Queue up the media init message -- it will be sent after all the currently queued messages.
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
-	message.setValue("target", mTarget);
-	sendMessage(message);
-	
-	mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
-
-	return true;
-}
-
-
-void LLPluginClassMedia::reset()
-{
-	if(mPlugin != NULL)
-	{
-		delete mPlugin;
-		mPlugin = NULL;
-	}
-
-	mTextureParamsReceived = false;
-	mRequestedTextureDepth = 0;
-	mRequestedTextureInternalFormat = 0;
-	mRequestedTextureFormat = 0;
-	mRequestedTextureType = 0;
-	mRequestedTextureSwapBytes = false;
-	mRequestedTextureCoordsOpenGL = false;
-	mTextureSharedMemorySize = 0;
-	mTextureSharedMemoryName.clear();
-	mDefaultMediaWidth = 0;
-	mDefaultMediaHeight = 0;
-	mNaturalMediaWidth = 0;
-	mNaturalMediaHeight = 0;
-	mSetMediaWidth = -1;
-	mSetMediaHeight = -1;
-	mRequestedMediaWidth = 0;
-	mRequestedMediaHeight = 0;
-	mRequestedTextureWidth = 0;
-	mRequestedTextureHeight = 0;
-	mFullMediaWidth = 0;
-	mFullMediaHeight = 0;
-	mTextureWidth = 0;
-	mTextureHeight = 0;
-	mMediaWidth = 0;
-	mMediaHeight = 0;
-	mDirtyRect = LLRect::null;	
-	mAutoScaleMedia = false;
-	mRequestedVolume = 1.0f;
-	mPriority = PRIORITY_NORMAL;
-	mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
-	mAllowDownsample = false;
-	mPadding = 0;
-	mLastMouseX = 0;
-	mLastMouseY = 0;
-	mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
-	mSleepTime = 1.0f / 100.0f;
-	mCanCut = false;
-	mCanCopy = false;
-	mCanPaste = false;
-	mMediaName.clear();
-	mMediaDescription.clear();
-	mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-	
-	// media_browser class
-	mNavigateURI.clear();
-	mNavigateResultCode = -1;
-	mNavigateResultString.clear();
-	mHistoryBackAvailable = false;
-	mHistoryForwardAvailable = false;
-	mStatusText.clear();
-	mProgressPercent = 0;	
-	mClickURL.clear();
-	mClickNavType.clear();
-	mClickTarget.clear();
-	mClickUUID.clear();
-	mStatusCode = 0;
-	
-	// media_time class
-	mCurrentTime = 0.0f;
-	mDuration = 0.0f;
-	mCurrentRate = 0.0f;
-	mLoadedDuration = 0.0f;
-}
-
-void LLPluginClassMedia::idle(void)
-{
-	if(mPlugin)
-	{
-		mPlugin->idle();
-	}
-	
-	if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
-	{
-		// Can't process a size change at this time
-	}
-	else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
-	{
-		// Calculate the correct size for the media texture
-		mRequestedTextureHeight = mRequestedMediaHeight;
-		if(mPadding < 0)
-		{
-			// negative values indicate the plugin wants a power of 2
-			mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
-		}
-		else
-		{
-			mRequestedTextureWidth = mRequestedMediaWidth;
-			
-			if(mPadding > 1)
-			{
-				// Pad up to a multiple of the specified number of bytes per row
-				int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
-				int pad = rowbytes % mPadding;
-				if(pad != 0)
-				{
-					rowbytes += mPadding - pad;
-				}
-				
-				if(rowbytes % mRequestedTextureDepth == 0)
-				{
-					mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
-				}
-				else
-				{
-					LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
-				}
-			}
-		}
-
-		
-		// Size change has been requested but not initiated yet.
-		size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
-		// Add an extra line for padding, just in case.
-		newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
-		if(newsize != mTextureSharedMemorySize)
-		{
-			if(!mTextureSharedMemoryName.empty())
-			{
-				// Tell the plugin to remove the old memory segment
-				mPlugin->removeSharedMemory(mTextureSharedMemoryName);
-				mTextureSharedMemoryName.clear();
-			}
-			
-			mTextureSharedMemorySize = newsize;
-			mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
-			if(!mTextureSharedMemoryName.empty())
-			{
-				void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-				
-				// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
-				memset( addr, 0x00, newsize );
-				
-				// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
-				// so it may not be worthwhile.
-				// mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
-			}
-		}
-		
-		// This is our local indicator that a change is in progress.
-		mTextureWidth = -1;
-		mTextureHeight = -1;
-		mMediaWidth = -1;
-		mMediaHeight = -1;
-
-		// This invalidates any existing dirty rect.
-		resetDirty();
-		
-		// Send a size change message to the plugin
-		{
-			LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
-			message.setValue("name", mTextureSharedMemoryName);
-			message.setValueS32("width", mRequestedMediaWidth);
-			message.setValueS32("height", mRequestedMediaHeight);
-			message.setValueS32("texture_width", mRequestedTextureWidth);
-			message.setValueS32("texture_height", mRequestedTextureHeight);
-			message.setValueReal("background_r", mBackgroundColor.mV[VX]);
-			message.setValueReal("background_g", mBackgroundColor.mV[VY]);
-			message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
-			message.setValueReal("background_a", mBackgroundColor.mV[VW]);
-			mPlugin->sendMessage(message);	// DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-			
-			LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
-		}
-	}
-	
-	if(mPlugin && mPlugin->isRunning())
-	{
-		// Send queued messages
-		while(!mSendQueue.empty())
-		{
-			LLPluginMessage message = mSendQueue.front();
-			mSendQueue.pop();
-			mPlugin->sendMessage(message);
-		}
-	}
-}
-
-int LLPluginClassMedia::getTextureWidth() const
-{
-	return nextPowerOf2(mTextureWidth);
-}
-
-int LLPluginClassMedia::getTextureHeight() const
-{
-	return nextPowerOf2(mTextureHeight);
-}
-
-unsigned char* LLPluginClassMedia::getBitsData()
-{
-	unsigned char *result = NULL;
-	if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
-	{
-		result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-	}
-	return result;
-}
-
-void LLPluginClassMedia::setSize(int width, int height)
-{
-	if((width > 0) && (height > 0))
-	{
-		mSetMediaWidth = width;
-		mSetMediaHeight = height;
-	}
-	else
-	{
-		mSetMediaWidth = -1;
-		mSetMediaHeight = -1;
-	}
-
-	setSizeInternal();
-}
-
-void LLPluginClassMedia::setSizeInternal(void)
-{
-	if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
-	{
-		mRequestedMediaWidth = mSetMediaWidth;
-		mRequestedMediaHeight = mSetMediaHeight;
-	}
-	else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
-	{
-		mRequestedMediaWidth = mNaturalMediaWidth;
-		mRequestedMediaHeight = mNaturalMediaHeight;
-	}
-	else
-	{
-		mRequestedMediaWidth = mDefaultMediaWidth;
-		mRequestedMediaHeight = mDefaultMediaHeight;
-	}
-	
-	// Save these for size/interest calculations
-	mFullMediaWidth = mRequestedMediaWidth;
-	mFullMediaHeight = mRequestedMediaHeight;
-	
-	if(mAllowDownsample)
-	{
-		switch(mPriority)
-		{
-			case PRIORITY_SLIDESHOW:
-			case PRIORITY_LOW:
-				// Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
-				while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
-				{
-					mRequestedMediaWidth /= 2;
-					mRequestedMediaHeight /= 2;
-				}
-			break;
-			
-			default:
-				// Don't adjust texture size
-			break;
-		}
-	}
-	
-	if(mAutoScaleMedia)
-	{
-		mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
-		mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
-	}
-	
-	if(mRequestedMediaWidth > 2048)
-		mRequestedMediaWidth = 2048;
-
-	if(mRequestedMediaHeight > 2048)
-		mRequestedMediaHeight = 2048;
-}
-
-void LLPluginClassMedia::setAutoScale(bool auto_scale)
-{
-	if(auto_scale != mAutoScaleMedia)
-	{
-		mAutoScaleMedia = auto_scale;
-		setSizeInternal();
-	}
-}
-
-bool LLPluginClassMedia::textureValid(void)
-{
-	if(
-		!mTextureParamsReceived ||
-		mTextureWidth <= 0 ||
-		mTextureHeight <= 0 ||
-		mMediaWidth <= 0 ||
-		mMediaHeight <= 0 ||
-		mRequestedMediaWidth != mMediaWidth ||
-		mRequestedMediaHeight != mMediaHeight ||
-		getBitsData() == NULL
-	)	
-		return false;
-	
-	return true;
-}
-
-bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
-{
-	bool result = !mDirtyRect.isEmpty();
-
-	if(dirty_rect != NULL)
-	{
-		*dirty_rect = mDirtyRect;
-	}
-
-	return result;
-}
-
-void LLPluginClassMedia::resetDirty(void)
-{
-	mDirtyRect = LLRect::null;
-}
-
-std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
-{
-	std::string result;
-	
-	
-	if(modifiers & MASK_CONTROL)
-	{
-		result += "control|";
-	}
-
-	if(modifiers & MASK_ALT)
-	{
-		result += "alt|";
-	}
-
-	if(modifiers & MASK_SHIFT)
-	{
-		result += "shift|";
-	}
-
-	// TODO: should I deal with platform differences here or in callers?
-	// TODO: how do we deal with the Mac "command" key?
-/*
-	if(modifiers & MASK_SOMETHING)
-	{
-		result += "meta|";
-	}
-*/	
-	return result;
-}
-
-void LLPluginClassMedia::jsEnableObject( bool enable )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
-	message.setValueBoolean( "enable", enable );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
-	message.setValueReal( "x", x );
-	message.setValueReal( "y", y );
-	message.setValueReal( "z", z );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
-	message.setValueReal( "x", x );
-	message.setValueReal( "y", y );
-	message.setValueReal( "z", z );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
-	message.setValueReal( "angle", angle );
-
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
-	message.setValue( "language", language );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
-	message.setValue( "region", region );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
-{
-	if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
-	{
-		return;
-	}
-
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
-	message.setValue( "maturity", maturity );
-	sendMessage( message );
-}
-
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
-{
-	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.
-			return;
-		}
-		
-		mLastMouseX = x;
-		mLastMouseY = y;
-	}
-	
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
-	std::string temp;
-	switch(type)
-	{
-		case MOUSE_EVENT_DOWN:			temp = "down";			break;
-		case MOUSE_EVENT_UP:			temp = "up";			break;
-		case MOUSE_EVENT_MOVE:			temp = "move";			break;
-		case MOUSE_EVENT_DOUBLE_CLICK:	temp = "double_click";	break;
-	}
-	message.setValue("event", temp);
-
-	message.setValueS32("button", button);
-
-	message.setValueS32("x", x);
-	
-	// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
-	if(!mRequestedTextureCoordsOpenGL)
-	{
-		// TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
-		y = mMediaHeight - y;
-	}
-	message.setValueS32("y", y);
-
-	message.setValue("modifiers", translateModifiers(modifiers));
-	
-	sendMessage(message);
-}
-
-bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
-{
-	bool result = true;
-	
-	// FIXME:
-	// HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
-	// For now, return false for the ones the webkit plugin won't handle properly.
-	
-	switch(key_code)
-	{
-		case KEY_BACKSPACE:		
-		case KEY_TAB:			
-		case KEY_RETURN:		
-		case KEY_PAD_RETURN:	
-		case KEY_SHIFT:			
-		case KEY_CONTROL:		
-		case KEY_ALT:			
-		case KEY_CAPSLOCK:		
-		case KEY_ESCAPE:		
-		case KEY_PAGE_UP:		
-		case KEY_PAGE_DOWN:		
-		case KEY_END:			
-		case KEY_HOME:			
-		case KEY_LEFT:			
-		case KEY_UP:			
-		case KEY_RIGHT:			
-		case KEY_DOWN:			
-		case KEY_INSERT:		
-		case KEY_DELETE:
-			// These will be handled		
-		break;
-		
-		default:
-			// regular ASCII characters will also be handled
-			if(key_code >= KEY_SPECIAL)
-			{
-				// Other "special" codes will not work properly.
-				result = false;
-			}
-		break;
-	}
-
-#if LL_DARWIN	
-	if(modifiers & MASK_ALT)
-	{
-		// Option-key modified characters should be handled by the unicode input path instead of this one.
-		result = false;
-	}
-#endif
-
-	if(result)
-	{
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
-		std::string temp;
-		switch(type)
-		{
-			case KEY_EVENT_DOWN:			temp = "down";			break;
-			case KEY_EVENT_UP:				temp = "up";			break;
-			case KEY_EVENT_REPEAT:			temp = "repeat";		break;
-		}
-		message.setValue("event", temp);
-		
-		message.setValueS32("key", key_code);
-
-		message.setValue("modifiers", translateModifiers(modifiers));
-		message.setValueLLSD("native_key_data", native_key_data);
-		
-		sendMessage(message);
-	}
-		
-	return result;
-}
-
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
-
-	message.setValueS32("x", x);
-	message.setValueS32("y", y);
-	message.setValue("modifiers", translateModifiers(modifiers));
-	
-	sendMessage(message);
-}
-	
-bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
-
-	message.setValue("text", text);
-	message.setValue("modifiers", translateModifiers(modifiers));
-	message.setValueLLSD("native_key_data", native_key_data);
-	
-	sendMessage(message);
-	
-	return true;
-}
-
-void LLPluginClassMedia::loadURI(const std::string &uri)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
-
-	message.setValue("uri", uri);
-	
-	sendMessage(message);
-}
-
-const char* LLPluginClassMedia::priorityToString(EPriority priority)
-{
-	const char* result = "UNKNOWN";
-	switch(priority)
-	{
-		case PRIORITY_UNLOADED:		result = "unloaded";	break;
-		case PRIORITY_STOPPED:		result = "stopped";		break;
-		case PRIORITY_HIDDEN:		result = "hidden";		break;
-		case PRIORITY_SLIDESHOW:	result = "slideshow";	break;
-		case PRIORITY_LOW:			result = "low";			break;
-		case PRIORITY_NORMAL:		result = "normal";		break;
-		case PRIORITY_HIGH:			result = "high";		break;
-	}
-	
-	return result;
-}
-
-void LLPluginClassMedia::setPriority(EPriority priority)
-{
-	if(mPriority != priority)
-	{
-		mPriority = priority;
-
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-		
-		std::string priority_string = priorityToString(priority);
-		switch(priority)
-		{
-			case PRIORITY_UNLOADED:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_STOPPED:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_HIDDEN:	
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_SLIDESHOW:
-				mSleepTime = 1.0f;
-			break;
-			case PRIORITY_LOW:		
-				mSleepTime = 1.0f / 25.0f;
-			break;
-			case PRIORITY_NORMAL:	
-				mSleepTime = 1.0f / 50.0f;
-			break;
-			case PRIORITY_HIGH:		
-				mSleepTime = 1.0f / 100.0f;
-			break;
-		}
-		
-		message.setValue("priority", priority_string);
-
-		sendMessage(message);
-		
-		if(mPlugin)
-		{
-			mPlugin->setSleepTime(mSleepTime);
-		}
-		
-		LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-		
-		// This may affect the calculated size, so recalculate it here.
-		setSizeInternal();
-	}
-}
-
-void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
-{
-	int power = nextPowerOf2(size);
-	if(mLowPrioritySizeLimit != power)
-	{
-		mLowPrioritySizeLimit = power;
-
-		// This may affect the calculated size, so recalculate it here.
-		setSizeInternal();
-	}
-}
-
-F64 LLPluginClassMedia::getCPUUsage()
-{
-	F64 result = 0.0f;
-	
-	if(mPlugin)
-	{
-		result = mPlugin->getCPUUsage();
-	}
-	
-	return result;
-}
-
-void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
-	message.setValue("file", file);
-	if(mPlugin && mPlugin->isBlocked())
-	{
-		// If the plugin sent a blocking pick-file request, the response should unblock it.
-		message.setValueBoolean("blocking_response", true);
-	}
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
-	message.setValueBoolean("ok", ok);
-	message.setValue("username", username);
-	message.setValue("password", password);
-	if(mPlugin && mPlugin->isBlocked())
-	{
-		// If the plugin sent a blocking pick-file request, the response should unblock it.
-		message.setValueBoolean("blocking_response", true);
-	}
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::cut()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::copy()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::paste()
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
-	message.setValue("path", user_data_path);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
-	message.setValue("language", language_code);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
-	message.setValueBoolean("enable", enabled);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
-	message.setValueBoolean("enable", enabled);
-	sendMessage(message);
-}
-
-void LLPluginClassMedia::setTarget(const std::string &target)
-{
-	mTarget = target;
-}
-
-/* virtual */ 
-void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
-{
-	std::string message_class = message.getClass();
-	
-	if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
-	{
-		std::string message_name = message.getName();
-		if(message_name == "texture_params")
-		{
-			mRequestedTextureDepth = message.getValueS32("depth");
-			mRequestedTextureInternalFormat = message.getValueU32("internalformat");
-			mRequestedTextureFormat = message.getValueU32("format");
-			mRequestedTextureType = message.getValueU32("type");
-			mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
-			mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");			
-			
-			// These two are optional, and will default to 0 if they're not specified.
-			mDefaultMediaWidth = message.getValueS32("default_width");
-			mDefaultMediaHeight = message.getValueS32("default_height");
-			
-			mAllowDownsample = message.getValueBoolean("allow_downsample");
-			mPadding = message.getValueS32("padding");
-
-			setSizeInternal();
-			
-			mTextureParamsReceived = true;
-		}
-		else if(message_name == "updated")
-		{			
-			if(message.hasValue("left"))
-			{
-				LLRect newDirtyRect;
-				newDirtyRect.mLeft = message.getValueS32("left");
-				newDirtyRect.mTop = message.getValueS32("top");
-				newDirtyRect.mRight = message.getValueS32("right");
-				newDirtyRect.mBottom = message.getValueS32("bottom");
-							
-				// The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
-				// If they're backwards, swap them.
-				if(newDirtyRect.mTop < newDirtyRect.mBottom)
-				{
-					S32 temp = newDirtyRect.mTop;
-					newDirtyRect.mTop = newDirtyRect.mBottom;
-					newDirtyRect.mBottom = temp;
-				}
-				
-				if(mDirtyRect.isEmpty())
-				{
-					mDirtyRect = newDirtyRect;
-				}
-				else
-				{
-					mDirtyRect.unionWith(newDirtyRect);
-				}
-
-				LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" 
-					<< newDirtyRect.mLeft << ", "
-					<< newDirtyRect.mTop << ", "
-					<< newDirtyRect.mRight << ", "
-					<< newDirtyRect.mBottom << "), new dirty rect is: ("
-					<< mDirtyRect.mLeft << ", "
-					<< mDirtyRect.mTop << ", "
-					<< mDirtyRect.mRight << ", "
-					<< mDirtyRect.mBottom << ")"
-					<< LL_ENDL;
-				
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
-			}			
-			
-
-			bool time_duration_updated = false;
-			int previous_percent = mProgressPercent;
-
-			if(message.hasValue("current_time"))
-			{
-				mCurrentTime = message.getValueReal("current_time");
-				time_duration_updated = true;
-			}
-			if(message.hasValue("duration"))
-			{
-				mDuration = message.getValueReal("duration");
-				time_duration_updated = true;
-			}
-
-			if(message.hasValue("current_rate"))
-			{
-				mCurrentRate = message.getValueReal("current_rate");
-			}
-			
-			if(message.hasValue("loaded_duration"))
-			{
-				mLoadedDuration = message.getValueReal("loaded_duration");
-				time_duration_updated = true;
-			}
-			else
-			{
-				// If the message doesn't contain a loaded_duration param, assume it's equal to duration
-				mLoadedDuration = mDuration;
-			}
-			
-			// Calculate a percentage based on the loaded duration and total duration.
-			if(mDuration != 0.0f)	// Don't divide by zero.
-			{
-				mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
-			}
-
-			if(time_duration_updated)
-			{
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
-			}
-			
-			if(previous_percent != mProgressPercent)
-			{
-				mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
-			}
-		}
-		else if(message_name == "media_status")
-		{
-			std::string status = message.getValue("status");
-			
-			LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-			
-			if(status == "loading")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
-			}
-			else if(status == "loaded")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
-			}
-			else if(status == "error")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
-			}
-			else if(status == "playing")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
-			}
-			else if(status == "paused")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
-			}
-			else if(status == "done")
-			{
-				mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
-			}
-			else
-			{
-				// empty string or any unknown string
-				mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
-			}
-		}
-		else if(message_name == "size_change_request")
-		{
-			S32 width = message.getValueS32("width");
-			S32 height = message.getValueS32("height");
-			std::string name = message.getValue("name");
-
-			// TODO: check that name matches?
-			mNaturalMediaWidth = width;
-			mNaturalMediaHeight = height;
-			
-			setSizeInternal();
-		}
-		else if(message_name == "size_change_response")
-		{
-			std::string name = message.getValue("name");
-			
-			// TODO: check that name matches?
-			
-			mTextureWidth = message.getValueS32("texture_width");
-			mTextureHeight = message.getValueS32("texture_height");
-			mMediaWidth = message.getValueS32("width");
-			mMediaHeight = message.getValueS32("height");
-			
-			// This invalidates any existing dirty rect.
-			resetDirty();
-			
-			// TODO: should we verify that the plugin sent back the right values?  
-			// Two size changes in a row may cause them to not match, due to queueing, etc.
-
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
-		}
-		else if(message_name == "cursor_changed")
-		{
-			mCursorName = message.getValue("name");
-
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
-		}
-		else if(message_name == "edit_state")
-		{
-			if(message.hasValue("cut"))
-			{
-				mCanCut = message.getValueBoolean("cut");
-			}
-			if(message.hasValue("copy"))
-			{
-				mCanCopy = message.getValueBoolean("copy");
-			}
-			if(message.hasValue("paste"))
-			{
-				mCanPaste = message.getValueBoolean("paste");
-			}
-		}
-		else if(message_name == "name_text")
-		{
-			mMediaName = message.getValue("name");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
-		}
-		else if(message_name == "pick_file")
-		{
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
-		}
-		else if(message_name == "auth_request")
-		{
-			mAuthURL = message.getValue("url");
-			mAuthRealm = message.getValue("realm");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
-		}
-		else
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
-	{
-		std::string message_name = message.getName();
-		if(message_name == "navigate_begin")
-		{
-			mNavigateURI = message.getValue("uri");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
-		}
-		else if(message_name == "navigate_complete")
-		{
-			mNavigateURI = message.getValue("uri");
-			mNavigateResultCode = message.getValueS32("result_code");
-			mNavigateResultString = message.getValue("result_string");
-			mHistoryBackAvailable = message.getValueBoolean("history_back_available");
-			mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-			
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
-		}
-		else if(message_name == "progress")
-		{
-			mProgressPercent = message.getValueS32("percent");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
-		}
-		else if(message_name == "status_text")
-		{
-			mStatusText = message.getValue("status");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
-		}
-		else if(message_name == "location_changed")
-		{
-			mLocation = message.getValue("uri");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
-		}
-		else if(message_name == "click_href")
-		{
-			mClickURL = message.getValue("uri");
-			mClickTarget = message.getValue("target");
-			mClickUUID = message.getValue("uuid");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
-		}
-		else if(message_name == "click_nofollow")
-		{
-			mClickURL = message.getValue("uri");
-			mClickNavType = message.getValue("nav_type");
-			mClickTarget.clear();
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
-		}
-		else if(message_name == "navigate_error_page")
-		{
-			mStatusCode = message.getValueS32("status_code");
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
-		}
-		else if(message_name == "cookie_set")
-		{
-			if(mOwner)
-			{
-				mOwner->handleCookieSet(this, message.getValue("cookie"));
-			}
-		}
-		else if(message_name == "close_request")
-		{
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
-		}
-		else if(message_name == "geometry_change")
-		{
-			mClickUUID = message.getValue("uuid");
-			mGeometryX = message.getValueS32("x");
-			mGeometryY = message.getValueS32("y");
-			mGeometryWidth = message.getValueS32("width");
-			mGeometryHeight = message.getValueS32("height");
-				
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
-		}
-		else if(message_name == "link_hovered")
-		{
-			// text is not currently used -- the tooltip hover text is taken from the "title".
-			mHoverLink = message.getValue("link");
-			mHoverText = message.getValue("title");
-			// message.getValue("text");
-				
-			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
-		}
-		else
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-	else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
-	{
-		std::string message_name = message.getName();
-
-		// This class hasn't defined any incoming messages yet.
-//		if(message_name == "message_name")
-//		{
-//		}
-//		else 
-		{
-			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
-		}
-	}
-
-}
-
-/* virtual */ 
-void LLPluginClassMedia::pluginLaunchFailed()
-{
-	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
-}
-
-/* virtual */ 
-void LLPluginClassMedia::pluginDied()
-{
-	mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
-}
-
-void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
-{
-	if(mOwner)
-	{
-		mOwner->handleMediaEvent(this, event);
-	}
-}
-
-void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
-{
-	if(mPlugin && mPlugin->isRunning())
-	{
-		mPlugin->sendMessage(message);
-	}
-	else
-	{
-		// The plugin isn't set up yet -- queue this message to be sent after initialization.
-		mSendQueue.push(message);
-	}
-}
-
-////////////////////////////////////////////////////////////
-// MARK: media_browser class functions
-bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
-{
-	std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
-	return !version.empty();
-}
-
-void LLPluginClassMedia::focus(bool focused)
-{
-	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus&qu