diff options
30 files changed, 2306 insertions, 1908 deletions
| diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 2a343fd0c9..fc58b48a7b 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -835,6 +835,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)  				mCanPaste = message.getValueBoolean("paste");  			}  		} +		else if(message_name == "name_text") +		{ +			mMediaName = message.getValue("name"); +			mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); +		}  		else  		{  			LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index cfee847080..4690f09172 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -52,6 +52,7 @@ public:  		MEDIA_EVENT_NAVIGATE_COMPLETE,		// browser has finished navigation  		MEDIA_EVENT_PROGRESS_UPDATED,		// browser has updated loading progress  		MEDIA_EVENT_STATUS_TEXT_CHANGED,	// browser has updated the status text +		MEDIA_EVENT_NAME_CHANGED,			// browser has updated the name of the media (typically <title> tag)  		MEDIA_EVENT_LOCATION_CHANGED,		// browser location (URL) has changed (maybe due to internal navagation/frames/etc)  		MEDIA_EVENT_CLICK_LINK_HREF,		// I'm not entirely sure what the semantics of these two are  		MEDIA_EVENT_CLICK_LINK_NOFOLLOW, diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index c9163d2890..793a526c26 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -893,6 +893,13 @@ LLFontGL* LLFontGL::getFontByName(const std::string& name)  	}  } +//static +LLFontGL* LLFontGL::getFontDefault() +{ +	return getFontSansSerif(); // Fallback to sans serif as default font +} + +  // static   std::string LLFontGL::getFontPathSystem()  { diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index a278d88287..5f2c86c6c1 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -165,6 +165,7 @@ public:  	static LLFontGL* getFont(const LLFontDescriptor& desc);  	// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"  	static LLFontGL* getFontByName(const std::string& name); +	static LLFontGL* getFontDefault(); // default fallback font  	static std::string getFontPathLocal();  	static std::string getFontPathSystem(); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 45573cd817..7a3d6ec4f2 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -380,7 +380,10 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  	LLFontDescriptor nearest_exact_desc = *match_desc;  	nearest_exact_desc.setSize(norm_desc.getSize());  	font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc); -	if (it != mFontMap.end()) +	// If we fail to find a font in the fonts directory, it->second might be NULL. +	// We shouldn't construcnt a font with a NULL mFontFreetype. +	// This may not be the best solution, but it at least prevents a crash. +	if (it != mFontMap.end() && it->second != NULL)  	{  		llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 285ce82d2d..e0053b4cc7 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -120,6 +120,11 @@ void LLConsole::setFontSize(S32 size_index)  	{  		mFont = LLFontGL::getFontSansSerifHuge();  	} +	// Make sure the font exists +	if (mFont == NULL) +	{ +		mFont = LLFontGL::getFontDefault(); +	}  	for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)  	{ diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index f253857851..da9384f876 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1952,7 +1952,12 @@ namespace LLInitParam  				return fontp;  			}  		} - +		 +		if (mData.mValue == NULL) +		{ +			mData.mValue = LLFontGL::getFontDefault(); +		} +		  		// default to current value  		return mData.mValue;  	} diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 556865f771..7100d03f05 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -1,995 +1,1077 @@ -/**  - * @file media_plugin_quicktime.cpp - * @brief QuickTime plugin for LLMedia API plugin system - * - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "linden_common.h" - -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_QUICKTIME_ENABLED - -#if defined(LL_DARWIN) -	#include <QuickTime/QuickTime.h> -#elif defined(LL_WINDOWS) -	#include "MacTypes.h" -	#include "QTML.h" -	#include "Movies.h" -	#include "QDoffscreen.h" -	#include "FixMath.h" -#endif - -// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginQuickTime : public MediaPluginBase -{ -public: -	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); -	~MediaPluginQuickTime(); - -	/* virtual */ void receiveMessage(const char *message_string); - -private: - -	int mNaturalWidth; -	int mNaturalHeight; -	Movie mMovieHandle; -	GWorldPtr mGWorldHandle; -	ComponentInstance mMovieController; -	int mCurVolume; -	bool mMediaSizeChanging; -	bool mIsLooping; -	const int mMinWidth; -	const int mMaxWidth; -	const int mMinHeight; -	const int mMaxHeight; -	F64 mPlayRate; - -	enum ECommand { -		COMMAND_NONE, -		COMMAND_STOP, -		COMMAND_PLAY, -		COMMAND_FAST_FORWARD, -		COMMAND_FAST_REWIND, -		COMMAND_PAUSE, -		COMMAND_SEEK, -	}; -	ECommand mCommand; - -	// Override this to add current time and duration to the message -	/*virtual*/ void setDirty(int left, int top, int right, int bottom) -	{ -		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); - -		message.setValueS32("left", left); -		message.setValueS32("top", top); -		message.setValueS32("right", right); -		message.setValueS32("bottom", bottom); -		 -		if(mMovieHandle) -		{ -			message.setValueReal("current_time", getCurrentTime()); -			message.setValueReal("duration", getDuration()); -			message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); -			message.setValueReal("loaded_duration", getLoadedDuration()); -		} -			 -		sendMessage(message); -	} - - -	static Rect rectFromSize(int width, int height) -	{ -		Rect result; -		 - -		result.left = 0; -		result.top = 0; -		result.right = width; -		result.bottom = height; -		 -		return result; -	} -	 -	Fixed getPlayRate(void) -	{ -		Fixed result; -		if(mPlayRate == 0.0f) -		{ -			// Default to the movie's preferred rate -			result = GetMoviePreferredRate(mMovieHandle); -			if(result == 0) -			{ -				// Don't return a 0 play rate, ever. -				std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; -				result = X2Fix(1.0f); -			} -		} -		else -		{ -			result = X2Fix(mPlayRate); -		} -		 -		return result; -	} -	 -	void load( const std::string url ) -	{ -		if ( url.empty() ) -			return; -		 -		// Stop and unload any existing movie before starting another one. -		unload(); -			 -		setStatus(STATUS_LOADING); -		 -		//In case std::string::c_str() makes a copy of the url data, -		//make sure there is memory to hold it before allocating memory for handle. -		//if fails, NewHandleClear(...) should return NULL. -		const char* url_string = url.c_str() ; -		Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); -		if ( NULL == handle || noErr != MemError() || NULL == *handle ) -		{ -			setStatus(STATUS_ERROR); -			return; -		} - -		BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); - -		OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); -		DisposeHandle( handle ); -		if ( noErr != err ) -		{ -			setStatus(STATUS_ERROR); -			return; -		}; - -		// do pre-roll actions (typically fired for streaming movies but not always) -		PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); - -		Rect movie_rect = rectFromSize(mWidth, mHeight); - -		// make a new movie controller -		mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); - -		// movie controller -		MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); - -		SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); - -		// function that gets called when a frame is drawn -		SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); - -		setStatus(STATUS_LOADED); -		 -		sizeChanged(); -	}; - -	bool unload() -	{ -		if ( mMovieHandle ) -		{ -			StopMovie( mMovieHandle ); -			if ( mMovieController ) -			{ -				MCMovieChanged( mMovieController, mMovieHandle ); -			}; -		}; - -		if ( mMovieController ) -		{ -			MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); -			DisposeMovieController( mMovieController ); -			mMovieController = NULL; -		}; - -		if ( mMovieHandle ) -		{ -			SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); -			DisposeMovie( mMovieHandle ); -			mMovieHandle = NULL; -		}; - -		if ( mGWorldHandle ) -		{ -			DisposeGWorld( mGWorldHandle ); -			mGWorldHandle = NULL; -		}; -		 -		setStatus(STATUS_NONE); - -		return true; -	} - -	bool navigateTo( const std::string url ) -	{ -		unload(); -		load( url ); -		 -		return true; -	}; - -	bool sizeChanged() -	{ -		if ( ! mMovieHandle ) -			return false; -		 -		// Check to see whether the movie's natural size has updated -		{ -			int width, height; -			getMovieNaturalSize(&width, &height); -			if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) -			{ -				mNaturalWidth = width; -				mNaturalHeight = height; - -				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); -				message.setValue("name", mTextureSegmentName); -				message.setValueS32("width", width); -				message.setValueS32("height", height); -				sendMessage(message); -				//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; -			} -		} -		 -		// sanitize destination size -		Rect dest_rect = rectFromSize(mWidth, mHeight); - -		// media depth won't change -		int depth_bits = mDepth * 8; -		long rowbytes = mDepth * mTextureWidth; -				 -		GWorldPtr old_gworld_handle = mGWorldHandle; - -		if(mPixels != NULL) -		{ -			// We have pixels.  Set up a GWorld pointing at the texture. -			OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); -			if ( noErr != result ) -			{ -				// TODO: unrecoverable??  throw exception?  return something? -				return false; -			} -		} -		else -		{ -			// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. -			Rect tempRect = rectFromSize(1, 1); -			OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); -			if ( noErr != result ) -			{ -				// TODO: unrecoverable??  throw exception?  return something? -				return false; -			} -		} - -		SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) ); - -		// If the GWorld was already set up, delete it. -		if(old_gworld_handle != NULL) -		{ -			DisposeGWorld( old_gworld_handle ); -		} -		 -		// Set up the movie display matrix -		{ -			// scale movie to fit rect and invert vertically to match opengl image format -			MatrixRecord transform; -			SetIdentityMatrix( &transform );	// transforms are additive so start from identify matrix -			double scaleX = (double) mWidth / mNaturalWidth; -			double scaleY = -1.0 * (double) mHeight / mNaturalHeight; -			double centerX = mWidth / 2.0; -			double centerY = mHeight / 2.0; -			ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); -			SetMovieMatrix( mMovieHandle, &transform ); -		} -		 -		// update movie controller -		if ( mMovieController ) -		{ -			MCSetControllerPort( mMovieController, mGWorldHandle ); -			MCPositionController( mMovieController, &dest_rect, &dest_rect, -								  mcTopLeftMovie | mcPositionDontInvalidate ); -			MCMovieChanged( mMovieController, mMovieHandle ); -		} - - -		// Emit event with size change so the calling app knows about it too -		// TODO: -		//LLMediaEvent event( this ); -		//mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - -		return true; -	} - -	static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) -	{ -		Boolean result = false; - -		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - -		switch( action ) -		{ -			// handle window resizing -			case mcActionControllerSizeChanged:				 -				// Ensure that the movie draws correctly at the new size -				self->sizeChanged();						 -				break; - -			// Block any movie controller actions that open URLs. -			case mcActionLinkToURL: -			case mcActionGetNextURL: -			case mcActionLinkToURLExtended: -				// Prevent the movie controller from handling the message -				result = true; -				break; - -			default: -				break; -		}; - -		return result; -	}; - -	static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) -	{ -		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - -		// IMPORTANT: typically, a consumer who is observing this event will set a flag -		// when this event is fired then render later. Be aware that the media stream -		// can change during this period - dimensions, depth, format etc. -		//LLMediaEvent event( self ); -//		self->updateQuickTime(); -		// TODO ^^^ - -		if ( self->mWidth > 0 && self->mHeight > 0 ) -			self->setDirty( 0, 0, self->mWidth, self->mHeight ); - -		return noErr; -	}; - -	static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) -	{ -		//MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - -		// TODO: -		//LLMediaEvent event( self ); -		//self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); -	}; - - -	void rewind() -	{ -		GoToBeginningOfMovie( mMovieHandle ); -		MCMovieChanged( mMovieController, mMovieHandle ); -	}; - -	bool processState() -	{ -		if ( mCommand == COMMAND_PLAY ) -		{ -			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING ) -			{ -				long state = GetMovieLoadState( mMovieHandle ); - -				if ( state >= kMovieLoadStatePlaythroughOK ) -				{ -					// if the movie is at the end (generally because it reached it naturally) -					// and we play is requested, jump back to the start of the movie. -					// note: this is different from having loop flag set. -					if ( IsMovieDone( mMovieHandle ) ) -					{ -						Fixed rate = X2Fix( 0.0 ); -						MCDoAction( mMovieController, mcActionPlay, (void*)rate ); -						rewind(); -					}; -					 -					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); -					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); -					setStatus(STATUS_PLAYING); -					mCommand = COMMAND_NONE; -				}; -			}; -		} -		else -		if ( mCommand == COMMAND_STOP ) -		{ -			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED ) -			{ -				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) -				{ -					Fixed rate = X2Fix( 0.0 ); -					MCDoAction( mMovieController, mcActionPlay, (void*)rate ); -					rewind(); - -					setStatus(STATUS_LOADED); -					mCommand = COMMAND_NONE; -				}; -			}; -		} -		else -		if ( mCommand == COMMAND_PAUSE ) -		{ -			if ( mStatus == STATUS_PLAYING ) -			{				 -				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) -				{ -					Fixed rate = X2Fix( 0.0 ); -					MCDoAction( mMovieController, mcActionPlay, (void*)rate ); -					setStatus(STATUS_PAUSED); -					mCommand = COMMAND_NONE; -				}; -			}; -		}; - -		return true; -	}; - -	void play(F64 rate) -	{ -		mPlayRate = rate; -		mCommand = COMMAND_PLAY; -	}; - -	void stop() -	{ -		mCommand = COMMAND_STOP; -	}; - -	void pause() -	{ -		mCommand = COMMAND_PAUSE; -	}; - -	void getMovieNaturalSize(int *movie_width, int *movie_height) -	{ -		Rect rect; -		 -		GetMovieNaturalBoundsRect( mMovieHandle, &rect ); - -		int width  = ( rect.right - rect.left ); -		int height = ( rect.bottom - rect.top ); - -		// make sure width and height fall in valid range -		if ( width < mMinWidth ) -			width = mMinWidth; - -		if ( width > mMaxWidth ) -			width = mMaxWidth; - -		if ( height < mMinHeight ) -			height = mMinHeight; - -		if ( height > mMaxHeight ) -			height = mMaxHeight; - -		// return the new rect -		*movie_width = width; -		*movie_height = height; -	} -	 -	void updateQuickTime(int milliseconds) -	{ -		if ( ! mMovieHandle ) -			return; - -		if ( ! mMovieController ) -			return; - -		// service QuickTime -		// Calling it this way doesn't have good behavior on Windows... -//		MoviesTask( mMovieHandle, milliseconds ); -		// This was the original, but I think using both MoviesTask and MCIdle is redundant.  Trying with only MCIdle. -//		MoviesTask( mMovieHandle, 0 ); - -		MCIdle( mMovieController ); - -		if ( ! mGWorldHandle ) -			return; - -		if ( mMediaSizeChanging ) -			return; - -		// update state machine -		processState(); - -		// special code for looping - need to rewind at the end of the movie -		if ( mIsLooping ) -		{ -			// QT call to see if we are at the end - can't do with controller -			if ( IsMovieDone( mMovieHandle ) ) -			{ -				// go back to start -				rewind(); - -				if ( mMovieController ) -				{ -					// kick off new play -					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); - -					// set the volume -					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); -				}; -			}; -		}; -	}; - -	int getDataWidth() const -	{ -		if ( mGWorldHandle ) -		{ -			int depth = mDepth; - -			if (depth < 1) -				depth = 1; - -			// ALWAYS use the row bytes from the PixMap if we have a GWorld because -			// sometimes it's not the same as mMediaDepth * mMediaWidth ! -			PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); -			return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; -		} -		else -		{ -			// TODO :   return LLMediaImplCommon::getaDataWidth(); -			return 0; -		} -	}; - -	void seek( F64 time ) -	{ -		if ( mMovieController ) -		{ -			TimeRecord when; -			when.scale = GetMovieTimeScale( mMovieHandle ); -			when.base = 0; - -			// 'time' is in (floating point) seconds.  The timebase time will be in 'units', where -			// there are 'scale' units per second. -			SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); - -			when.value.hi = ( SInt32 )( raw_time >> 32 ); -			when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); - -			MCDoAction( mMovieController, mcActionGoToTime, &when ); -		}; -	}; - -	F64 getDuration() -	{ -		TimeValue duration = GetMovieDuration( mMovieHandle ); -		TimeValue scale = GetMovieTimeScale( mMovieHandle ); - -		return (F64)duration / (F64)scale; -	}; - -	F64 getLoadedDuration() -	{ -		TimeValue duration; -		if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) -		{ -			// If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. -			duration = GetMovieDuration( mMovieHandle ); -		} -		TimeValue scale = GetMovieTimeScale( mMovieHandle ); - -		return (F64)duration / (F64)scale; -	}; - -	F64 getCurrentTime() -	{ -		TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); -		TimeValue scale = GetMovieTimeScale( mMovieHandle ); - -		return (F64)curr_time / (F64)scale; -	}; - -	void setVolume( F64 volume ) -	{ -		mCurVolume = (short)(volume * ( double ) 0x100 ); - -		if ( mMovieController ) -		{ -			MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); -		}; -	}; - -	//////////////////////////////////////////////////////////////////////////////// -	// -	void update(int milliseconds = 0) -	{ -		updateQuickTime(milliseconds); -	}; - -	//////////////////////////////////////////////////////////////////////////////// -	// -	void mouseDown( int x, int y ) -	{ -	}; - -	//////////////////////////////////////////////////////////////////////////////// -	// -	void mouseUp( int x, int y ) -	{ -	}; - -	//////////////////////////////////////////////////////////////////////////////// -	// -	void mouseMove( int x, int y ) -	{ -	}; - -	//////////////////////////////////////////////////////////////////////////////// -	// -	void keyPress( unsigned char key ) -	{ -	}; - -}; - -MediaPluginQuickTime::MediaPluginQuickTime( -	LLPluginInstance::sendMessageFunction host_send_func, -	void *host_user_data ) : -	MediaPluginBase(host_send_func, host_user_data), -	mMinWidth( 0 ), -	mMaxWidth( 2048 ), -	mMinHeight( 0 ), -	mMaxHeight( 2048 ) -{ -//	std::cerr << "MediaPluginQuickTime constructor" << std::endl; - -	mNaturalWidth = -1; -	mNaturalHeight = -1; -	mMovieHandle = 0; -	mGWorldHandle = 0; -	mMovieController = 0; -	mCurVolume = 0x99; -	mMediaSizeChanging = false; -	mIsLooping = false; -	mCommand = COMMAND_NONE; -	mPlayRate = 0.0f; -	mStatus = STATUS_NONE; -} - -MediaPluginQuickTime::~MediaPluginQuickTime() -{ -//	std::cerr << "MediaPluginQuickTime destructor" << std::endl; - -	ExitMovies(); - -#ifdef LL_WINDOWS -	TerminateQTML(); -//		std::cerr << "QuickTime closing down" << std::endl; -#endif -} - - -void MediaPluginQuickTime::receiveMessage(const char *message_string) -{ -//	std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; -	LLPluginMessage message_in; - -	if(message_in.parse(message_string) >= 0) -	{ -		std::string message_class = message_in.getClass(); -		std::string message_name = message_in.getName(); -		if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) -		{ -			if(message_name == "init") -			{ -				LLPluginMessage message("base", "init_response"); -				LLSD versions = LLSD::emptyMap(); -				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; -				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; -				// Normally a plugin would only specify one of these two subclasses, but this is a demo... -//				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; -				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; -				message.setValueLLSD("versions", versions); - -				#ifdef LL_WINDOWS -				if ( InitializeQTML( 0L ) != noErr ) -				{ -					//TODO: If no QT on Windows, this fails - respond accordingly. -					//return false; -				} -				else -				{ -//					std::cerr << "QuickTime initialized" << std::endl; -				}; -				#endif - -				EnterMovies(); - -				std::string plugin_version = "QuickTime media plugin, QuickTime version "; - -				long version = 0; -				Gestalt( gestaltQuickTimeVersion, &version ); -				std::ostringstream codec( "" ); -				codec << std::hex << version << std::dec; -				plugin_version += codec.str(); -				message.setValue("plugin_version", plugin_version); -				sendMessage(message); - -				// Plugin gets to decide the texture parameters to use. -				message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); -				#if defined(LL_WINDOWS) -					// Values for Windows -					mDepth = 3;	 -					message.setValueU32("format", GL_RGB); -					message.setValueU32("type", GL_UNSIGNED_BYTE); - -					// We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. -					// Padding to a multiple of 3*32 guarantees it'll divide out properly. -					message.setValueU32("padding", 32 * 3); -				#else -					// Values for Mac -					mDepth = 4;	 -					message.setValueU32("format", GL_BGRA_EXT); -					#ifdef __BIG_ENDIAN__ -						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); -					#else -						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); -					#endif - -					// Pad texture width to a multiple of 32 bytes, to line up with cache lines. -					message.setValueU32("padding", 32); -				#endif -				message.setValueS32("depth", mDepth); -				message.setValueU32("internalformat", GL_RGB); -				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left. -				message.setValueBoolean("allow_downsample", true); -				sendMessage(message); -			} -			else if(message_name == "idle") -			{ -				// no response is necessary here. -				F64 time = message_in.getValueReal("time"); -				 -				// Convert time to milliseconds for update() -				update((int)(time * 1000.0f)); -			} -			else if(message_name == "cleanup") -			{ -				// TODO: clean up here -			} -			else if(message_name == "shm_added") -			{ -				SharedSegmentInfo info; -				info.mAddress = message_in.getValuePointer("address"); -				info.mSize = (size_t)message_in.getValueS32("size"); -				std::string name = message_in.getValue("name"); - - -//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name -//					<< ", size: " << info.mSize -//					<< ", address: " << info.mAddress -//					<< std::endl; - -				mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - -			} -			else if(message_name == "shm_remove") -			{ -				std::string name = message_in.getValue("name"); - -//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; - -				SharedSegmentMap::iterator iter = mSharedSegments.find(name); -				if(iter != mSharedSegments.end()) -				{ -					if(mPixels == iter->second.mAddress) -					{ -						// This is the currently active pixel buffer.  Make sure we stop drawing to it. -						mPixels = NULL; -						mTextureSegmentName.clear(); -						 -						// Make sure the movie GWorld is no longer pointed at the shared segment. -						sizeChanged();						 -					} -					mSharedSegments.erase(iter); -				} -				else -				{ -//					std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl; -				} - -				// Send the response so it can be cleaned up. -				LLPluginMessage message("base", "shm_remove_response"); -				message.setValue("name", name); -				sendMessage(message); -			} -			else -			{ -//				std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; -			} -		} -		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) -		{ -			if(message_name == "size_change") -			{ -				std::string name = message_in.getValue("name"); -				S32 width = message_in.getValueS32("width"); -				S32 height = message_in.getValueS32("height"); -				S32 texture_width = message_in.getValueS32("texture_width"); -				S32 texture_height = message_in.getValueS32("texture_height"); - -				//std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; - -				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); -				message.setValue("name", name); -				message.setValueS32("width", width); -				message.setValueS32("height", height); -				message.setValueS32("texture_width", texture_width); -				message.setValueS32("texture_height", texture_height); -				sendMessage(message); - -				if(!name.empty()) -				{ -					// Find the shared memory region with this name -					SharedSegmentMap::iterator iter = mSharedSegments.find(name); -					if(iter != mSharedSegments.end()) -					{ -//						std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; -//						std::cerr << "%%%%  texture size is " << texture_width << " by " << texture_height << std::endl; - -						mPixels = (unsigned char*)iter->second.mAddress; -						mTextureSegmentName = name; -						mWidth = width; -						mHeight = height; - -						mTextureWidth = texture_width; -						mTextureHeight = texture_height; - -						mMediaSizeChanging = false; -						 -						sizeChanged(); -						 -						update(); -					}; -				}; -			} -			else if(message_name == "load_uri") -			{ -				std::string uri = message_in.getValue("uri"); -				load( uri ); -				sendStatus();		 -			} -			else if(message_name == "mouse_event") -			{ -				std::string event = message_in.getValue("event"); -				S32 x = message_in.getValueS32("x"); -				S32 y = message_in.getValueS32("y"); -				 -				if(event == "down") -				{ -					mouseDown(x, y); -				} -				else if(event == "up") -				{ -					mouseUp(x, y); -				} -				else if(event == "move") -				{ -					mouseMove(x, y); -				}; -			}; -		} -		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) -		{ -			if(message_name == "stop") -			{ -				stop(); -			} -			else if(message_name == "start") -			{ -				F64 rate = 0.0; -				if(message_in.hasValue("rate")) -				{ -					rate = message_in.getValueReal("rate"); -				} -				play(rate); -			} -			else if(message_name == "pause") -			{ -				pause(); -			} -			else if(message_name == "seek") -			{ -				F64 time = message_in.getValueReal("time"); -				seek(time); -			} -			else if(message_name == "set_loop") -			{ -				bool loop = message_in.getValueBoolean("loop"); -				mIsLooping = loop; -			} -			else if(message_name == "set_volume") -			{ -				F64 volume = message_in.getValueReal("volume"); -				setVolume(volume); -			} -		} -		else -		{ -//			std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; -		}; -	}; -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ -	MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); -	*plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; -	*plugin_user_data = (void*)self; - -	return 0; -} - -#else // LL_QUICKTIME_ENABLED - -// Stubbed-out class with constructor/destructor (necessary or windows linker -// will just think its dead code and optimize it all out) -class MediaPluginQuickTime : public MediaPluginBase -{ -public: -	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); -	~MediaPluginQuickTime(); -	/* virtual */ void receiveMessage(const char *message_string); -}; - -MediaPluginQuickTime::MediaPluginQuickTime( -	LLPluginInstance::sendMessageFunction host_send_func, -	void *host_user_data ) : -	MediaPluginBase(host_send_func, host_user_data) -{ -    // no-op -} - -MediaPluginQuickTime::~MediaPluginQuickTime() -{ -    // no-op -} - -void MediaPluginQuickTime::receiveMessage(const char *message_string) -{ -    // no-op  -} - -// We're building without quicktime enabled.  Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ -    return -1; -} - -#endif // LL_QUICKTIME_ENABLED +/**
 + * @file media_plugin_quicktime.cpp
 + * @brief QuickTime plugin for LLMedia API plugin system
 + *
 + * $LicenseInfo:firstyear=2008&license=viewergpl$
 + *
 + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "linden_common.h"
 +
 +#include "llgl.h"
 +
 +#include "llplugininstance.h"
 +#include "llpluginmessage.h"
 +#include "llpluginmessageclasses.h"
 +#include "media_plugin_base.h"
 +
 +#if LL_QUICKTIME_ENABLED
 +
 +#if defined(LL_DARWIN)
 +	#include <QuickTime/QuickTime.h>
 +#elif defined(LL_WINDOWS)
 +	#include "MacTypes.h"
 +	#include "QTML.h"
 +	#include "Movies.h"
 +	#include "QDoffscreen.h"
 +	#include "FixMath.h"
 +	#include "QTLoadLibraryUtils.h"
 +#endif
 +
 +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +class MediaPluginQuickTime : public MediaPluginBase
 +{
 +public:
 +	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
 +	~MediaPluginQuickTime();
 +
 +	/* virtual */ void receiveMessage(const char *message_string);
 +
 +private:
 +
 +	int mNaturalWidth;
 +	int mNaturalHeight;
 +	Movie mMovieHandle;
 +	GWorldPtr mGWorldHandle;
 +	ComponentInstance mMovieController;
 +	int mCurVolume;
 +	bool mMediaSizeChanging;
 +	bool mIsLooping;
 +	std::string mMovieTitle;
 +	bool mReceivedTitle;
 +	const int mMinWidth;
 +	const int mMaxWidth;
 +	const int mMinHeight;
 +	const int mMaxHeight;
 +	F64 mPlayRate;
 +
 +	enum ECommand {
 +		COMMAND_NONE,
 +		COMMAND_STOP,
 +		COMMAND_PLAY,
 +		COMMAND_FAST_FORWARD,
 +		COMMAND_FAST_REWIND,
 +		COMMAND_PAUSE,
 +		COMMAND_SEEK,
 +	};
 +	ECommand mCommand;
 +
 +	// Override this to add current time and duration to the message
 +	/*virtual*/ void setDirty(int left, int top, int right, int bottom)
 +	{
 +		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
 +
 +		message.setValueS32("left", left);
 +		message.setValueS32("top", top);
 +		message.setValueS32("right", right);
 +		message.setValueS32("bottom", bottom);
 +
 +		if(mMovieHandle)
 +		{
 +			message.setValueReal("current_time", getCurrentTime());
 +			message.setValueReal("duration", getDuration());
 +			message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
 +		}
 +
 +		sendMessage(message);
 +	}
 +
 +
 +	static Rect rectFromSize(int width, int height)
 +	{
 +		Rect result;
 +
 +
 +		result.left = 0;
 +		result.top = 0;
 +		result.right = width;
 +		result.bottom = height;
 +
 +		return result;
 +	}
 +
 +	Fixed getPlayRate(void)
 +	{
 +		Fixed result;
 +		if(mPlayRate == 0.0f)
 +		{
 +			// Default to the movie's preferred rate
 +			result = GetMoviePreferredRate(mMovieHandle);
 +			if(result == 0)
 +			{
 +				// Don't return a 0 play rate, ever.
 +				std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
 +				result = X2Fix(1.0f);
 +			}
 +		}
 +		else
 +		{
 +			result = X2Fix(mPlayRate);
 +		}
 +
 +		return result;
 +	}
 +
 +	void load( const std::string url )
 +	{
 +
 +		if ( url.empty() )
 +			return;
 +
 +		// Stop and unload any existing movie before starting another one.
 +		unload();
 +
 +		setStatus(STATUS_LOADING);
 +
 +		//In case std::string::c_str() makes a copy of the url data,
 +		//make sure there is memory to hold it before allocating memory for handle.
 +		//if fails, NewHandleClear(...) should return NULL.
 +		const char* url_string = url.c_str() ;
 +		Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
 +
 +		if ( NULL == handle || noErr != MemError() || NULL == *handle )
 +		{
 +			setStatus(STATUS_ERROR);
 +			return;
 +		}
 +
 +		BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
 +
 +		OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
 +		DisposeHandle( handle );
 +		if ( noErr != err )
 +		{
 +			setStatus(STATUS_ERROR);
 +			return;
 +		};
 +
 +		// do pre-roll actions (typically fired for streaming movies but not always)
 +		PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
 +
 +		Rect movie_rect = rectFromSize(mWidth, mHeight);
 +
 +		// make a new movie controller
 +		mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
 +
 +		// movie controller
 +		MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
 +
 +		SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
 +
 +		// function that gets called when a frame is drawn
 +		SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
 +
 +		setStatus(STATUS_LOADED);
 +
 +		sizeChanged();
 +	};
 +
 +	bool unload()
 +	{
 +		// new movie and have to get title again
 +		mReceivedTitle = false;
 +
 +		if ( mMovieHandle )
 +		{
 +			StopMovie( mMovieHandle );
 +			if ( mMovieController )
 +			{
 +				MCMovieChanged( mMovieController, mMovieHandle );
 +			};
 +		};
 +
 +		if ( mMovieController )
 +		{
 +			MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
 +			DisposeMovieController( mMovieController );
 +			mMovieController = NULL;
 +		};
 +
 +		if ( mMovieHandle )
 +		{
 +			SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
 +			DisposeMovie( mMovieHandle );
 +			mMovieHandle = NULL;
 +		};
 +
 +		if ( mGWorldHandle )
 +		{
 +			DisposeGWorld( mGWorldHandle );
 +			mGWorldHandle = NULL;
 +		};
 +
 +		setStatus(STATUS_NONE);
 +
 +		return true;
 +	}
 +
 +	bool navigateTo( const std::string url )
 +	{
 +		unload();
 +		load( url );
 +
 +		return true;
 +	};
 +
 +	bool sizeChanged()
 +	{
 +		if ( ! mMovieHandle )
 +			return false;
 +
 +		// Check to see whether the movie's natural size has updated
 +		{
 +			int width, height;
 +			getMovieNaturalSize(&width, &height);
 +			if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
 +			{
 +				mNaturalWidth = width;
 +				mNaturalHeight = height;
 +
 +				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
 +				message.setValue("name", mTextureSegmentName);
 +				message.setValueS32("width", width);
 +				message.setValueS32("height", height);
 +				sendMessage(message);
 +				//std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
 +			}
 +		}
 +
 +		// sanitize destination size
 +		Rect dest_rect = rectFromSize(mWidth, mHeight);
 +
 +		// media depth won't change
 +		int depth_bits = mDepth * 8;
 +		long rowbytes = mDepth * mTextureWidth;
 +
 +		GWorldPtr old_gworld_handle = mGWorldHandle;
 +
 +		if(mPixels != NULL)
 +		{
 +			// We have pixels.  Set up a GWorld pointing at the texture.
 +			OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
 +			if ( noErr != result )
 +			{
 +				// TODO: unrecoverable??  throw exception?  return something?
 +				return false;
 +			}
 +		}
 +		else
 +		{
 +			// We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
 +			Rect tempRect = rectFromSize(1, 1);
 +			OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
 +			if ( noErr != result )
 +			{
 +				// TODO: unrecoverable??  throw exception?  return something?
 +				return false;
 +			}
 +		}
 +
 +		SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
 +
 +		// If the GWorld was already set up, delete it.
 +		if(old_gworld_handle != NULL)
 +		{
 +			DisposeGWorld( old_gworld_handle );
 +		}
 +
 +		// Set up the movie display matrix
 +		{
 +			// scale movie to fit rect and invert vertically to match opengl image format
 +			MatrixRecord transform;
 +			SetIdentityMatrix( &transform );	// transforms are additive so start from identify matrix
 +			double scaleX = (double) mWidth / mNaturalWidth;
 +			double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
 +			double centerX = mWidth / 2.0;
 +			double centerY = mHeight / 2.0;
 +			ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
 +			SetMovieMatrix( mMovieHandle, &transform );
 +		}
 +
 +		// update movie controller
 +		if ( mMovieController )
 +		{
 +			MCSetControllerPort( mMovieController, mGWorldHandle );
 +			MCPositionController( mMovieController, &dest_rect, &dest_rect,
 +								  mcTopLeftMovie | mcPositionDontInvalidate );
 +			MCMovieChanged( mMovieController, mMovieHandle );
 +		}
 +
 +
 +		// Emit event with size change so the calling app knows about it too
 +		// TODO:
 +		//LLMediaEvent event( this );
 +		//mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
 +
 +		return true;
 +	}
 +	static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
 +	{
 +		Boolean result = false;
 +
 +		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
 +
 +		switch( action )
 +		{
 +			// handle window resizing
 +			case mcActionControllerSizeChanged:
 +				// Ensure that the movie draws correctly at the new size
 +				self->sizeChanged();
 +				break;
 +
 +			// Block any movie controller actions that open URLs.
 +			case mcActionLinkToURL:
 +			case mcActionGetNextURL:
 +			case mcActionLinkToURLExtended:
 +				// Prevent the movie controller from handling the message
 +				result = true;
 +				break;
 +
 +			default:
 +				break;
 +		};
 +
 +		return result;
 +	};
 +
 +	static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
 +	{
 +		MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
 +
 +		// IMPORTANT: typically, a consumer who is observing this event will set a flag
 +		// when this event is fired then render later. Be aware that the media stream
 +		// can change during this period - dimensions, depth, format etc.
 +		//LLMediaEvent event( self );
 +//		self->updateQuickTime();
 +		// TODO ^^^
 +
 +
 +		if ( self->mWidth > 0 && self->mHeight > 0 )
 +			self->setDirty( 0, 0, self->mWidth, self->mHeight );
 +
 +		return noErr;
 +	};
 +
 +	static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
 +	{
 +		//MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
 +
 +		// TODO:
 +		//LLMediaEvent event( self );
 +		//self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
 +	};
 +
 +
 +	void rewind()
 +	{
 +		GoToBeginningOfMovie( mMovieHandle );
 +		MCMovieChanged( mMovieController, mMovieHandle );
 +	};
 +
 +	bool processState()
 +	{
 +		if ( mCommand == COMMAND_PLAY )
 +		{
 +			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING )
 +			{
 +				long state = GetMovieLoadState( mMovieHandle );
 +
 +				if ( state >= kMovieLoadStatePlaythroughOK )
 +				{
 +					// if the movie is at the end (generally because it reached it naturally)
 +					// and we play is requested, jump back to the start of the movie.
 +					// note: this is different from having loop flag set.
 +					if ( IsMovieDone( mMovieHandle ) )
 +					{
 +						Fixed rate = X2Fix( 0.0 );
 +						MCDoAction( mMovieController, mcActionPlay, (void*)rate );
 +						rewind();
 +					};
 +
 +					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
 +					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
 +					setStatus(STATUS_PLAYING);
 +					mCommand = COMMAND_NONE;
 +				};
 +			};
 +		}
 +		else
 +		if ( mCommand == COMMAND_STOP )
 +		{
 +			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED )
 +			{
 +				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
 +				{
 +					Fixed rate = X2Fix( 0.0 );
 +					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
 +					rewind();
 +
 +					setStatus(STATUS_LOADED);
 +					mCommand = COMMAND_NONE;
 +				};
 +			};
 +		}
 +		else
 +		if ( mCommand == COMMAND_PAUSE )
 +		{
 +			if ( mStatus == STATUS_PLAYING )
 +			{
 +				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
 +				{
 +					Fixed rate = X2Fix( 0.0 );
 +					MCDoAction( mMovieController, mcActionPlay, (void*)rate );
 +					setStatus(STATUS_PAUSED);
 +					mCommand = COMMAND_NONE;
 +				};
 +			};
 +		};
 +
 +		return true;
 +	};
 +
 +	void play(F64 rate)
 +	{
 +		mPlayRate = rate;
 +		mCommand = COMMAND_PLAY;
 +	};
 +
 +	void stop()
 +	{
 +		mCommand = COMMAND_STOP;
 +	};
 +
 +	void pause()
 +	{
 +		mCommand = COMMAND_PAUSE;
 +	};
 +
 +	void getMovieNaturalSize(int *movie_width, int *movie_height)
 +	{
 +		Rect rect;
 +
 +		GetMovieNaturalBoundsRect( mMovieHandle, &rect );
 +
 +		int width  = ( rect.right - rect.left );
 +		int height = ( rect.bottom - rect.top );
 +
 +		// make sure width and height fall in valid range
 +		if ( width < mMinWidth )
 +			width = mMinWidth;
 +
 +		if ( width > mMaxWidth )
 +			width = mMaxWidth;
 +
 +		if ( height < mMinHeight )
 +			height = mMinHeight;
 +
 +		if ( height > mMaxHeight )
 +			height = mMaxHeight;
 +
 +		// return the new rect
 +		*movie_width = width;
 +		*movie_height = height;
 +	}
 +
 +	void updateQuickTime(int milliseconds)
 +	{
 +		if ( ! mMovieHandle )
 +			return;
 +
 +		if ( ! mMovieController )
 +			return;
 +
 +		// service QuickTime
 +		// Calling it this way doesn't have good behavior on Windows...
 +//		MoviesTask( mMovieHandle, milliseconds );
 +		// This was the original, but I think using both MoviesTask and MCIdle is redundant.  Trying with only MCIdle.
 +//		MoviesTask( mMovieHandle, 0 );
 +
 +		MCIdle( mMovieController );
 +
 +		if ( ! mGWorldHandle )
 +			return;
 +
 +		if ( mMediaSizeChanging )
 +			return;
 +
 +		// update state machine
 +		processState();
 +
 +		// see if title arrived and if so, update member variable with contents
 +		checkTitle();
 +
 +		// special code for looping - need to rewind at the end of the movie
 +		if ( mIsLooping )
 +		{
 +			// QT call to see if we are at the end - can't do with controller
 +			if ( IsMovieDone( mMovieHandle ) )
 +			{
 +				// go back to start
 +				rewind();
 +
 +				if ( mMovieController )
 +				{
 +					// kick off new play
 +					MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
 +
 +					// set the volume
 +					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
 +				};
 +			};
 +		};
 +	};
 +
 +	int getDataWidth() const
 +	{
 +		if ( mGWorldHandle )
 +		{
 +			int depth = mDepth;
 +
 +			if (depth < 1)
 +				depth = 1;
 +
 +			// ALWAYS use the row bytes from the PixMap if we have a GWorld because
 +			// sometimes it's not the same as mMediaDepth * mMediaWidth !
 +			PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
 +			return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
 +		}
 +		else
 +		{
 +			// TODO :   return LLMediaImplCommon::getaDataWidth();
 +			return 0;
 +		}
 +	};
 +
 +	void seek( F64 time )
 +	{
 +		if ( mMovieController )
 +		{
 +			TimeRecord when;
 +			when.scale = GetMovieTimeScale( mMovieHandle );
 +			when.base = 0;
 +
 +			// 'time' is in (floating point) seconds.  The timebase time will be in 'units', where
 +			// there are 'scale' units per second.
 +			SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
 +
 +			when.value.hi = ( SInt32 )( raw_time >> 32 );
 +			when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
 +
 +			MCDoAction( mMovieController, mcActionGoToTime, &when );
 +		};
 +	};
 +
 +	F64 getLoadedDuration() 	  	 
 +	{ 	  	 
 +		TimeValue duration; 	  	 
 +		if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) 	  	 
 +		{ 	  	 
 +			// If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. 	  	 
 +			duration = GetMovieDuration( mMovieHandle ); 	  	 
 +		} 	  	 
 +		TimeValue scale = GetMovieTimeScale( mMovieHandle ); 	  	 
 +
 +		return (F64)duration / (F64)scale; 	  	 
 +	}; 	  	 
 +
 +	F64 getDuration()
 +	{
 +		TimeValue duration = GetMovieDuration( mMovieHandle );
 +		TimeValue scale = GetMovieTimeScale( mMovieHandle );
 +
 +		return (F64)duration / (F64)scale;
 +	};
 +
 +	F64 getCurrentTime()
 +	{
 +		TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
 +		TimeValue scale = GetMovieTimeScale( mMovieHandle );
 +
 +		return (F64)curr_time / (F64)scale;
 +	};
 +
 +	void setVolume( F64 volume )
 +	{
 +		mCurVolume = (short)(volume * ( double ) 0x100 );
 +
 +		if ( mMovieController )
 +		{
 +			MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
 +		};
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	//
 +	void update(int milliseconds = 0)
 +	{
 +		updateQuickTime(milliseconds);
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	//
 +	void mouseDown( int x, int y )
 +	{
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	//
 +	void mouseUp( int x, int y )
 +	{
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	//
 +	void mouseMove( int x, int y )
 +	{
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	//
 +	void keyPress( unsigned char key )
 +	{
 +	};
 +
 +	////////////////////////////////////////////////////////////////////////////////
 +	// Grab movie title into mMovieTitle - should be called repeatedly
 +	// until it returns true since movie title takes a while to become 
 +	// available.
 +	const bool getMovieTitle()
 +	{
 +		// grab meta data from movie
 +		QTMetaDataRef media_data_ref;
 +		OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
 +		if ( noErr != result ) 
 +			return false;
 +
 +		// look up "Display Name" in meta data
 +		OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
 +		QTMetaDataItem item = kQTMetaDataItemUninitialized;
 +		result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, 
 +										0, kQTMetaDataKeyFormatCommon, 
 +										(const UInt8 *)&meta_data_key, 
 +										sizeof( meta_data_key ), &item );
 +		if ( noErr != result ) 
 +			return false;
 +
 +		// find the size of the title
 +		ByteCount size;
 +		result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
 +		if ( noErr != result || size <= 0 ) 
 +			return false;
 +
 +		// allocate some space and grab it
 +		UInt8* item_data = new UInt8( size );
 +		memset( item_data, 0, size * sizeof( UInt8* ) );
 +		result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
 +		if ( noErr != result ) 
 +			return false;
 +
 +		// save it
 +		mMovieTitle = std::string( (char* )item_data );
 +
 +		// clean up
 +		delete [] item_data;
 +
 +		return true;
 +	};
 +
 +	// called regularly to see if title changed
 +	void checkTitle()
 +	{
 +		// we did already receive title so keep checking
 +		if ( ! mReceivedTitle )
 +		{
 +			// grab title from movie meta data
 +			if ( getMovieTitle() )
 +			{
 +				// pass back to host application
 +				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
 +				message.setValue("name", mMovieTitle );
 +				sendMessage( message );
 +
 +				// stop looking once we find a title for this movie.
 +				// TODO: this may to be reset if movie title changes
 +				// during playback but this is okay for now
 +				mReceivedTitle = true;
 +			};
 +		};
 +	};
 +};
 +
 +MediaPluginQuickTime::MediaPluginQuickTime(
 +	LLPluginInstance::sendMessageFunction host_send_func,
 +	void *host_user_data ) :
 +	MediaPluginBase(host_send_func, host_user_data),
 +	mMinWidth( 0 ),
 +	mMaxWidth( 2048 ),
 +	mMinHeight( 0 ),
 +	mMaxHeight( 2048 )
 +{
 +//	std::cerr << "MediaPluginQuickTime constructor" << std::endl;
 +
 +	mNaturalWidth = -1;
 +	mNaturalHeight = -1;
 +	mMovieHandle = 0;
 +	mGWorldHandle = 0;
 +	mMovieController = 0;
 +	mCurVolume = 0x99;
 +	mMediaSizeChanging = false;
 +	mIsLooping = false;
 +	mMovieTitle = std::string();
 +	mReceivedTitle = false;
 +	mCommand = COMMAND_NONE;
 +	mPlayRate = 0.0f;
 +	mStatus = STATUS_NONE;
 +}
 +
 +MediaPluginQuickTime::~MediaPluginQuickTime()
 +{
 +//	std::cerr << "MediaPluginQuickTime destructor" << std::endl;
 +
 +	ExitMovies();
 +
 +#ifdef LL_WINDOWS
 +	TerminateQTML();
 +//		std::cerr << "QuickTime closing down" << std::endl;
 +#endif
 +}
 +
 +
 +void MediaPluginQuickTime::receiveMessage(const char *message_string)
 +{
 +//	std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
 +	LLPluginMessage message_in;
 +
 +	if(message_in.parse(message_string) >= 0)
 +	{
 +		std::string message_class = message_in.getClass();
 +		std::string message_name = message_in.getName();
 +		if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
 +		{
 +			if(message_name == "init")
 +			{
 +				LLPluginMessage message("base", "init_response");
 +				LLSD versions = LLSD::emptyMap();
 +				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
 +				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
 +				// Normally a plugin would only specify one of these two subclasses, but this is a demo...
 +				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
 +				message.setValueLLSD("versions", versions);
 +
 +				#ifdef LL_WINDOWS
 +
 +				// QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
 +				// according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
 +				// The solution presented there appears to work.
 +				QTLoadLibrary("qtcf.dll");
 +
 +				// main initialization for QuickTime - only required on Windows
 +				OSErr result = InitializeQTML( 0L );
 +				if ( result != noErr )
 +				{
 +					//TODO: If no QT on Windows, this fails - respond accordingly.
 +				}
 +				else
 +				{
 +					//std::cerr << "QuickTime initialized" << std::endl;
 +				};
 +				#endif
 +
 +				// required for both Windows and Mac
 +				EnterMovies();
 +
 +				std::string plugin_version = "QuickTime media plugin, QuickTime version ";
 +
 +				long version = 0;
 +				Gestalt( gestaltQuickTimeVersion, &version );
 +				std::ostringstream codec( "" );
 +				codec << std::hex << version << std::dec;
 +				plugin_version += codec.str();
 +				message.setValue("plugin_version", plugin_version);
 +				sendMessage(message);
 +
 +				// Plugin gets to decide the texture parameters to use.
 +				message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
 +				#if defined(LL_WINDOWS)
 +					// Values for Windows
 +					mDepth = 3;
 +					message.setValueU32("format", GL_RGB);
 +					message.setValueU32("type", GL_UNSIGNED_BYTE);
 +
 +					// We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
 +					// Padding to a multiple of 3*32 guarantees it'll divide out properly.
 +					message.setValueU32("padding", 32 * 3);
 +				#else
 +					// Values for Mac
 +					mDepth = 4;
 +					message.setValueU32("format", GL_BGRA_EXT);
 +					#ifdef __BIG_ENDIAN__
 +						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
 +					#else
 +						message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
 +					#endif
 +
 +					// Pad texture width to a multiple of 32 bytes, to line up with cache lines.
 +					message.setValueU32("padding", 32);
 +				#endif
 +				message.setValueS32("depth", mDepth);
 +				message.setValueU32("internalformat", GL_RGB);
 +				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left.
 +				message.setValueBoolean("allow_downsample", true);
 +				sendMessage(message);
 +			}
 +			else if(message_name == "idle")
 +			{
 +				// no response is necessary here.
 +				F64 time = message_in.getValueReal("time");
 +
 +				// Convert time to milliseconds for update()
 +				update((int)(time * 1000.0f));
 +			}
 +			else if(message_name == "cleanup")
 +			{
 +				// TODO: clean up here
 +			}
 +			else if(message_name == "shm_added")
 +			{
 +				SharedSegmentInfo info;
 +				info.mAddress = message_in.getValuePointer("address");
 +				info.mSize = (size_t)message_in.getValueS32("size");
 +				std::string name = message_in.getValue("name");
 +//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
 +//					<< ", size: " << info.mSize
 +//					<< ", address: " << info.mAddress
 +//					<< std::endl;
 +
 +				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
 +
 +			}
 +			else if(message_name == "shm_remove")
 +			{
 +				std::string name = message_in.getValue("name");
 +
 +//				std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
 +
 +				SharedSegmentMap::iterator iter = mSharedSegments.find(name);
 +				if(iter != mSharedSegments.end())
 +				{
 +					if(mPixels == iter->second.mAddress)
 +					{
 +						// This is the currently active pixel buffer.  Make sure we stop drawing to it.
 +						mPixels = NULL;
 +						mTextureSegmentName.clear();
 +
 +						// Make sure the movie GWorld is no longer pointed at the shared segment.
 +						sizeChanged();
 +					}
 +					mSharedSegments.erase(iter);
 +				}
 +				else
 +				{
 +//					std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
 +				}
 +
 +				// Send the response so it can be cleaned up.
 +				LLPluginMessage message("base", "shm_remove_response");
 +				message.setValue("name", name);
 +				sendMessage(message);
 +			}
 +			else
 +			{
 +//				std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
 +			}
 +		}
 +		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
 +		{
 +			if(message_name == "size_change")
 +			{
 +				std::string name = message_in.getValue("name");
 +				S32 width = message_in.getValueS32("width");
 +				S32 height = message_in.getValueS32("height");
 +				S32 texture_width = message_in.getValueS32("texture_width");
 +				S32 texture_height = message_in.getValueS32("texture_height");
 +
 +				//std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
 +
 +				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
 +				message.setValue("name", name);
 +				message.setValueS32("width", width);
 +				message.setValueS32("height", height);
 +				message.setValueS32("texture_width", texture_width);
 +				message.setValueS32("texture_height", texture_height);
 +				sendMessage(message);
 +
 +				if(!name.empty())
 +				{
 +					// Find the shared memory region with this name
 +					SharedSegmentMap::iterator iter = mSharedSegments.find(name);
 +					if(iter != mSharedSegments.end())
 +					{
 +//						std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
 +//						std::cerr << "%%%%  texture size is " << texture_width << " by " << texture_height << std::endl;
 +
 +						mPixels = (unsigned char*)iter->second.mAddress;
 +						mTextureSegmentName = name;
 +						mWidth = width;
 +						mHeight = height;
 +
 +						mTextureWidth = texture_width;
 +						mTextureHeight = texture_height;
 +
 +						mMediaSizeChanging = false;
 +
 +						sizeChanged();
 +
 +						update();
 +					};
 +				};
 +			}
 +			else if(message_name == "load_uri")
 +			{
 +				std::string uri = message_in.getValue("uri");
 +				load( uri );
 +				sendStatus();
 +			}
 +			else if(message_name == "mouse_event")
 +			{
 +				std::string event = message_in.getValue("event");
 +				S32 x = message_in.getValueS32("x");
 +				S32 y = message_in.getValueS32("y");
 +
 +				if(event == "down")
 +				{
 +					mouseDown(x, y);
 +				}
 +				else if(event == "up")
 +				{
 +					mouseUp(x, y);
 +				}
 +				else if(event == "move")
 +				{
 +					mouseMove(x, y);
 +				};
 +			};
 +		}
 +		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
 +		{
 +			if(message_name == "stop")
 +			{
 +				stop();
 +			}
 +			else if(message_name == "start")
 +			{
 +				F64 rate = 0.0;
 +				if(message_in.hasValue("rate"))
 +				{
 +					rate = message_in.getValueReal("rate");
 +				}
 +				play(rate);
 +			}
 +			else if(message_name == "pause")
 +			{
 +				pause();
 +			}
 +			else if(message_name == "seek")
 +			{
 +				F64 time = message_in.getValueReal("time");
 +				seek(time);
 +			}
 +			else if(message_name == "set_loop")
 +			{
 +				bool loop = message_in.getValueBoolean("loop");
 +				mIsLooping = loop;
 +			}
 +			else if(message_name == "set_volume")
 +			{
 +				F64 volume = message_in.getValueReal("volume");
 +				setVolume(volume);
 +			}
 +		}
 +		else
 +		{
 +//			std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
 +		};
 +	};
 +}
 +
 +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
 +{
 +	MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
 +	*plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
 +	*plugin_user_data = (void*)self;
 +
 +	return 0;
 +}
 +
 +#else // LL_QUICKTIME_ENABLED
 +
 +// Stubbed-out class with constructor/destructor (necessary or windows linker
 +// will just think its dead code and optimize it all out)
 +class MediaPluginQuickTime : public MediaPluginBase
 +{
 +public:
 +	MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
 +	~MediaPluginQuickTime();
 +	/* virtual */ void receiveMessage(const char *message_string);
 +};
 +
 +MediaPluginQuickTime::MediaPluginQuickTime(
 +	LLPluginInstance::sendMessageFunction host_send_func,
 +	void *host_user_data ) :
 +	MediaPluginBase(host_send_func, host_user_data)
 +{
 +    // no-op
 +}
 +
 +MediaPluginQuickTime::~MediaPluginQuickTime()
 +{
 +    // no-op
 +}
 +
 +void MediaPluginQuickTime::receiveMessage(const char *message_string)
 +{
 +    // no-op
 +}
 +
 +// We're building without quicktime enabled.  Just refuse to initialize.
 +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
 +{
 +    return -1;
 +}
 +
 +#endif // LL_QUICKTIME_ENABLED
 diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 01bb22881f..65872e1596 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -308,7 +308,16 @@ private:  		message.setValue("status", event.getStringValue());  		sendMessage(message);  	} -	 + +	//////////////////////////////////////////////////////////////////////////////// +	// virtual +	void onTitleChange(const EventType& event) +	{ +		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); +		message.setValue("name", event.getStringValue()); +		sendMessage(message); +	} +  	////////////////////////////////////////////////////////////////////////////////  	// virtual  	void onLocationChange(const EventType& event) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index a4b33162d6..d27bce99a6 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -5976,7 +5976,7 @@ bool LLAgent::teleportCore(bool is_local)  	LLFloaterReg::hideInstance("about_land");  	LLViewerParcelMgr::getInstance()->deselectLand(); -	LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL); +	LLViewerMediaFocus::getInstance()->clearFocus();  	// Close all pie menus, deselect land, etc.  	// Don't change the camera until we know teleport succeeded. JC diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b4b30d0cde..4cb3b92476 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1527,7 +1527,6 @@ bool LLAppViewer::cleanup()  	//Note:  	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()  	//because some new image might be generated during cleaning up media. --bao -	LLViewerMediaFocus::cleanupClass();  	LLViewerMedia::cleanupClass();  	LLViewerParcelMedia::cleanupClass();  	gTextureList.shutdown(); // shutdown again in case a callback added something diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index aa457de2d8..d941f24f49 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -118,6 +118,7 @@ BOOL LLFloaterMediaSettings::postBuild()  	mTabContainer->addTabPanel(   			LLTabContainer::TabPanelParams().  			panel(mPanelMediaSettingsSecurity)); +	mPanelMediaSettingsSecurity->setParent( this );  	// restore the last tab viewed from persistance variable storage  	if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab"))) @@ -248,3 +249,28 @@ void LLFloaterMediaSettings::enableOkApplyBtns( bool enable )  	childSetEnabled( "OK", enable );  	childSetEnabled( "Apply", enable );  } + +//////////////////////////////////////////////////////////////////////////////// +// +const std::string LLFloaterMediaSettings::getHomeUrl() +{ +	if ( mPanelMediaSettingsGeneral ) +		return mPanelMediaSettingsGeneral->getHomeUrl(); +	else +		return std::string( "" ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLFloaterMediaSettings::passesWhiteList( const std::string& test_url ) +{ +	// sanity check - don't think this can happen +	if ( mPanelMediaSettingsSecurity ) +		// version in security dialog code is specialized so we pass in  +		// empty string for first parameter since it's not used +		return mPanelMediaSettingsSecurity->passesWhiteList( "", test_url ); +	else +		// this is all we can do +		return false; +} diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h index e2683039cc..17a47cb0f5 100644 --- a/indra/newview/llfloatermediasettings.h +++ b/indra/newview/llfloatermediasettings.h @@ -56,6 +56,8 @@ public:  	static void clearValues( bool editable);  	void enableOkApplyBtns( bool enable );  	LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;}; +	const std::string getHomeUrl(); +	bool passesWhiteList( const std::string& test_url );  	bool mIdenticalHasMediaInfo;  	bool mMultipleMedia; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index e00b352c9b..63953580fe 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1120,7 +1120,7 @@ void LLFloaterTools::getMediaState()  			if(media_data_get!=default_media_data)  			{  				//TODO: get media title -				//media_title =  media_data_get->getTile(); +				//media_title =  media_data_get->getTitle();  				//LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true;  				media_title = media_data_get.getHomeURL();  			} @@ -1155,7 +1155,7 @@ void LLFloaterTools::getMediaState()  			if(media_data_get!=default_media_data)  			{  				//TODO: get media title -				//media_title =  media_data_get->getTile(); +				//media_title =  media_data_get->getTitle();  				media_title = media_data_get.getHomeURL();  			} diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 2b1dd83d72..879b33e571 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -70,6 +70,10 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)  	{  		LLFontDescriptor labelfontdesc("SansSerif", "Small", style);  		rtn = LLFontGL::getFont(labelfontdesc); +		if (!rtn) +		{ +			rtn = LLFontGL::getFontDefault(); +		}  		sFonts[style] = rtn;  	}  	return rtn; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 26ff219437..8005cd1180 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -911,6 +911,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)  			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;  		};  		break; +		 +		case MEDIA_EVENT_NAME_CHANGED: +		{ +			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; +		}; +		break;  	};  	// chain all events to any potential observers of this object. diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 76dcd89028..ab5d8601d0 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -1,440 +1,457 @@ -/** - * @file llpanelmediasettingsgeneral.cpp - * @brief LLPanelMediaSettingsGeneral class implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - *  - * Copyright (c) 2009, 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 "llviewerprecompiledheaders.h" - -#include "llagent.h" -#include "llpanelmediasettingsgeneral.h" -#include "llcombobox.h" -#include "llcheckboxctrl.h" -#include "llspinctrl.h" -#include "lluictrlfactory.h" -#include "llviewerwindow.h" -#include "llviewermedia.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llbutton.h" -#include "lltexturectrl.h" -#include "llurl.h" -#include "llwindow.h" -#include "llmediaentry.h" -#include "llmediactrl.h" -#include "llpanelcontents.h" -#include "llpermissions.h" -#include "llpluginclassmedia.h" -#include "llfloatermediasettings.h" -#include "llfloatertools.h" -#include "lltrans.h" - -//////////////////////////////////////////////////////////////////////////////// -// -LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : -	mControls( NULL ), -	mAutoLoop( NULL ), -	mFirstClick( NULL ), -	mAutoZoom( NULL ), -	mAutoPlay( NULL ), -	mAutoScale( NULL ), -	mWidthPixels( NULL ), -	mHeightPixels( NULL ), -	mHomeURL( NULL ), -	mCurrentURL( NULL ), -	mAltImageEnable( NULL ), -	mParent( NULL ), -	mMediaEditable(false) -{ -	// build dialog from XML -	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml"); -//	mCommitCallbackRegistrar.add("Media.ResetCurrentUrl",		boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this)); -//	mCommitCallbackRegistrar.add("Media.CommitHomeURL",			boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this));	 - -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLPanelMediaSettingsGeneral::postBuild() -{ -	// connect member vars with UI widgets -    mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY ); -	mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY ); -	mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); -	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); -	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); -	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); -	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); -	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); -	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); -	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); -	mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY ); -	mPreviewMedia = getChild<LLMediaCtrl>("preview_media"); - -	// watch commit action for HOME URL -	childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this); -	childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this); -	// interrogates controls and updates widgets as required -	updateMediaPreview(); -	updateCurrentURL(); - -	return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::draw() -{ -	// housekeeping -	LLPanel::draw(); - -	// enable/disable pixel values image entry based on auto scale checkbox  -	if ( mAutoScale->getValue().asBoolean() == false ) -	{ -		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true ); -		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true ); -	} -	else -	{ -		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false ); -		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false ); -	}; - -	// enable/disable UI based on type of media -	bool reset_button_is_active = true; -	if( mPreviewMedia ) -	{ -		LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin(); -		if( media_plugin ) -		{ -			// some controls are only appropriate for time or browser type plugins -			// so we selectively enable/disable them - need to do it in draw -			// because the information from plugins arrives assynchronously -			bool show_time_controls = media_plugin->pluginSupportsMediaTime(); -			if ( show_time_controls ) -			{ -				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false ); -				reset_button_is_active = false; -				childSetEnabled( "current_url_label", false ); -				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true ); -			} -			else -			{ -				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true ); -				reset_button_is_active = true; -				childSetEnabled( "current_url_label", true ); -				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false ); -			}; -		}; -	}; - -	// current URL can change over time. -//	updateCurrentURL(); - -	LLPermissions perm; -	bool user_can_press_reset = mMediaEditable; - -	// several places modify this widget so we must collect states in one place -	if ( reset_button_is_active ) -	{ -		// user has perms to press reset button and it is active -		if ( user_can_press_reset ) -		{ -			childSetEnabled( "current_url_reset_btn", true ); -		} -		// user does not has perms to press reset button and it is active -		else -		{ -			childSetEnabled( "current_url_reset_btn", false ); -		}; -	} -	else -	// reset button is inactive so we just slam it to off - other states don't matter -	{ -		childSetEnabled( "current_url_reset_btn", false ); -	}; -} - -//////////////////////////////////////////////////////////////////////////////// -// static  -void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable) -{	 -	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; -	self->mAltImageEnable ->clear(); -	self->mAutoLoop->clear(); -	self->mAutoPlay->clear(); -	self->mAutoScale->clear(); -	self->mAutoZoom ->clear(); -	self->mControls->clear(); -	self->mCurrentURL->clear(); -	self->mFirstClick->clear(); -	self->mHeightPixels->clear(); -	self->mHomeURL->clear(); -	self->mWidthPixels->clear(); -	self->mAltImageEnable ->setEnabled(editable); -	self->mAutoLoop ->setEnabled(editable); -	self->mAutoPlay ->setEnabled(editable); -	self->mAutoScale ->setEnabled(editable); -	self->mAutoZoom  ->setEnabled(editable); -	self->mControls ->setEnabled(editable); -	self->mCurrentURL ->setEnabled(editable); -	self->mFirstClick ->setEnabled(editable); -	self->mHeightPixels ->setEnabled(editable); -	self->mHomeURL ->setEnabled(editable); -	self->mWidthPixels ->setEnabled(editable); -	self->mPreviewMedia->unloadMediaSource();  -} - -//////////////////////////////////////////////////////////////////////////////// -// static  -void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable) -{ -	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; -	self->mMediaEditable = editable; - -	//llinfos << "---------------" << llendl; -	//llinfos << ll_pretty_print_sd(media_settings) << llendl; -	//llinfos << "---------------" << llendl; - -	// IF all the faces have media (or all dont have media) -	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) -	{ -		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)  -		{ -			self->clearValues(self, self->mMediaEditable); -			// only show multiple  -			self->mHomeURL ->setText(LLTrans::getString("Multiple Media")); -			return; -		} -		 -	} -	else -	{ -		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)  -		{ -			self->clearValues(self, self->mMediaEditable); -			// only show multiple  -			self->mHomeURL ->setText(LLTrans::getString("Multiple Media")); -			return; -		}			 -		 -	} -	std::string base_key( "" ); -	std::string tentative_key( "" ); - -	struct  -	{ -		std::string key_name; -		LLUICtrl* ctrl_ptr; -		std::string ctrl_type; - -	} data_set [] =  -	{  -        { LLMediaEntry::AUTO_LOOP_KEY,				self->mAutoLoop,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::AUTO_PLAY_KEY,				self->mAutoPlay,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" }, -		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" }, -		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" }, -		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" }, -		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::WIDTH_PIXELS_KEY,			self->mWidthPixels,		"LLSpinCtrl" }, -		{ LLMediaEntry::ALT_IMAGE_ENABLE_KEY,		self->mAltImageEnable,	"LLCheckBoxCtrl" }, -		{ "", NULL , "" } -	}; - -	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) -	{ -		base_key = std::string( data_set[ i ].key_name ); -		tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); -		// TODO: CP - I bet there is a better way to do this using Boost -		if ( media_settings[ base_key ].isDefined() ) -		{ -			if ( data_set[ i ].ctrl_type == "LLLineEditor" ) -			{ -				static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )-> -					setText( media_settings[ base_key ].asString() ); -			} -			else -			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) -				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> -					setValue( media_settings[ base_key ].asBoolean() ); -			else -			if ( data_set[ i ].ctrl_type == "LLComboBox" ) -				static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> -					setCurrentByIndex( media_settings[ base_key ].asInteger() ); -			else -			if ( data_set[ i ].ctrl_type == "LLSpinCtrl" ) -				static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )-> -					setValue( media_settings[ base_key ].asInteger() ); - -			data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable); -			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); -		}; -	}; -	 -	// interrogates controls and updates widgets as required -	self->updateMediaPreview(); -	self->updateCurrentURL(); -} - -//////////////////////////////////////////////////////////////////////////////// -// Helper to set media control to media URL as required -void LLPanelMediaSettingsGeneral::updateMediaPreview() -{ -	if ( mHomeURL->getValue().asString().length() > 0 ) -	{ -		mPreviewMedia->navigateTo( mHomeURL->getValue().asString() ); -	} -	else -	// new home URL will be empty if media is deleted but -	// we still need to clean out the preview. -	{ -		mPreviewMedia->unloadMediaSource(); -	}; -} - -//////////////////////////////////////////////////////////////////////////////// -// Helper to set current URL -void LLPanelMediaSettingsGeneral::updateCurrentURL() -{ -	if( mCurrentURL->getText().empty() ) -	{ -		childSetText( "current_url", mHomeURL->getText() ); -	} -	 -} - -//////////////////////////////////////////////////////////////////////////////// - -// virtual -void LLPanelMediaSettingsGeneral::onClose(bool app_quitting) -{ -	if(mPreviewMedia) -	{ -		mPreviewMedia->unloadMediaSource(); -	} -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata ) -{ -	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; -	self->updateMediaPreview(); -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata) -{ -	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; -	self->navigateHomeSelectedFace(); -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::apply( void* userdata ) -{ -	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; -	self->mHomeURL->onCommit(); -	// build LLSD Fragment -	LLSD media_data_general; -	self->getValues(media_data_general); - -	// this merges contents of LLSD passed in with what's there so this is ok -	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in ) -{ -    fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue(); -    fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue(); -    fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue(); -    fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue(); -    fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue(); -    fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex(); -    fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue(); -    fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue(); -    fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue(); -    fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue(); -    fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent ) -{ -	mParent = parent; -}; - -bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace() -{ -	// HACK: This is directly referencing an impl name.  BAD! -	// This can be removed when we have a truly generic media browser that only  -	// builds an impl based on the type of url it is passed. -	struct functor_navigate_media : public LLSelectedTEGetFunctor< bool> -	{ -		bool get( LLViewerObject* object, S32 face ) -		{ -			if ( object ) -				if ( object->getTE(face) ) -					if ( object->getTE(face)->getMediaData() ) -					{ -						if(object->permModify()) -						{ -							viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID()); -							if(media_impl) -							{ -								media_impl->navigateHome(); -								return true; -							} -						}	 -					} -		   return false; -		 }; -				 -	} functor_navigate_media; -	 -	bool all_face_media_navigated = false; -	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); -	selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated ); -	 -	return all_face_media_navigated; -} - +/**
 + * @file llpanelmediasettingsgeneral.cpp
 + * @brief LLPanelMediaSettingsGeneral class implementation
 + *
 + * $LicenseInfo:firstyear=2009&license=viewergpl$
 + * 
 + * Copyright (c) 2009, 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 "llviewerprecompiledheaders.h"
 +
 +#include "llagent.h"
 +#include "llpanelmediasettingsgeneral.h"
 +#include "llcombobox.h"
 +#include "llcheckboxctrl.h"
 +#include "llspinctrl.h"
 +#include "lluictrlfactory.h"
 +#include "llviewerwindow.h"
 +#include "llviewermedia.h"
 +#include "llsdutil.h"
 +#include "llselectmgr.h"
 +#include "llbutton.h"
 +#include "lltexturectrl.h"
 +#include "llurl.h"
 +#include "llwindow.h"
 +#include "llmediaentry.h"
 +#include "llmediactrl.h"
 +#include "llpanelcontents.h"
 +#include "llpermissions.h"
 +#include "llpluginclassmedia.h"
 +#include "llfloatermediasettings.h"
 +#include "llfloatertools.h"
 +#include "lltrans.h"
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
 +	mControls( NULL ),
 +	mAutoLoop( NULL ),
 +	mFirstClick( NULL ),
 +	mAutoZoom( NULL ),
 +	mAutoPlay( NULL ),
 +	mAutoScale( NULL ),
 +	mWidthPixels( NULL ),
 +	mHeightPixels( NULL ),
 +	mHomeURL( NULL ),
 +	mCurrentURL( NULL ),
 +	mAltImageEnable( NULL ),
 +	mParent( NULL ),
 +	mMediaEditable(false)
 +{
 +	// build dialog from XML
 +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
 +//	mCommitCallbackRegistrar.add("Media.ResetCurrentUrl",		boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this));
 +//	mCommitCallbackRegistrar.add("Media.CommitHomeURL",			boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this));	
 +
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +BOOL LLPanelMediaSettingsGeneral::postBuild()
 +{
 +	// connect member vars with UI widgets
 +    mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
 +	mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
 +	mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
 +	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
 +	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
 +	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
 +	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
 +	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
 +	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
 +	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
 +	mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
 +	mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
 +
 +	// watch commit action for HOME URL
 +	childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
 +	childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
 +	// interrogates controls and updates widgets as required
 +	updateMediaPreview();
 +	updateCurrentURL();
 +
 +	return true;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// virtual
 +LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
 +{
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsGeneral::draw()
 +{
 +	// housekeeping
 +	LLPanel::draw();
 +
 +	// enable/disable pixel values image entry based on auto scale checkbox 
 +	if ( mAutoScale->getValue().asBoolean() == false )
 +	{
 +		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
 +		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
 +	}
 +	else
 +	{
 +		childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
 +		childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
 +	};
 +
 +	// enable/disable UI based on type of media
 +	bool reset_button_is_active = true;
 +	if( mPreviewMedia )
 +	{
 +		LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
 +		if( media_plugin )
 +		{
 +			// some controls are only appropriate for time or browser type plugins
 +			// so we selectively enable/disable them - need to do it in draw
 +			// because the information from plugins arrives assynchronously
 +			bool show_time_controls = media_plugin->pluginSupportsMediaTime();
 +			if ( show_time_controls )
 +			{
 +				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
 +				reset_button_is_active = false;
 +				childSetEnabled( "current_url_label", false );
 +				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
 +			}
 +			else
 +			{
 +				childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
 +				reset_button_is_active = true;
 +				childSetEnabled( "current_url_label", true );
 +				childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
 +			};
 +		};
 +	};
 +
 +	// current URL can change over time.
 +//	updateCurrentURL();
 +
 +	LLPermissions perm;
 +	bool user_can_press_reset = mMediaEditable;
 +
 +	// several places modify this widget so we must collect states in one place
 +	if ( reset_button_is_active )
 +	{
 +		// user has perms to press reset button and it is active
 +		if ( user_can_press_reset )
 +		{
 +			childSetEnabled( "current_url_reset_btn", true );
 +		}
 +		// user does not has perms to press reset button and it is active
 +		else
 +		{
 +			childSetEnabled( "current_url_reset_btn", false );
 +		};
 +	}
 +	else
 +	// reset button is inactive so we just slam it to off - other states don't matter
 +	{
 +		childSetEnabled( "current_url_reset_btn", false );
 +	};
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static 
 +void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
 +{	
 +	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
 +	self->mAltImageEnable ->clear();
 +	self->mAutoLoop->clear();
 +	self->mAutoPlay->clear();
 +	self->mAutoScale->clear();
 +	self->mAutoZoom ->clear();
 +	self->mControls->clear();
 +	self->mCurrentURL->clear();
 +	self->mFirstClick->clear();
 +	self->mHeightPixels->clear();
 +	self->mHomeURL->clear();
 +	self->mWidthPixels->clear();
 +	self->mAltImageEnable ->setEnabled(editable);
 +	self->mAutoLoop ->setEnabled(editable);
 +	self->mAutoPlay ->setEnabled(editable);
 +	self->mAutoScale ->setEnabled(editable);
 +	self->mAutoZoom  ->setEnabled(editable);
 +	self->mControls ->setEnabled(editable);
 +	self->mCurrentURL ->setEnabled(editable);
 +	self->mFirstClick ->setEnabled(editable);
 +	self->mHeightPixels ->setEnabled(editable);
 +	self->mHomeURL ->setEnabled(editable);
 +	self->mWidthPixels ->setEnabled(editable);
 +	self->mPreviewMedia->unloadMediaSource(); 
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static 
 +void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
 +{
 +	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
 +	self->mMediaEditable = editable;
 +
 +	//llinfos << "---------------" << llendl;
 +	//llinfos << ll_pretty_print_sd(media_settings) << llendl;
 +	//llinfos << "---------------" << llendl;
 +
 +	// IF all the faces have media (or all dont have media)
 +	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
 +	{
 +		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
 +		{
 +			self->clearValues(self, self->mMediaEditable);
 +			// only show multiple 
 +			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
 +			return;
 +		}
 +		
 +	}
 +	else
 +	{
 +		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
 +		{
 +			self->clearValues(self, self->mMediaEditable);
 +			// only show multiple 
 +			self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
 +			return;
 +		}			
 +		
 +	}
 +	std::string base_key( "" );
 +	std::string tentative_key( "" );
 +
 +	struct 
 +	{
 +		std::string key_name;
 +		LLUICtrl* ctrl_ptr;
 +		std::string ctrl_type;
 +
 +	} data_set [] = 
 +	{ 
 +        { LLMediaEntry::AUTO_LOOP_KEY,				self->mAutoLoop,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::AUTO_PLAY_KEY,				self->mAutoPlay,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" },
 +		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" },
 +		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" },
 +		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" },
 +		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::WIDTH_PIXELS_KEY,			self->mWidthPixels,		"LLSpinCtrl" },
 +		{ LLMediaEntry::ALT_IMAGE_ENABLE_KEY,		self->mAltImageEnable,	"LLCheckBoxCtrl" },
 +		{ "", NULL , "" }
 +	};
 +
 +	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
 +	{
 +		base_key = std::string( data_set[ i ].key_name );
 +		tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
 +		// TODO: CP - I bet there is a better way to do this using Boost
 +		if ( media_settings[ base_key ].isDefined() )
 +		{
 +			if ( data_set[ i ].ctrl_type == "LLLineEditor" )
 +			{
 +				static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
 +					setText( media_settings[ base_key ].asString() );
 +			}
 +			else
 +			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
 +				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
 +					setValue( media_settings[ base_key ].asBoolean() );
 +			else
 +			if ( data_set[ i ].ctrl_type == "LLComboBox" )
 +				static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
 +					setCurrentByIndex( media_settings[ base_key ].asInteger() );
 +			else
 +			if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
 +				static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
 +					setValue( media_settings[ base_key ].asInteger() );
 +
 +			data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
 +			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
 +		};
 +	};
 +	
 +	// interrogates controls and updates widgets as required
 +	self->updateMediaPreview();
 +	self->updateCurrentURL();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// Helper to set media control to media URL as required
 +void LLPanelMediaSettingsGeneral::updateMediaPreview()
 +{
 +	if ( mHomeURL->getValue().asString().length() > 0 )
 +	{
 +		mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
 +	}
 +	else
 +	// new home URL will be empty if media is deleted but
 +	// we still need to clean out the preview.
 +	{
 +		mPreviewMedia->unloadMediaSource();
 +	};
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// Helper to set current URL
 +void LLPanelMediaSettingsGeneral::updateCurrentURL()
 +{
 +	if( mCurrentURL->getText().empty() )
 +	{
 +		childSetText( "current_url", mHomeURL->getText() );
 +	}
 +	
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +
 +// virtual
 +void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
 +{
 +	if(mPreviewMedia)
 +	{
 +		mPreviewMedia->unloadMediaSource();
 +	}
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
 +{
 +	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
 +
 +	// check url user is trying to enter for home URL will pass whitelist 
 +	// and decline to accept it if it doesn't.
 +	std::string home_url = self->mHomeURL->getValue().asString();
 +	if ( ! self->mParent->passesWhiteList( home_url ) )
 +	{
 +		LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");		
 +		return;
 +	};
 +	
 +	self->updateMediaPreview();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
 +{
 +	LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
 +	self->navigateHomeSelectedFace();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsGeneral::apply( void* userdata )
 +{
 +	LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
 +	self->mHomeURL->onCommit();
 +	// build LLSD Fragment
 +	LLSD media_data_general;
 +	self->getValues(media_data_general);
 +
 +	// this merges contents of LLSD passed in with what's there so this is ok
 +	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
 +{
 +    fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue();
 +    fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
 +    fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
 +    fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
 +    fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
 +    fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
 +    fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
 +    fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
 +    fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
 +    fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
 +    fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
 +{
 +	mParent = parent;
 +};
 +
 +bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
 +{
 +	// HACK: This is directly referencing an impl name.  BAD!
 +	// This can be removed when we have a truly generic media browser that only 
 +	// builds an impl based on the type of url it is passed.
 +	struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
 +	{
 +		bool get( LLViewerObject* object, S32 face )
 +		{
 +			if ( object )
 +				if ( object->getTE(face) )
 +					if ( object->getTE(face)->getMediaData() )
 +					{
 +						if(object->permModify())
 +						{
 +							viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
 +							if(media_impl)
 +							{
 +								media_impl->navigateHome();
 +								return true;
 +							}
 +						}	
 +					}
 +		   return false;
 +		 };
 +				
 +	} functor_navigate_media;
 +	
 +	bool all_face_media_navigated = false;
 +	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
 +	selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
 +	
 +	return all_face_media_navigated;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
 +{
 +	return mHomeURL->getValue().asString(); 
 +}
 +
 diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index 1b60909786..5eb42ffaf4 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -64,6 +64,8 @@ public:  	bool navigateHomeSelectedFace();  	void updateMediaPreview();  	void updateCurrentURL(); + +	const std::string getHomeUrl();  protected:  	LLFloaterMediaSettings* mParent; @@ -76,7 +78,6 @@ private:  	LLComboBox* mControls;  	LLCheckBoxCtrl* mAutoLoop;  	LLCheckBoxCtrl* mFirstClick; -//	LLTextureCtrl* mMediaPreview;  	LLCheckBoxCtrl* mAutoZoom;  	LLCheckBoxCtrl* mAutoPlay;  	LLCheckBoxCtrl* mAutoScale; diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index cea105d7de..f5607aa287 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -1,255 +1,343 @@ -/** - * @file llpanelmediasettingssecurity.cpp - * @brief LLPanelMediaSettingsSecurity class implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - *  - * Copyright (c) 2009, 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 "llviewerprecompiledheaders.h" -#include "llfloaterreg.h" -#include "llpanelmediasettingssecurity.h" -#include "llpanelcontents.h" -#include "llcheckboxctrl.h" -#include "llscrolllistctrl.h" -#include "llscrolllistitem.h" -#include "lluictrlfactory.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llmediaentry.h" -#include "llfloaterwhitelistentry.h" -#include "llfloatermediasettings.h" -//////////////////////////////////////////////////////////////////////////////// -// -LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() -{ -	// build dialog from XML -	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml"); -	mCommitCallbackRegistrar.add("Media.whitelistAdd",		boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this)); -	mCommitCallbackRegistrar.add("Media.whitelistDelete",	boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));	 -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLPanelMediaSettingsSecurity::postBuild() -{ -	mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY ); -	mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY ); - -	childSetAction("whitelist_add", onBtnAdd, this); -	childSetAction("whitelist_del", onBtnDel, this); - -	setDefaultBtn("whitelist_add"); - -	return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -//  -void LLPanelMediaSettingsSecurity::draw() -{ -	// housekeeping -	LLPanel::draw(); - -	// if list is empty, disable DEL button and checkbox to enable use of list -	if ( mWhiteListList->isEmpty() ) -	{ -		childSetEnabled( "whitelist_del", false ); -		childSetEnabled( LLMediaEntry::WHITELIST_KEY, false ); -		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false ); -	} -	else -	{ -		childSetEnabled( "whitelist_del", true ); -		childSetEnabled( LLMediaEntry::WHITELIST_KEY, true ); -		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true ); -	}; - -	// if nothing is selected, disable DEL button -	if ( mWhiteListList->getSelectedValue().asString().empty() ) -	{ -		childSetEnabled( "whitelist_del", false ); -	} -	else -	{ -		childSetEnabled( "whitelist_del", true ); -	}; -} - -//////////////////////////////////////////////////////////////////////////////// -// static  -void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable) -{ -	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; - -	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) -	{ -		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)  -		{ -			self->clearValues(self, editable); -			// only show multiple  -			return; -		} -		 -	} -	else -	{ -		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)  -		{ -			self->clearValues(self, editable); -			// only show multiple  -			return; -		}			 -		 -	} -	std::string base_key( "" ); -	std::string tentative_key( "" ); - -	struct  -	{ -		std::string key_name; -		LLUICtrl* ctrl_ptr; -		std::string ctrl_type; - -	} data_set [] =  +/**
 + * @file llpanelmediasettingssecurity.cpp
 + * @brief LLPanelMediaSettingsSecurity class implementation
 + *
 + * $LicenseInfo:firstyear=2009&license=viewergpl$
 + * 
 + * Copyright (c) 2009, 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 "llviewerprecompiledheaders.h"
 +#include "llfloaterreg.h"
 +#include "llpanelmediasettingssecurity.h"
 +#include "llpanelcontents.h"
 +#include "llcheckboxctrl.h"
 +#include "llscrolllistctrl.h"
 +#include "llscrolllistitem.h"
 +#include "lluictrlfactory.h"
 +#include "llwindow.h"
 +#include "llviewerwindow.h"
 +#include "llsdutil.h"
 +#include "llselectmgr.h"
 +#include "llmediaentry.h"
 +#include "llfloaterwhitelistentry.h"
 +#include "llfloatermediasettings.h"
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() :
 +	mParent( NULL )
 +{
 +	// build dialog from XML
 +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
 +	mCommitCallbackRegistrar.add("Media.whitelistAdd",		boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
 +	mCommitCallbackRegistrar.add("Media.whitelistDelete",	boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));	
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +BOOL LLPanelMediaSettingsSecurity::postBuild()
 +{
 +	mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
 +	mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
 +
 +	childSetAction("whitelist_add", onBtnAdd, this);
 +	childSetAction("whitelist_del", onBtnDel, this);
 +
 +	setDefaultBtn("whitelist_add");
 +
 +	return true;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// virtual
 +LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
 +{
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// 
 +void LLPanelMediaSettingsSecurity::draw()
 +{
 +	// housekeeping
 +	LLPanel::draw();
 +
 +	// if list is empty, disable DEL button and checkbox to enable use of list
 +	if ( mWhiteListList->isEmpty() )
 +	{
 +		childSetEnabled( "whitelist_del", false );
 +		childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
 +		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
 +	}
 +	else
 +	{
 +		childSetEnabled( "whitelist_del", true );
 +		childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
 +		childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
 +	};
 +
 +	// if nothing is selected, disable DEL button
 +	if ( mWhiteListList->getSelectedValue().asString().empty() )
 +	{
 +		childSetEnabled( "whitelist_del", false );
 +	}
 +	else
 +	{
 +		childSetEnabled( "whitelist_del", true );
 +	};
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static 
 +void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
 +{
 +	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
 +
 +	if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
 +	{
 +		if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) 
 +		{
 +			self->clearValues(self, editable);
 +			// only show multiple 
 +			return;
 +		}
 +		
 +	}
 +	else
 +	{
 +		if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) 
 +		{
 +			self->clearValues(self, editable);
 +			// only show multiple 
 +			return;
 +		}			
 +		
 +	}
 +	std::string base_key( "" );
 +	std::string tentative_key( "" );
 +
 +	struct 
 +	{
 +		std::string key_name;
 +		LLUICtrl* ctrl_ptr;
 +		std::string ctrl_type;
 +
 +	} data_set [] = 
 +	{
 +		{ LLMediaEntry::WHITELIST_ENABLE_KEY,	self->mEnableWhiteList,		"LLCheckBoxCtrl" },
 +		{ LLMediaEntry::WHITELIST_KEY,			self->mWhiteListList,		"LLScrollListCtrl" },
 +		{ "", NULL , "" }
 +	};
 +
 +	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
 +	{
 +		base_key = std::string( data_set[ i ].key_name );
 +        tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
 +
 +		// TODO: CP - I bet there is a better way to do this using Boost
 +		if ( media_settings[ base_key ].isDefined() )
 +		{
 +			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
 +			{
 +				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
 +					setValue( media_settings[ base_key ].asBoolean() );
 +			}
 +			else
 +			if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
 +			{
 +				// get control 
 +				LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
 +				list->deleteAllItems();
 +
 +				// points to list of white list URLs
 +				LLSD url_list = media_settings[ base_key ];
 +
 +				// iterate over them and add to scroll list
 +				LLSD::array_iterator iter = url_list.beginArray();
 +				while( iter != url_list.endArray() )
 +				{
 +					// TODO: is iter guaranteed to be valid here?
 +					std::string url = *iter;
 +					list->addSimpleElement( url );
 +					++iter;
 +				};
 +			};
 +			data_set[ i ].ctrl_ptr->setEnabled(editable);
 +			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
 +		};
 +	};
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +// static 
 +void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
 +{
 +	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
 +	self->mEnableWhiteList->clear();
 +	self->mWhiteListList->deleteAllItems();
 +	self->mEnableWhiteList->setEnabled(editable);
 +	self->mWhiteListList->setEnabled(editable);
 +}
 +////////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsSecurity::apply( void* userdata )
 +{
 +	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
 +
 +	// build LLSD Fragment
 +	LLSD media_data_security;
 +	self->getValues(media_data_security);
 +	// this merges contents of LLSD passed in with what's there so this is ok
 +	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////
 +//
 +void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
 +{
 +    fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
 +
 +    // iterate over white list and extract items
 +    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
 +    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
 +    fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
 +    while( iter != white_list_items.end() )
 +    {
 +        std::string white_list_url = (*iter)->getValue().asString();
 +        fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
 +        ++iter;
 +    };
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// Try to make a valid URL if a fragment (
 +// white list list box widget and build a list to test against. Can also
 +const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& src_url )
 +{
 +	// use LLURI to determine if we have a valid scheme
 +	LLURI candidate_url( src_url ); +	if ( candidate_url.scheme().empty() )  	{ -		{ LLMediaEntry::WHITELIST_ENABLE_KEY,	self->mEnableWhiteList,		"LLCheckBoxCtrl" }, -		{ LLMediaEntry::WHITELIST_KEY,			self->mWhiteListList,		"LLScrollListCtrl" }, -		{ "", NULL , "" } +		// build a URL comprised of default scheme and the original fragment 
 +		const std::string default_scheme( "http://" );
 +		return default_scheme + src_url;
  	}; -	for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) -	{ -		base_key = std::string( data_set[ i ].key_name ); -        tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); - -		// TODO: CP - I bet there is a better way to do this using Boost -		if ( media_settings[ base_key ].isDefined() ) -		{ -			if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) -			{ -				static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> -					setValue( media_settings[ base_key ].asBoolean() ); -			} -			else -			if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" ) -			{ -				// get control  -				LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr ); -				list->deleteAllItems(); - -				// points to list of white list URLs -				LLSD url_list = media_settings[ base_key ]; - -				// iterate over them and add to scroll list -				LLSD::array_iterator iter = url_list.beginArray(); -				while( iter != url_list.endArray() ) -				{ -					// TODO: is iter guaranteed to be valid here? -					std::string url = *iter; -					list->addSimpleElement( url ); -					++iter; -				}; -			}; -			data_set[ i ].ctrl_ptr->setEnabled(editable); -			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); -		}; -	}; -} - -//////////////////////////////////////////////////////////////////////////////// -// static  -void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable) -{ -	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; -	self->mEnableWhiteList->clear(); -	self->mWhiteListList->deleteAllItems(); -	self->mEnableWhiteList->setEnabled(editable); -	self->mWhiteListList->setEnabled(editable); -} -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::apply( void* userdata ) -{ -	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; - -	// build LLSD Fragment -	LLSD media_data_security; -	self->getValues(media_data_security); -	// this merges contents of LLSD passed in with what's there so this is ok -	LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security ); -} - +	// we *could* test the "default scheme" + "original fragment" URL again +	// using LLURI to see if it's valid but I think the outcome is the same +	// in either case - our only option is to return the original URL +
 +	// we *think* the original url passed in was valid
 +	return src_url;
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// wrapper for testing a URL against the whitelist. We grab entries from
 +// white list list box widget and build a list to test against. Can also
 +// optionally pass the URL that you are trying to add to the widget since
 +// it won't be added until this call returns.
 +bool LLPanelMediaSettingsSecurity::passesWhiteList( const std::string& added_url,
 +													const std::string& test_url )
 +{
 +	// the checkUrlAgainstWhitelist(..) function works on a vector
 +	// of strings for the white list entries - in this panel, the white list
 +	// is stored in the widgets themselves so we need to build something compatible.
 +	std::vector< std::string > whitelist_strings;
 +	whitelist_strings.clear();	// may not be required - I forget what the spec says.
 +
 +	// step through whitelist widget entries and grab them as strings
 +    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
 +    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin(); 
 +	while( iter != white_list_items.end()  )
 +    {
 +        const std::string whitelist_url = (*iter)->getValue().asString();
 +		whitelist_strings.push_back( whitelist_url );
 +
 +		++iter;
 +    };
 +
 +	// add in the URL that might be added to the whitelist so we can test that too
 +	if ( added_url.length() )
 +		whitelist_strings.push_back( added_url );
 +
 +	// possible the URL is just a fragment so we validize it
 +	const std::string valid_url = makeValidUrl( test_url );
 +
 +	// indicate if the URL passes whitelist
 +	return LLMediaEntry::checkUrlAgainstWhitelist( valid_url, whitelist_strings );
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +//
 +void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
 +{
 +	// grab home URL from the general panel (via the parent floater)
 +	std::string home_url( "" );
 +	if ( mParent )
 +		home_url = mParent->getHomeUrl();
 +
 +	// if the home URL is blank (user hasn't entered it yet) then
 +	// don't bother to check if it passes the white list
 +	if ( home_url.empty() )
 +	{
 +		mWhiteListList->addSimpleElement( url );
 +		return;
 +	};
 +
 +	// if the URL passes the white list, add it
 +	if ( passesWhiteList( url, home_url ) )
 +	{
 +		mWhiteListList->addSimpleElement( url );
 +	}
 +	else
 +	// display a message indicating you can't do that
 +	{
 +		LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
 +	};
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
 +{
 +	LLFloaterReg::showInstance("whitelist_entry");
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// static
 +void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
 +{
 +	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
 +
 +	self->mWhiteListList->deleteSelectedItems();
 +}
 +
  ////////////////////////////////////////////////////////////////////////////////  // -void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in ) -{ -    fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue(); - -    // iterate over white list and extract items -    std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData(); -    std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin(); -    fill_me_in[LLMediaEntry::WHITELIST_KEY].clear(); -    while( iter != white_list_items.end() ) -    { -        std::string white_list_url = (*iter)->getValue().asString(); -        fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url ); -        ++iter; -    }; -} - - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url) -{ -	mWhiteListList->addSimpleElement( url ); -} - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata ) -{ -	LLFloaterReg::showInstance("whitelist_entry"); -} - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata ) +void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent )  { -	LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; +	mParent = parent; +}; -	self->mWhiteListList->deleteSelectedItems(); -} diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h index b7cf67c039..b78ee92193 100644 --- a/indra/newview/llpanelmediasettingssecurity.h +++ b/indra/newview/llpanelmediasettingssecurity.h @@ -37,6 +37,7 @@  class LLCheckBoxCtrl;  class LLScrollListCtrl; +class LLFloaterMediaSettings;  class LLPanelMediaSettingsSecurity : public LLPanel  { @@ -52,6 +53,12 @@ class LLPanelMediaSettingsSecurity : public LLPanel  		static void initValues( void* userdata, const LLSD& media_settings,bool editable );  		static void clearValues( void* userdata, bool editable);  		void addWhiteListItem(const std::string& url); +		void setParent( LLFloaterMediaSettings* parent ); +		const std::string makeValidUrl( const std::string& src_url ); +		bool passesWhiteList( const std::string& added_url, const std::string& test_url );
 + +	protected: +		LLFloaterMediaSettings* mParent;  	private:  		LLCheckBoxCtrl* mEnableWhiteList; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 288cf728b9..1ea9655b26 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -4903,7 +4903,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)  		{  			inspect_item_id = inspect_instance->getSelectedUUID();  		} -		LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID();  		for (S32 pass = 0; pass < 2; pass++)  		{  			for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); @@ -4917,11 +4916,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)  				{  					continue;  				} -				if (objectp->getID() == focus_item_id) -				{ -					node->renderOneSilhouette(gFocusMgr.getFocusColor()); -				} -				else if(objectp->getID() == inspect_item_id) +				if(objectp->getID() == inspect_item_id)  				{  					node->renderOneSilhouette(sHighlightInspectColor);  				} @@ -4975,6 +4970,19 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)  		}  	} +#if 0	 +	// Hilight focused media object +	{ +		LLViewerObject* objectp = LLViewerMediaFocus::getInstance()->getFocusedObject(); +		if(objectp) +		{ +			// FIXME: how do I construct a silhouette for an object that's not selected? +			// Would we need to add another LLObjectSelectionHandle for this purpose? +			node->renderOneSilhouette(gFocusMgr.getFocusColor()); +		} +	} +#endif +  	if (for_hud && avatar)  	{  		glMatrixMode(GL_PROJECTION); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index b015f668e4..b035fd53fd 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -518,11 +518,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)  		if(!object)  		{ -			// We need to clear media hover flag -			if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) -			{ -				LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); -			} +			LLViewerMediaFocus::getInstance()->clearHover();  		}  	} @@ -1029,7 +1025,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)  		pick.mObjectFace < 0 ||   		pick.mObjectFace >= objectp->getNumTEs())   	{ -		LLSelectMgr::getInstance()->deselect();  		LLViewerMediaFocus::getInstance()->clearFocus();  		return false; @@ -1037,11 +1032,7 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) -	// HACK: This is directly referencing an impl name.  BAD! -	// This can be removed when we have a truly generic media browser that only  -	// builds an impl based on the type of url it is passed. - -	// is media playing on this face? +	// Does this face have media?  	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);  	LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;  	viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; @@ -1051,11 +1042,9 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)  		&& gSavedSettings.getBOOL("MediaOnAPrimUI")  		&& media_impl.notNull())  	{ -		// LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection(); -		if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/ -			! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) +		if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )  		{ -			LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); +			LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);  		}  		else  		{ @@ -1067,7 +1056,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)  		return true;  	} -	LLSelectMgr::getInstance()->deselect();  	LLViewerMediaFocus::getInstance()->clearFocus();  	return false; @@ -1081,50 +1069,50 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick)  	LLPointer<LLViewerObject> objectp = pick.getObject(); -	// Early out cases.  Must clear mouse over media focus flag +	// Early out cases.  Must clear media hover.   	// did not hit an object or did not hit a valid face  	if ( objectp.isNull() ||  		pick.mObjectFace < 0 ||   		pick.mObjectFace >= objectp->getNumTEs() )  	{ -		LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); +		LLViewerMediaFocus::getInstance()->clearHover();  		return false;  	} - -	// HACK: This is directly referencing an impl name.  BAD! -	// This can be removed when we have a truly generic media browser that only  -	// builds an impl based on the type of url it is passed. - -	// is media playing on this face? +	// Does this face have media?  	const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);  	const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;  	if (mep  		&& gSavedSettings.getBOOL("MediaOnAPrimUI"))  	{		  		viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); -		if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull()) -		{ -			media_impl->mouseMove(pick.mUVCoords); - -			gViewerWindow->setCursor(media_impl->getLastSetCursor()); -		} -		else +		 +		if(media_impl.notNull())  		{ -			gViewerWindow->setCursor(UI_CURSOR_ARROW); -		} +			// Update media hover object +			if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace)) +			{ +				LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal); +			} +			 +			// If this is the focused media face, send mouse move events. +			if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace)) +			{ +				media_impl->mouseMove(pick.mUVCoords); +				gViewerWindow->setCursor(media_impl->getLastSetCursor()); +			} +			else +			{ +				// This is not the focused face -- set the default cursor. +				gViewerWindow->setCursor(UI_CURSOR_ARROW); +			} -		// Set mouse over flag if unset -		if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag()) -		{ -			LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace); -			LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl); -			LLViewerMediaFocus::getInstance()->setPickInfo(pick); +			return true;  		} - -		return true;  	} -	LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); +	 +	// In all other cases, clear media hover. +	LLViewerMediaFocus::getInstance()->clearHover();  	return false;  } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bac1f170b0..b8cf3e667e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -836,7 +836,15 @@ void LLViewerMediaImpl::stop()  {  	if(mMediaSource)  	{ -		mMediaSource->stop(); +		if(mMediaSource->pluginSupportsMediaBrowser()) +		{ +			mMediaSource->browse_stop(); +		} +		else +		{ +			mMediaSource->stop(); +		} +  		// destroyMediaSource();  	}  } @@ -1010,6 +1018,44 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)  }  ////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateBack() +{ +	if (mMediaSource) +	{ +		if(mMediaSource->pluginSupportsMediaTime()) +		{ +			mMediaSource->start(-2.0); +		} +		else +		{ +			mMediaSource->browse_back(); +		} +	} +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateForward() +{ +	if (mMediaSource) +	{ +		if(mMediaSource->pluginSupportsMediaTime()) +		{ +			mMediaSource->start(2.0); +		} +		else +		{ +			mMediaSource->browse_forward(); +		} +	} +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateReload() +{ +	navigateTo(mMediaURL, "", true, false); +} + +//////////////////////////////////////////////////////////////////////////////////////////  void LLViewerMediaImpl::navigateHome()  {  	navigateTo(mHomeURL, "", true, false); diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 37aabcf2d6..05c67eda47 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -141,7 +141,10 @@ public:  	void mouseMove(const LLVector2& texture_coords);  	void mouseLeftDoubleClick(S32 x,S32 y );  	void mouseCapture(); - +	 +	void navigateBack(); +	void navigateForward(); +	void navigateReload();  	void navigateHome();  	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);  	void navigateStop(); diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index db31714f16..cad8b5f0ce 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -53,7 +53,8 @@  //  LLViewerMediaFocus::LLViewerMediaFocus() -: mMouseOverFlag(false) +:	mFocusedObjectFace(0), +	mHoverObjectFace(0)  {  } @@ -63,110 +64,100 @@ LLViewerMediaFocus::~LLViewerMediaFocus()  	// Clean up in cleanupClass() instead.  } -void LLViewerMediaFocus::cleanupClass() -{ -	LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance(); -	 -	if(self) -	{ -		// mMediaHUD will have been deleted by this point -- don't try to delete it. - -		/* Richard says: -			all widgets are supposed to be destroyed at the same time -			you shouldn't hold on to pointer to them outside of ui code		 -			you can use the LLHandle approach -			if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to -			look at llview::gethandle -			its our version of a weak pointer			 -		*/ -		if(self->mMediaHUD.get()) -		{ -			self->mMediaHUD.get()->setMediaImpl(NULL); -		} -		self->mMediaImpl = NULL; -	} -	 -} - - -void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl ) -{ +void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal) +{	  	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - -	if(mMediaImpl.notNull()) +	 +	LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl(); +	if(old_media_impl)  	{ -		mMediaImpl->focus(false); +		old_media_impl->focus(false);  	} -	if (b && media_impl.notNull()) +	if (media_impl.notNull() && objectp.notNull())  	{  		bool face_auto_zoom = false; -		mMediaImpl = media_impl; -		mMediaImpl->focus(true); +		media_impl->focus(true); -		LLSelectMgr::getInstance()->deselectAll(); -		LLSelectMgr::getInstance()->selectObjectOnly(objectp, face); +		mFocusedImplID = media_impl->getMediaTextureID(); +		mFocusedObjectID = objectp->getID(); +		mFocusedObjectFace = face; +		mFocusedObjectNormal = pick_normal; -		if(objectp.notNull()) +		LLTextureEntry* tep = objectp->getTE(face); +		if(tep->hasMedia())  		{ -			LLTextureEntry* tep = objectp->getTE(face); -			if(! tep->hasMedia()) -			{ -				// Error condition -			}  			LLMediaEntry* mep = tep->getMediaData();  			face_auto_zoom = mep->getAutoZoom(); -			if(! mep->getAutoPlay()) +			if(!media_impl->hasMedia())  			{  				std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();  				media_impl->navigateTo(url, "", true);  			}  		} -		mFocus = LLSelectMgr::getInstance()->getSelection(); +		else +		{ +			// This should never happen. +			llwarns << "Can't find media entry for focused face" << llendl; +		} + +		gFocusMgr.setKeyboardFocus(this); +		 +		// We must do this before  processing the media HUD zoom, or it may zoom to the wrong face.  +		update(); +  		if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())  		{  			mMediaHUD.get()->resetZoomLevel();  			mMediaHUD.get()->nextZoomLevel();  		} -		if (!mFocus->isEmpty()) -		{ -			gFocusMgr.setKeyboardFocus(this); -		} -		mObjectID = objectp->getID(); -		mObjectFace = face; -		// LLViewerMedia::addObserver(this, mObjectID); - -  	}  	else  	{ -		gFocusMgr.setKeyboardFocus(NULL); -		if(! parcel->getMediaPreventCameraZoom()) +		if(hasFocus())  		{ -			if (!mFocus->isEmpty()) +			if(mMediaHUD.get())  			{ -				gAgent.setFocusOnAvatar(TRUE, ANIMATE); +				mMediaHUD.get()->resetZoomLevel();  			} + +			gFocusMgr.setKeyboardFocus(NULL);  		} -		mFocus = NULL; -		// LLViewerMedia::remObserver(this, mObjectID); -		// Null out the media hud media pointer -		if(mMediaHUD.get()) -		{ -			mMediaHUD.get()->setMediaImpl(NULL); -		} +		mFocusedImplID = LLUUID::null; +		mFocusedObjectID = LLUUID::null; +		mFocusedObjectFace = 0; +	} +} -		// and null out the media impl -		mMediaImpl = NULL; -		mObjectID = LLUUID::null; -		mObjectFace = 0; +void LLViewerMediaFocus::clearFocus() +{ +	setFocusFace(NULL, 0, NULL); +} + +void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal) +{ +	if (media_impl.notNull()) +	{ +		mHoverImplID = media_impl->getMediaTextureID(); +		mHoverObjectID = objectp->getID(); +		mHoverObjectFace = face; +		mHoverObjectNormal = pick_normal;  	} -	if(mMediaHUD.get()) +	else  	{ -		mMediaHUD.get()->setMediaFocus(b); +		mHoverObjectID = LLUUID::null; +		mHoverObjectFace = 0; +		mHoverImplID = LLUUID::null;  	}  } + +void LLViewerMediaFocus::clearHover() +{ +	setHoverFace(NULL, 0, NULL); +} + +  bool LLViewerMediaFocus::getFocus()  {  	if (gFocusMgr.getKeyboardFocus() == this) @@ -176,22 +167,15 @@ bool LLViewerMediaFocus::getFocus()  	return false;  } -// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value -void LLViewerMediaFocus::setCameraZoom(F32 padding_factor) +// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value +void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor)  { -	LLPickInfo& pick = LLToolPie::getInstance()->getPick(); - -	if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) -	{ -		pick = mPickInfo; -		setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl); -	} - -	if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) +	if (object)  	{  		gAgent.setFocusOnAvatar(FALSE, ANIMATE); -		LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); +		LLBBox bbox = object->getBoundingBoxAgent(); +		LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());  		F32 height;  		F32 width;  		F32 depth; @@ -199,7 +183,7 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)  		F32 distance;  		// We need the aspect ratio, and the 3 components of the bbox as height, width, and depth. -		F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &depth); +		F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth);  		F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();  		// We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for  @@ -227,93 +211,97 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)  		distance += depth * 0.5;  		// Finally animate the camera to this new position and focal point -		gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(pick.mNormal * distance),  -			LLSelectMgr::getInstance()->getSelectionCenterGlobal(), LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID ); +		LLVector3d camera_pos, target_pos; +		// The target lookat position is the center of the selection (in global coords) +		target_pos = center; +		// Target look-from (camera) position is "distance" away from the target along the normal  +		LLVector3d pickNormal = LLVector3d(normal); +		pickNormal.normalize(); +        camera_pos = target_pos + pickNormal * distance; +        if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg) +        { +			// If the normal points directly up, the camera will "flip" around. +			// We try to avoid this by adjusting the target camera position a  +			// smidge towards current camera position +			// *NOTE: this solution is not perfect.  All it attempts to solve is the +			// "looking down" problem where the camera flips around when it animates +			// to that position.  You still are not guaranteed to be looking at the +			// media in the correct orientation.  What this solution does is it will +			// put the camera into position keeping as best it can the current  +			// orientation with respect to the face.  In other words, if before zoom +			// the media appears "upside down" from the camera, after zooming it will +			// still be upside down, but at least it will not flip. +            LLVector3d cur_camera_pos = LLVector3d(gAgent.getCameraPositionGlobal()); +            LLVector3d delta = (cur_camera_pos - camera_pos); +            F64 len = delta.length(); +            delta.normalize(); +            // Move 1% of the distance towards original camera location +            camera_pos += 0.01 * len * delta; +        } + +		gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() ); +	} +	else +	{ +		// If we have no object, focus back on the avatar. +		gAgent.setFocusOnAvatar(TRUE, ANIMATE);  	}  }  void LLViewerMediaFocus::onFocusReceived()  { -	if(mMediaImpl.notNull()) -		mMediaImpl->focus(true); +	// Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media. +//	LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +//	if(media_impl.notNull()) +//		media_impl->focus(true);  	LLFocusableElement::onFocusReceived();  }  void LLViewerMediaFocus::onFocusLost()  { -	if(mMediaImpl.notNull()) -		mMediaImpl->focus(false); +	// Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media. +//	LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +//	if(media_impl.notNull()) +//		media_impl->focus(false); +  	gViewerWindow->focusClient(); -	mFocus = NULL;  	LLFocusableElement::onFocusLost();  } -void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl) + +BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)  { -	if (b && media_impl.notNull()) +	LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +	if(media_impl)  	{ -		if(! mMediaHUD.get()) -		{ -			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl); -			mMediaHUD = media_hud->getHandle(); -			gHUDView->addChild(media_hud);	 -		} -		mMediaHUD.get()->setMediaImpl(media_impl); +		media_impl->handleKeyHere(key, mask); -		if(mMediaImpl.notNull() && (mMediaImpl != media_impl)) +		if (key == KEY_ESCAPE)  		{ -			mMediaImpl->focus(false); +			clearFocus();  		} - -		mMediaImpl = media_impl; -	} -	mMouseOverFlag = b; -} -LLUUID LLViewerMediaFocus::getSelectedUUID()  -{  -	LLViewerObject* object = mFocus->getFirstObject(); -	return object ? object->getID() : LLUUID::null;  -} -#if 0 // Must re-implement when the new media api event system is ready -void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in ) -{ -	if (hasFocus() && mLastURL != event_in.getStringValue()) -	{ -		LLViewerMedia::focus(true, mObjectID); -		// spoof mouse event to reassert focus -		LLViewerMedia::mouseDown(1,1, mObjectID); -		LLViewerMedia::mouseUp(1,1, mObjectID); -	} -	mLastURL = event_in.getStringValue(); -} -#endif -BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) -{ -	if(mMediaImpl.notNull()) -		mMediaImpl->handleKeyHere(key, mask); - -	if (key == KEY_ESCAPE && mMediaHUD.get()) -	{ -		mMediaHUD.get()->close();  	} +	  	return true;  }  BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)  { -	if(mMediaImpl.notNull()) -		mMediaImpl->handleUnicodeCharHere(uni_char); +	LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +	if(media_impl) +		media_impl->handleUnicodeCharHere(uni_char);  	return true;  }  BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)  {  	BOOL retval = FALSE; -	if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia()) +	LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +	if(media_impl && media_impl->hasMedia())  	{          // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.          // The latter is the position of the mouse at the time of the event          // The former is the 'scroll amount' in x and y, respectively.          // All we have for 'scroll amount' here is 'clicks', and no mask. -		mMediaImpl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0); +		media_impl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0);  		retval = TRUE;  	}  	return retval; @@ -321,19 +309,45 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)  void LLViewerMediaFocus::update()  { -	if (mMediaHUD.get()) +	LLViewerMediaImpl *media_impl = getFocusedMediaImpl(); +	LLViewerObject *viewer_object = getFocusedObject(); +	S32 face = mFocusedObjectFace; +	LLVector3 normal = mFocusedObjectNormal; +	bool focus = true; +	 +	if(!media_impl || !viewer_object) +	{ +		focus = false; +		media_impl = getHoverMediaImpl(); +		viewer_object = getHoverObject(); +		face = mHoverObjectFace; +		normal = mHoverObjectNormal; +	} +	 +	if(media_impl && viewer_object)  	{ -		if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver()) +		// We have an object and impl to point at. +		 +		// Make sure the media HUD object exists. +		if(! mMediaHUD.get())  		{ -			// mMediaHUD.get()->setVisible(true); -			mMediaHUD.get()->updateShape(); +			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(); +			mMediaHUD = media_hud->getHandle(); +			gHUDView->addChild(media_hud);	  		} -		else +		mMediaHUD.get()->setMediaFace(viewer_object, face, media_impl, normal); +	} +	else +	{ +		// The media HUD is no longer needed. +		if(mMediaHUD.get())  		{ -			mMediaHUD.get()->setVisible(false); +			mMediaHUD.get()->setMediaFace(NULL, 0, NULL);  		}  	}  } + +  // This function calculates the aspect ratio and the world aligned components of a selection bounding box.  F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)  { @@ -402,5 +416,31 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3&  bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face)  { -	return objectp->getID() == mObjectID && face == mObjectFace; +	return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace; +} + +bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face) +{ +	return objectp->getID() == mHoverObjectID && face == mHoverObjectFace; +} + + +LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl() +{ +	return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID); +} + +LLViewerObject* LLViewerMediaFocus::getFocusedObject() +{ +	return gObjectList.findObject(mFocusedObjectID); +} + +LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl() +{ +	return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID); +} + +LLViewerObject* LLViewerMediaFocus::getHoverObject() +{ +	return gObjectList.findObject(mHoverObjectID);  } diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index 2688a8b708..c77533ba5a 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -50,44 +50,55 @@ public:  	LLViewerMediaFocus();  	~LLViewerMediaFocus(); -	static void cleanupClass(); - -	void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl); -	void clearFocus() { setFocusFace(false, NULL, 0, NULL); } +	// Set/clear the face that has media focus (takes keyboard input and has the full set of controls) +	void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); +	void clearFocus(); +	 +	// Set/clear the face that has "media hover" (has the mimimal set of controls to zoom in or pop out into a media browser). +	// If a media face has focus, the media hover will be ignored. +	void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); +	void clearHover(); +	  	/*virtual*/ bool	getFocus(); -	/*virtual*/ // void onNavigateComplete( const EventType& event_in ); -  	/*virtual*/ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);  	/*virtual*/ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);  	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); -	LLUUID getSelectedUUID(); -	LLObjectSelectionHandle getSelection() { return mFocus; } -  	void update(); +	 +	static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor); +	static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); -	void setCameraZoom(F32 padding_factor); -	void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL); -	bool getMouseOverFlag() { return mMouseOverFlag; } -	void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; } -	F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); - -	// TODO: figure out why selection mgr hates me  	bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face); +	bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face); +	 +	// These look up (by uuid) and return the values that were set with setFocusFace.  They will return null if the objects have been destroyed. +	LLViewerMediaImpl* getFocusedMediaImpl(); +	LLViewerObject* getFocusedObject(); +	S32 getFocusedFace() { return mFocusedObjectFace; } +	 +	// These look up (by uuid) and return the values that were set with setHoverFace.  They will return null if the objects have been destroyed. +	LLViewerMediaImpl* getHoverMediaImpl(); +	LLViewerObject* getHoverObject(); +	S32 getHoverFace() { return mHoverObjectFace; }  protected:  	/*virtual*/ void	onFocusReceived();  	/*virtual*/ void	onFocusLost();  private: -	LLObjectSelectionHandle mFocus; -	std::string mLastURL; -	bool mMouseOverFlag; -	LLPickInfo mPickInfo; +	  	LLHandle<LLPanelMediaHUD> mMediaHUD; -	LLUUID mObjectID; -	S32 mObjectFace; -	viewer_media_t mMediaImpl; +	 +	LLUUID mFocusedObjectID; +	S32 mFocusedObjectFace; +	LLUUID mFocusedImplID; +	LLVector3 mFocusedObjectNormal; +	 +	LLUUID mHoverObjectID; +	S32 mHoverObjectFace; +	LLUUID mHoverImplID; +	LLVector3 mHoverObjectNormal;  }; diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 9bcdcbf9ad..6233a337a6 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -552,6 +552,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent  			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;  		};  		break; +		 +		case MEDIA_EVENT_NAME_CHANGED: +		{ +			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; +		}; +		break;  	};  } diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 93a0b917f9..98dd2ddd79 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1109,6 +1109,14 @@              <menu_item_call.on_click               function="Advanced.RebakeTextures" />          </menu_item_call> +        <menu_item_call +           label="Set UI Size to Default" +           layout="topleft" +           name="Set UI Size to Default"> +          <menu_item_call.on_click +             function="View.DefaultUISize" /> +        </menu_item_call> +        <menu_item_separator/>          <menu_item_check           label="Limit Select Distance"           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 95dd8677b4..9dcd94eb20 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -675,6 +675,19 @@ To place the media on only one face, choose Select Texture and click on the desi    <notification     icon="alertmodal.tga" +   name="WhiteListInvalidatesHomeUrl" +   type="alertmodal"> +Adding this entry to the whitelist will invalidate the home URL you +specified for this instance of media. You are not allowed to do this +so the entry cannot be added to the whitelist. +    <usetemplate +     name="okbutton" +     yestext="Ok"/> +  </notification> + + +  <notification +   icon="alertmodal.tga"     name="MustBeInParcel"     type="alertmodal">  You must be standing inside the land parcel to set its Landing Point. diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index ba66b449f3..234422b68a 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -138,6 +138,8 @@ LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int wind  	mMediaBrowserControlBackButtonFlag( true ),  	mMediaBrowserControlForwardButtonFlag( true ),  	mHomeWebUrl( "http://www.google.com/" ) +	//mHomeWebUrl( "file:///C|/Program Files/QuickTime/Sample.mov" ) +	//mHomeWebUrl( "http://movies.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov" )  {  	// debugging spam  	std::cout << std::endl << "             GLUT version: " << "3.7.6" << std::endl;	// no way to get real version from GLUT @@ -2008,6 +2010,11 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e  			std::cerr <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;  		break; +		case MEDIA_EVENT_NAME_CHANGED: +			std::cerr <<  "Media event:  MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl; +			glutSetWindowTitle( self->getMediaName().c_str() ); +		break; +  		case MEDIA_EVENT_LOCATION_CHANGED:  		{  			std::cerr <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl; | 
