From e89d6d9d667a3fb7eb5d56cdfa1e00ed0d134098 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 6 May 2011 14:39:16 +0200 Subject: [PATCH] Split plugin classes and derive AIFilePicker from BasicPluginBase (part 1). This commit contains all changes, except those in indra/media_plugins (which was renamed to indra/plugins) and indra/llplugin. However, it does contain the (new) file indra/plugins/filepicker/basic_plugin_filepicker.cpp --- doc/contributions.txt | 1 + indra/CMakeLists.txt | 4 +- indra/cmake/BasicPluginBase.cmake | 8 + indra/cmake/MediaPluginBase.cmake | 8 +- indra/newview/CMakeLists.txt | 7 + indra/newview/lldirpicker.cpp | 28 +- indra/newview/lldirpicker.h | 16 +- indra/newview/llfilepicker.cpp | 64 ++- indra/newview/llfilepicker.h | 30 +- indra/newview/llfloatersnapshot.cpp | 12 +- indra/newview/llmediactrl.h | 2 +- indra/newview/llviewermedia.cpp | 338 +++++++--------- indra/newview/llviewermedia.h | 33 +- indra/newview/llviewermediaeventemitter.cpp | 85 ++++ indra/newview/llviewermediaeventemitter.h | 56 +++ indra/newview/llviewermediaobserver.cpp | 47 +++ indra/newview/llviewermenufile.cpp | 2 - indra/newview/llviewerparcelmedia.h | 2 +- indra/newview/llviewerpluginmanager.cpp | 56 +++ indra/newview/llviewerpluginmanager.h | 115 ++++++ indra/newview/llviewerwindow.cpp | 55 ++- indra/newview/llviewerwindow.h | 9 +- indra/newview/statemachine/aifilepicker.cpp | 369 ++++++++++++++++++ indra/newview/statemachine/aifilepicker.h | 160 ++++++++ indra/newview/viewer_manifest.py | 19 +- .../filepicker/basic_plugin_filepicker.cpp | 243 ++++++++++++ 26 files changed, 1432 insertions(+), 337 deletions(-) create mode 100644 indra/cmake/BasicPluginBase.cmake create mode 100644 indra/newview/llviewermediaeventemitter.cpp create mode 100644 indra/newview/llviewermediaeventemitter.h create mode 100644 indra/newview/llviewermediaobserver.cpp create mode 100644 indra/newview/llviewerpluginmanager.cpp create mode 100644 indra/newview/llviewerpluginmanager.h create mode 100644 indra/newview/statemachine/aifilepicker.cpp create mode 100644 indra/newview/statemachine/aifilepicker.h create mode 100644 indra/plugins/filepicker/basic_plugin_filepicker.cpp diff --git a/doc/contributions.txt b/doc/contributions.txt index ea148abd9..53ab212d8 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -113,6 +113,7 @@ Aleric Inglewood IMP-664 IMP-670 IMP-701 + IMP-702 IMP-734 IMP-735 Alissa Sabre diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index f88aa1fa0..c23a03e6a 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -76,8 +76,8 @@ if (VIEWER) add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) add_subdirectory(${LIBS_OPEN_PREFIX}llui) - # viewer media plugins - add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) + # viewer plugins directory + add_subdirectory(${LIBS_OPEN_PREFIX}plugins) # llplugin testbed code (is this the right way to include it?) #if (NOT LINUX) diff --git a/indra/cmake/BasicPluginBase.cmake b/indra/cmake/BasicPluginBase.cmake new file mode 100644 index 000000000..a4f339272 --- /dev/null +++ b/indra/cmake/BasicPluginBase.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + + +set(BASIC_PLUGIN_BASE_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/plugins/base_basic/ + ) + +set(BASIC_PLUGIN_BASE_LIBRARIES basic_plugin_base) diff --git a/indra/cmake/MediaPluginBase.cmake b/indra/cmake/MediaPluginBase.cmake index 2be035b64..7e2d30dfa 100644 --- a/indra/cmake/MediaPluginBase.cmake +++ b/indra/cmake/MediaPluginBase.cmake @@ -1,8 +1,6 @@ # -*- cmake -*- +include(BasicPluginBase) -set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/media_plugins/base/ - ) - -set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base) +set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS ${LIBS_OPEN_DIR}/plugins/base_media ${BASIC_PLUGIN_BASE_INCLUDE_DIRS}) +set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base ${BASIC_PLUGIN_BASE_LIBRARIES}) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 628ee9ec4..3599a1d3d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -442,6 +442,8 @@ set(viewer_SOURCE_FILES llviewerkeyboard.cpp llviewerlayer.cpp llviewermedia.cpp + llviewermediaeventemitter.cpp + llviewermediaobserver.cpp llviewermediafocus.cpp llviewermedia_streamingaudio.cpp llviewermenu.cpp @@ -456,6 +458,7 @@ set(viewer_SOURCE_FILES llviewerparceloverlay.cpp llviewerpartsim.cpp llviewerpartsource.cpp + llviewerpluginmanager.cpp llviewerregion.cpp llviewershadermgr.cpp llviewerstats.cpp @@ -918,6 +921,7 @@ set(viewer_HEADER_FILES llviewerkeyboard.h llviewerlayer.h llviewermedia.h + llviewermediaeventemitter.h llviewermediaobserver.h llviewermediafocus.h llviewermenu.h @@ -932,6 +936,7 @@ set(viewer_HEADER_FILES llviewerparceloverlay.h llviewerpartsim.h llviewerpartsource.h + llviewerpluginmanager.h llviewerprecompiledheaders.h llviewerregion.h llviewershadermgr.h @@ -1007,9 +1012,11 @@ source_group("CMake Rules" FILES ViewerInstall.cmake) set(statemachine_SOURCE_FILES statemachine/aistatemachine.cpp + statemachine/aifilepicker.cpp ) set(statemachine_HEADER_FILES statemachine/aistatemachine.h + statemachine/aifilepicker.h ) list(APPEND viewer_SOURCE_FILES ${statemachine_SOURCE_FILES}) list(APPEND viewer_HEADER_FILES ${statemachine_HEADER_FILES}) diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 8b0ed39eb..3840b52bd 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -269,48 +269,36 @@ void LLDirPicker::reset() LLDirPicker::LLDirPicker() { - mFilePicker = new LLFilePicker(); reset(); } LLDirPicker::~LLDirPicker() { - delete mFilePicker; } void LLDirPicker::reset() { - if (mFilePicker) - mFilePicker->reset(); + LLFilePickerBase::reset(); } BOOL LLDirPicker::getDir(std::string* filename) { reset(); - if (mFilePicker) + GtkWindow* picker = buildFilePicker(false, true, "dirpicker"); + if (picker) { - GtkWindow* picker = mFilePicker->buildFilePicker(false, true, - "dirpicker"); - - if (picker) - { - gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str()); - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - return (!mFilePicker->getFirstFile().empty()); - } + gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str()); + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + return (!getFirstFile().empty()); } return FALSE; } std::string LLDirPicker::getDirName() { - if (mFilePicker) - { - return mFilePicker->getFirstFile(); - } - return ""; + return getFirstFile(); } #else // not implemented diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index 26f76915a..cdee1d094 100644 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -57,9 +57,15 @@ #include #endif -class LLFilePicker; +#if LL_LINUX || LL_SOLARIS +#include "llfilepicker.h" +#endif class LLDirPicker +#if LL_LINUX || LL_SOLARIS + // On Linux we just implement LLDirPicker on top of LLFilePickerBase + : public LLFilePickerBase +#endif { public: // calling this before main() is undefined @@ -90,19 +96,13 @@ private: #endif -#if LL_LINUX || LL_SOLARIS - // On Linux we just implement LLDirPicker on top of LLFilePicker - LLFilePicker *mFilePicker; -#endif - std::string* mFileName; std::string mDir; BOOL mLocked; static LLDirPicker sInstance; -public: - // don't call these directly please. +private: LLDirPicker(); ~LLDirPicker(); }; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 5cea197ca..fb327e5a6 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -70,7 +70,7 @@ LLFilePicker LLFilePicker::sInstance; // // Implementation // -LLFilePicker::LLFilePicker() +LLFilePickerBase::LLFilePickerBase() : mCurrentFile(0), mLocked(FALSE) @@ -108,19 +108,13 @@ LLFilePicker::LLFilePicker() #endif } -LLFilePicker::~LLFilePicker() -{ - // nothing -} - - -const std::string LLFilePicker::getFirstFile() +const std::string LLFilePickerBase::getFirstFile() { mCurrentFile = 0; return getNextFile(); } -const std::string LLFilePicker::getNextFile() +const std::string LLFilePickerBase::getNextFile() { if (mCurrentFile >= getFileCount()) { @@ -133,7 +127,7 @@ const std::string LLFilePicker::getNextFile() } } -const std::string LLFilePicker::getCurFile() +const std::string LLFilePickerBase::getCurFile() { if (mCurrentFile >= getFileCount()) { @@ -146,7 +140,7 @@ const std::string LLFilePicker::getCurFile() } } -void LLFilePicker::reset() +void LLFilePickerBase::reset() { mLocked = FALSE; mFiles.clear(); @@ -155,7 +149,7 @@ void LLFilePicker::reset() #if LL_WINDOWS -BOOL LLFilePicker::setupFilter(ELoadFilter filter) +BOOL LLFilePickerBase::setupFilter(ELoadFilter filter) { BOOL res = TRUE; switch (filter) @@ -220,7 +214,7 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) return res; } -BOOL LLFilePicker::getOpenFile(ELoadFilter filter) +BOOL LLFilePickerBase::getOpenFile(ELoadFilter filter) { if( mLocked ) { @@ -258,7 +252,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter) return success; } -BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) +BOOL LLFilePickerBase::getMultipleOpenFiles(ELoadFilter filter) { if( mLocked ) { @@ -321,7 +315,7 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) return success; } -BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) +BOOL LLFilePickerBase::getSaveFile(ESaveFilter filter, const std::string& filename) { if( mLocked ) { @@ -735,7 +729,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) #elif LL_DARWIN -Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) +Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) { Boolean result = true; ELoadFilter filter = *((ELoadFilter*) callBackUD); @@ -832,7 +826,7 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB return result; } -OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter) +OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter) { OSStatus error = noErr; NavDialogRef navRef = NULL; @@ -887,7 +881,7 @@ OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter) return error; } -OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename) +OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string& filename) { OSStatus error = noErr; NavDialogRef navRef = NULL; @@ -1059,7 +1053,7 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& fi return error; } -BOOL LLFilePicker::getOpenFile(ELoadFilter filter) +BOOL LLFilePickerBase::getOpenFile(ELoadFilter filter) { if( mLocked ) return FALSE; @@ -1088,7 +1082,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter) return success; } -BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) +BOOL LLFilePickerBase::getMultipleOpenFiles(ELoadFilter filter) { if( mLocked ) return FALSE; @@ -1119,7 +1113,7 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) return success; } -BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) +BOOL LLFilePickerBase::getSaveFile(ESaveFilter filter, const std::string& filename) { if( mLocked ) return FALSE; @@ -1152,13 +1146,13 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) # if LL_GTK // static -void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data) +void LLFilePickerBase::add_to_selectedfiles(gpointer data, gpointer user_data) { // We need to run g_filename_to_utf8 in the user's locale std::string saved_locale(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); - LLFilePicker* picker = (LLFilePicker*) user_data; + LLFilePickerBase* picker = (LLFilePickerBase*) user_data; GError *error = NULL; gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, -1, NULL, NULL, &error); @@ -1189,7 +1183,7 @@ void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data) } // static -void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data) +void LLFilePickerBase::chooser_responder(GtkWidget *widget, gint response, gpointer user_data) { LLFilePicker* picker = (LLFilePicker*)user_data; @@ -1212,7 +1206,7 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer } -GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context) +GtkWindow* LLFilePickerBase::buildFilePicker(bool is_save, bool is_folder, std::string context) { if (LLWindowSDL::ll_try_gtk_init()) { @@ -1270,7 +1264,7 @@ GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::stri g_signal_connect (GTK_FILE_CHOOSER(win), "response", - G_CALLBACK(LLFilePicker::chooser_responder), + G_CALLBACK(LLFilePickerBase::chooser_responder), this); gtk_window_set_modal(GTK_WINDOW(win), TRUE); @@ -1346,7 +1340,7 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) } -BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +BOOL LLFilePickerBase::getSaveFile( ESaveFilter filter, const std::string& filename ) { BOOL rtn = FALSE; @@ -1435,7 +1429,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename return rtn; } -BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) +BOOL LLFilePickerBase::getOpenFile( ELoadFilter filter ) { BOOL rtn = FALSE; @@ -1479,7 +1473,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) return rtn; } -BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) +BOOL LLFilePickerBase::getMultipleOpenFiles( ELoadFilter filter ) { BOOL rtn = FALSE; @@ -1511,7 +1505,7 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with // static results, when we don't have a real filepicker. -BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +BOOL LLFilePickerBase::getSaveFile( ESaveFilter filter, const std::string& filename ) { reset(); @@ -1525,7 +1519,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename return FALSE; } -BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) +BOOL LLFilePickerBase::getOpenFile( ELoadFilter filter ) { reset(); @@ -1543,7 +1537,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) return TRUE; } -BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) +BOOL LLFilePickerBase::getMultipleOpenFiles( ELoadFilter filter ) { reset(); return FALSE; @@ -1553,19 +1547,19 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) #else // not implemented -BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +BOOL LLFilePickerBase::getSaveFile( ESaveFilter filter, const std::string& filename ) { reset(); return FALSE; } -BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) +BOOL LLFilePickerBase::getOpenFile( ELoadFilter filter ) { reset(); return FALSE; } -BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) +BOOL LLFilePickerBase::getMultipleOpenFiles( ELoadFilter filter ) { reset(); return FALSE; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index feba53423..8063a7068 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -69,16 +69,11 @@ #include "SDL/SDL_syswm.h" #endif -class LLFilePicker +// This class is used as base class of a singleton and is therefore not +// allowed to have any static members or static local variables! +class LLFilePickerBase { -#ifdef LL_GTK - friend class LLDirPicker; - friend void chooser_responder(GtkWidget *, gint, gpointer); -#endif // LL_GTK public: - // calling this before main() is undefined - static LLFilePicker& instance( void ) { return sInstance; } - enum ELoadFilter { FFLOAD_ALL = 1, @@ -212,8 +207,6 @@ private: S32 mCurrentFile; BOOL mLocked; BOOL mMultiFile; - - static LLFilePicker sInstance; protected: #if LL_GTK @@ -221,10 +214,21 @@ protected: std::string context = "generic"); #endif +protected: + LLFilePickerBase(); +}; + +// True singleton, private constructors (and no friends). +class LLFilePicker : public LLFilePickerBase +{ public: - // don't call these directly please. - LLFilePicker(); - ~LLFilePicker(); + // calling this before main() is undefined + static LLFilePicker& instance( void ) { return sInstance; } + +private: + static LLFilePicker sInstance; + + LLFilePicker() { } }; #endif diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 5af0de858..2d4ed9939 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -149,7 +149,7 @@ public: void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); LLFloaterPostcard* savePostcard(); void saveTexture(); - BOOL saveLocal(); + void saveLocal(); BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; @@ -1005,20 +1005,14 @@ void LLSnapshotLivePreview::saveTexture() mDataSize = 0; } -BOOL LLSnapshotLivePreview::saveLocal() +void LLSnapshotLivePreview::saveLocal() { - BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); + gViewerWindow->saveImageNumbered(mFormattedImage); // Relinquish image memory. Save button will be disabled as a side-effect. mFormattedImage = NULL; mDataSize = 0; updateSnapshot(FALSE, FALSE); - - if(success) - { - gViewerWindow->playSnapshotAnimAndSound(); - } - return success; } ///---------------------------------------------------------------------------- diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index f185fb9b9..bbf2dfa01 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -34,7 +34,7 @@ #define LL_LLMediaCtrl_H #include "llviewermedia.h" - +#include "llviewermediaobserver.h" #include "lluictrl.h" #include "llframetimer.h" #include "lldynamictexture.h" diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 035bdebe1..ca21f6d0c 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -47,84 +47,12 @@ #include "lluuid.h" #include "llkeyboard.h" - // Merov: Temporary definitions while porting the new viewer media code to Snowglobe const int LEFT_BUTTON = 0; const int RIGHT_BUTTON = 1; -// Move this to its own file. - -LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() -{ - observerListType::iterator iter = mObservers.begin(); - - while( iter != mObservers.end() ) - { - LLViewerMediaObserver *self = *iter; - iter++; - remObserver(self); - } -} - /////////////////////////////////////////////////////////////////////////////// -// -bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer ) -{ - if ( ! observer ) - return false; - - if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() ) - return false; - - mObservers.push_back( observer ); - observer->mEmitters.push_back( this ); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer ) -{ - if ( ! observer ) - return false; - - mObservers.remove( observer ); - observer->mEmitters.remove(this); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event ) -{ - observerListType::iterator iter = mObservers.begin(); - - while( iter != mObservers.end() ) - { - LLViewerMediaObserver *self = *iter; - ++iter; - self->handleMediaEvent( media, event ); - } -} - -// Move this to its own file. -LLViewerMediaObserver::~LLViewerMediaObserver() -{ - std::list::iterator iter = mEmitters.begin(); - - while( iter != mEmitters.end() ) - { - LLViewerMediaEventEmitter *self = *iter; - iter++; - self->remObserver( this ); - } -} - - -// Move this to its own file. -// helper class that tries to download a URL from a web site and calls a method +// Helper class that tries to download a URL from a web site and calls a method // on the Panel Land Media and to discover the MIME type class LLMimeDiscoveryResponder : public LLHTTPClient::Responder { @@ -279,9 +207,10 @@ void LLViewerMedia::updateBrowserUserAgent() for(; iter != end; iter++) { LLViewerMediaImpl* pimpl = *iter; - if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser()) + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + if(plugin && plugin->pluginSupportsMediaBrowser()) { - pimpl->mMediaSource->setBrowserUserAgent(user_agent); + plugin->setBrowserUserAgent(user_agent); } } @@ -366,7 +295,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, U8 media_loop, const std::string& mime_type) : - mMediaSource( NULL ), mMovieImageHasMips(false), mTextureId(texture_id), mMediaWidth(media_width), @@ -399,7 +327,7 @@ LLViewerMediaImpl::~LLViewerMediaImpl() ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) { - if((mMediaSource == NULL) || (mMimeType != mime_type)) + if((mPluginBase == NULL) || (mMimeType != mime_type)) { if(! initializePlugin(mime_type)) { @@ -413,7 +341,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) } // play(); - return (mMediaSource != NULL); + return (mPluginBase != NULL); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -434,14 +362,13 @@ void LLViewerMediaImpl::createMediaSource() void LLViewerMediaImpl::destroyMediaSource() { mNeedsNewTexture = true; - if(! mMediaSource) + if (!mPluginBase) { return; } // Restore the texture updateMovieImage(LLUUID::null, false); - delete mMediaSource; - mMediaSource = NULL; + destroyPlugin(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -514,16 +441,17 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ LLNotifications::instance().add("NoPlugin", args); return NULL; -} +} ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { // Save the previous media source's last set size before destroying it. - mMediaWidth = mMediaSource->getSetWidth(); - mMediaHeight = mMediaSource->getSetHeight(); + mMediaWidth = plugin->getSetWidth(); + mMediaHeight = plugin->getSetHeight(); } // Always delete the old media impl first. @@ -541,7 +469,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->setAutoScale(mMediaAutoScale); media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); - mMediaSource = media_source; + mPluginBase = media_source; return true; } @@ -550,34 +478,38 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) void LLViewerMediaImpl::setSize(int width, int height) { + LLPluginClassMedia* plugin = getMediaPlugin(); mMediaWidth = width; mMediaHeight = height; - if(mMediaSource) + if (plugin) { - mMediaSource->setSize(width, height); + plugin->setSize(width, height); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::play() { + LLPluginClassMedia* plugin = getMediaPlugin(); + // first stop any previously playing media // stop(); - // mMediaSource->addObserver( this ); - if(mMediaSource == NULL) + // plugin->addObserver( this ); + if (!plugin) { if(!initializePlugin(mMimeType)) { // Plugin failed initialization... should assert or something return; } + plugin = getMediaPlugin(); } // updateMovieImage(mTextureId, true); - mMediaSource->loadURI( mMediaURL ); - if(/*mMediaSource->pluginSupportsMediaTime()*/ true) + plugin->loadURI( mMediaURL ); + if(/*plugin->pluginSupportsMediaTime()*/ true) { start(); } @@ -586,9 +518,10 @@ void LLViewerMediaImpl::play() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::stop() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->stop(); + plugin->stop(); // destroyMediaSource(); } } @@ -596,52 +529,57 @@ void LLViewerMediaImpl::stop() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::pause() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->pause(); + plugin->pause(); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::start() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->start(); + plugin->start(); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::seek(F32 time) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->seek(time); + plugin->seek(time); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setVolume(F32 volume) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->setVolume(volume); + plugin->setVolume(volume); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::focus(bool focus) { - if (mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { // call focus just for the hell of it, even though this apopears to be a nop - mMediaSource->focus(focus); + plugin->focus(focus); if (focus) { // spoof a mouse click to *actually* pass focus // Don't do this anymore -- it actually clicks through now. -// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); -// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); +// plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); +// plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); } } } @@ -649,57 +587,62 @@ void LLViewerMediaImpl::focus(bool focus) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDown(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseUp(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseMove(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::onMouseCaptureLost() { - if (mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); } } @@ -720,15 +663,17 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateHome() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->loadURI( mHomeURL ); + plugin->loadURI( mHomeURL ); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type) { + LLPluginClassMedia* plugin = getMediaPlugin(); if(rediscover_type) { @@ -745,7 +690,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // We use "data" internally for a text/html url for loading the login screen if(initializeMedia("text/html")) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } } else @@ -753,17 +698,17 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // This catches 'rtsp://' urls if(initializeMedia(scheme)) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } } } - else if (mMediaSource) + else if (plugin) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } - else if(initializeMedia(mime_type) && mMediaSource) + else if(initializeMedia(mime_type) && (plugin = getMediaPlugin())) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } else { @@ -777,9 +722,10 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateStop() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->browse_stop(); + plugin->browse_stop(); } } @@ -788,8 +734,9 @@ void LLViewerMediaImpl::navigateStop() bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if (mMediaSource) + if (plugin) { // FIXME: THIS IS SO WRONG. // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... @@ -797,19 +744,19 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { if( 'C' == key ) { - mMediaSource->copy(); + plugin->copy(); result = true; } else if( 'V' == key ) { - mMediaSource->paste(); + plugin->paste(); result = true; } else if( 'X' == key ) { - mMediaSource->cut(); + plugin->cut(); result = true; } } @@ -819,9 +766,9 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) LLSD native_key_data = LLSD::emptyMap(); - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); + result = plugin->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. - (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); + (void)plugin->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); } } @@ -832,8 +779,9 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if (mMediaSource) + if (plugin) { // only accept 'printable' characters, sigh... if (uni_char >= 32 // discard 'control' characters @@ -841,7 +789,7 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) { LLSD native_key_data = LLSD::emptyMap(); - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); + plugin->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); } } @@ -851,10 +799,11 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::canNavigateForward() { - BOOL result = FALSE; - if (mMediaSource) + bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - result = mMediaSource->getHistoryForwardAvailable(); + result = plugin->getHistoryForwardAvailable(); } return result; } @@ -862,10 +811,11 @@ bool LLViewerMediaImpl::canNavigateForward() ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::canNavigateBack() { - BOOL result = FALSE; - if (mMediaSource) + bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - result = mMediaSource->getHistoryBackAvailable(); + result = plugin->getHistoryBackAvailable(); } return result; } @@ -909,20 +859,21 @@ void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::update() { - if(mMediaSource == NULL) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (!plugin) { return; } - mMediaSource->idle(); + plugin->idle(); - if(mMediaSource->isPluginExited()) + if (plugin->isPluginExited()) { destroyMediaSource(); return; } - if(!mMediaSource->textureValid()) + if (!plugin->textureValid()) { return; } @@ -937,7 +888,7 @@ void LLViewerMediaImpl::update() if(placeholder_image) { LLRect dirty_rect; - if(mMediaSource->getDirty(&dirty_rect)) + if (plugin->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture S32 x_pos = llmax(dirty_rect.mLeft, 0); @@ -948,16 +899,16 @@ void LLViewerMediaImpl::update() if(width > 0 && height > 0) { - U8* data = mMediaSource->getBitsData(); + U8* data = plugin->getBitsData(); // Offset the pixels pointer to match x_pos and y_pos - data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); - data += ( y_pos * mMediaSource->getTextureDepth() ); + data += ( x_pos * plugin->getTextureDepth() * plugin->getBitsWidth() ); + data += ( y_pos * plugin->getTextureDepth() ); placeholder_image->setSubImage( data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), + plugin->getBitsWidth(), + plugin->getBitsHeight(), x_pos, y_pos, width, @@ -966,7 +917,7 @@ void LLViewerMediaImpl::update() } - mMediaSource->resetDirty(); + plugin->resetDirty(); } } } @@ -988,22 +939,23 @@ void LLViewerMediaImpl::updateImagesMediaStreams() } LLViewerMediaTexture* placeholder_image = (LLViewerMediaTexture*)LLViewerTextureManager::findTexture( mTextureId ); + LLPluginClassMedia* plugin = getMediaPlugin(); if (mNeedsNewTexture || placeholder_image->getUseMipMaps() || ! placeholder_image->mIsMediaTexture - || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) - || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) - || (mTextureUsedWidth != mMediaSource->getWidth()) - || (mTextureUsedHeight != mMediaSource->getHeight()) + || (placeholder_image->getWidth() != plugin->getTextureWidth()) + || (placeholder_image->getHeight() != plugin->getTextureHeight()) + || (mTextureUsedWidth != plugin->getWidth()) + || (mTextureUsedHeight != plugin->getHeight()) ) { llinfos << "initializing media placeholder" << llendl; llinfos << "movie image id " << mTextureId << llendl; - int texture_width = mMediaSource->getTextureWidth(); - int texture_height = mMediaSource->getTextureHeight(); - int texture_depth = mMediaSource->getTextureDepth(); + int texture_width = plugin->getTextureWidth(); + int texture_height = plugin->getTextureHeight(); + int texture_depth = plugin->getTextureDepth(); // MEDIAOPT: check to see if size actually changed before doing work placeholder_image->destroyGLTexture(); @@ -1017,10 +969,10 @@ void LLViewerMediaImpl::updateImagesMediaStreams() int discard_level = 0; // ask media source for correct GL image format constants - placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), - mMediaSource->getTextureFormatPrimary(), - mMediaSource->getTextureFormatType(), - mMediaSource->getTextureFormatSwapBytes()); + placeholder_image->setExplicitFormat(plugin->getTextureFormatInternal(), + plugin->getTextureFormatPrimary(), + plugin->getTextureFormatType(), + plugin->getTextureFormatSwapBytes()); placeholder_image->createGLTexture(discard_level, raw); @@ -1033,8 +985,8 @@ void LLViewerMediaImpl::updateImagesMediaStreams() // If the amount of the texture being drawn by the media goes down in either width or height, // recreate the texture to avoid leaving parts of the old image behind. - mTextureUsedWidth = mMediaSource->getWidth(); - mTextureUsedHeight = mMediaSource->getHeight(); + mTextureUsedWidth = plugin->getWidth(); + mTextureUsedHeight = plugin->getHeight(); } return placeholder_image; @@ -1050,24 +1002,25 @@ LLUUID LLViewerMediaImpl::getMediaTextureID() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setVisible(bool visible) { + LLPluginClassMedia* plugin = getMediaPlugin(); mVisible = visible; if(mVisible) { - if(mMediaSource && mMediaSource->isPluginExited()) + if(plugin && plugin->isPluginExited()) { destroyMediaSource(); } - if(!mMediaSource) + if(!plugin) { createMediaSource(); } } - if(mMediaSource) + if(plugin) { - mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN); + plugin->setPriority(mVisible?LLPluginClassBasic::PRIORITY_NORMAL:LLPluginClassBasic::PRIORITY_SLEEP); } } @@ -1080,10 +1033,11 @@ void LLViewerMediaImpl::mouseCapture() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::getTextureSize(S32 *texture_width, S32 *texture_height) { - if(mMediaSource && mMediaSource->textureValid()) + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin && plugin->textureValid()) { - S32 real_texture_width = mMediaSource->getBitsWidth(); - S32 real_texture_height = mMediaSource->getBitsHeight(); + S32 real_texture_width = plugin->getBitsWidth(); + S32 real_texture_height = plugin->getBitsHeight(); { // The "texture width" coming back from the plugin may not be a power of two (thanks to webkit). @@ -1124,10 +1078,11 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y) bool LLViewerMediaImpl::isMediaPlaying() { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if(mMediaSource) + if(plugin) { - EMediaStatus status = mMediaSource->getStatus(); + EMediaStatus status = plugin->getStatus(); if(status == MEDIA_PLAYING || status == MEDIA_LOADING) result = true; } @@ -1138,10 +1093,11 @@ bool LLViewerMediaImpl::isMediaPlaying() bool LLViewerMediaImpl::isMediaPaused() { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if(mMediaSource) + if(plugin) { - if(mMediaSource->getStatus() == MEDIA_PAUSED) + if(plugin->getStatus() == MEDIA_PAUSED) result = true; } @@ -1152,7 +1108,7 @@ bool LLViewerMediaImpl::isMediaPaused() // bool LLViewerMediaImpl::hasMedia() { - return mMediaSource != NULL; + return mPluginBase != NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1179,8 +1135,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass void LLViewerMediaImpl::cut() { - if (mMediaSource) - mMediaSource->cut(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->cut(); } //////////////////////////////////////////////////////////////////////////////// @@ -1188,8 +1145,9 @@ LLViewerMediaImpl::cut() BOOL LLViewerMediaImpl::canCut() const { - if (mMediaSource) - return mMediaSource->canCut(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canCut(); else return FALSE; } @@ -1199,8 +1157,9 @@ LLViewerMediaImpl::canCut() const void LLViewerMediaImpl::copy() { - if (mMediaSource) - mMediaSource->copy(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->copy(); } //////////////////////////////////////////////////////////////////////////////// @@ -1208,8 +1167,9 @@ LLViewerMediaImpl::copy() BOOL LLViewerMediaImpl::canCopy() const { - if (mMediaSource) - return mMediaSource->canCopy(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canCopy(); else return FALSE; } @@ -1219,8 +1179,9 @@ LLViewerMediaImpl::canCopy() const void LLViewerMediaImpl::paste() { - if (mMediaSource) - mMediaSource->paste(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->paste(); } //////////////////////////////////////////////////////////////////////////////// @@ -1228,8 +1189,9 @@ LLViewerMediaImpl::paste() BOOL LLViewerMediaImpl::canPaste() const { - if (mMediaSource) - return mMediaSource->canPaste(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canPaste(); else return FALSE; } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 1e9ef6c90..6b8bd2217 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -33,34 +33,17 @@ #ifndef LLVIEWERMEDIA_H #define LLVIEWERMEDIA_H +#include "llviewermediaeventemitter.h" +#include "llviewerpluginmanager.h" #include "llfocusmgr.h" - #include "llpanel.h" -#include "llpluginclassmediaowner.h" - -#include "llviewermediaobserver.h" class LLViewerMediaImpl; class LLUUID; -//class LLViewerMediaTexture; +class LLSD; class LLViewerTexture; typedef LLPointer viewer_media_t; -/////////////////////////////////////////////////////////////////////////////// -// -class LLViewerMediaEventEmitter -{ -public: - virtual ~LLViewerMediaEventEmitter(); - - bool addObserver( LLViewerMediaObserver* subject ); - bool remObserver( LLViewerMediaObserver* subject ); - void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); - -private: - typedef std::list< LLViewerMediaObserver* > observerListType; - observerListType mObservers; -}; class LLViewerMedia { @@ -93,7 +76,7 @@ class LLViewerMedia // Implementation functions not exported into header file class LLViewerMediaImpl - : public LLMouseHandler, public LLRefCount, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler + : public LLViewerPluginManager, public LLMouseHandler, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler { LOG_CLASS(LLViewerMediaImpl); public: @@ -112,9 +95,12 @@ public: void setMediaType(const std::string& media_type); bool initializeMedia(const std::string& mime_type); bool initializePlugin(const std::string& media_type); - LLPluginClassMedia* getMediaPlugin() { return mMediaSource; } + LLPluginClassMedia* getMediaPlugin() const { return (LLPluginClassMedia*)mPluginBase; } void setSize(int width, int height); + // Inherited from LLViewerPluginManager. + /*virtual*/ void update(); + void play(); void stop(); void pause(); @@ -141,7 +127,6 @@ public: void getTextureSize(S32 *texture_width, S32 *texture_height); void scaleMouse(S32 *mouse_x, S32 *mouse_y); - void update(); void updateMovieImage(const LLUUID& image_id, BOOL active); void updateImagesMediaStreams(); LLUUID getMediaTextureID(); @@ -201,7 +186,6 @@ public: public: // a single media url with some data and an impl. - LLPluginClassMedia* mMediaSource; LLUUID mTextureId; bool mMovieImageHasMips; std::string mMediaURL; @@ -219,7 +203,6 @@ public: bool mSuspendUpdates; bool mVisible; - private: /*LLViewerMediaTexture*/LLViewerTexture *updatePlaceholderImage(); }; diff --git a/indra/newview/llviewermediaeventemitter.cpp b/indra/newview/llviewermediaeventemitter.cpp new file mode 100644 index 000000000..39e0b2b52 --- /dev/null +++ b/indra/newview/llviewermediaeventemitter.cpp @@ -0,0 +1,85 @@ +/** + * @file llviewermediaeventemitter.cpp + * @brief Implementation of LLViewerMediaEventEmitter + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewermediaeventemitter.h" +#include "llviewermediaobserver.h" +#include + +LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() +{ + observerListType::iterator iter = mObservers.begin(); + + while (iter != mObservers.end()) + { + LLViewerMediaObserver* self = *iter; + ++iter; + remObserver(self); + } +} + +bool LLViewerMediaEventEmitter::addObserver(LLViewerMediaObserver* observer) +{ + if (!observer) + return false; + + if (std::find(mObservers.begin(), mObservers.end(), observer) != mObservers.end()) + return false; + + mObservers.push_back(observer); + observer->mEmitters.push_back(this); + + return true; +} + +bool LLViewerMediaEventEmitter::remObserver(LLViewerMediaObserver* observer) +{ + if (!observer) + return false; + + mObservers.remove(observer); + observer->mEmitters.remove(this); + + return true; +} + +void LLViewerMediaEventEmitter::emitEvent(LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event) +{ + observerListType::iterator iter = mObservers.begin(); + + while (iter != mObservers.end()) + { + LLViewerMediaObserver* self = *iter; + ++iter; + self->handleMediaEvent(media, event); + } +} diff --git a/indra/newview/llviewermediaeventemitter.h b/indra/newview/llviewermediaeventemitter.h new file mode 100644 index 000000000..17453a9e1 --- /dev/null +++ b/indra/newview/llviewermediaeventemitter.h @@ -0,0 +1,56 @@ +/** + * @file llviewermediaeventemitter.h + * @brief Helper class + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERMEDIAEVENTEMITTER_H +#define LLVIEWERMEDIAEVENTEMITTER_H + +#include "llpluginclassmediaowner.h" +#include + +class LLViewerMediaObserver; +class LLPluginClassMedia; + +class LLViewerMediaEventEmitter +{ +public: + virtual ~LLViewerMediaEventEmitter(); + + bool addObserver(LLViewerMediaObserver* subject); + bool remObserver(LLViewerMediaObserver* subject); + void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); + +private: + typedef std::list< LLViewerMediaObserver*> observerListType; + observerListType mObservers; +}; + +#endif // LLVIEWERMEDIAEVENTEMITTER_H diff --git a/indra/newview/llviewermediaobserver.cpp b/indra/newview/llviewermediaobserver.cpp new file mode 100644 index 000000000..6bed14311 --- /dev/null +++ b/indra/newview/llviewermediaobserver.cpp @@ -0,0 +1,47 @@ +/** + * @file llviewermediaobserver.cpp + * @brief Implementation of class LLViewerMediaObserver. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewermediaeventemitter.h" +#include "llviewermediaobserver.h" + +LLViewerMediaObserver::~LLViewerMediaObserver() +{ + std::list::iterator iter = mEmitters.begin(); + + while (iter != mEmitters.end()) + { + LLViewerMediaEventEmitter* self = *iter; + ++iter; + self->remObserver(this); + } +} diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index b4d01d476..7e276e51f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -552,8 +552,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t 6144, supersample)) { - gViewerWindow->playSnapshotAnimAndSound(); - LLPointer formatted; switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h index 7531a0f59..50e7aaa2c 100644 --- a/indra/newview/llviewerparcelmedia.h +++ b/indra/newview/llviewerparcelmedia.h @@ -34,6 +34,7 @@ #define LLVIEWERPARCELMEDIA_H #include "llviewermedia.h" +#include "llviewermediaobserver.h" // For use by other patches so they know that media filtering is implemented. #define MEDIA_FILTERING 1 @@ -42,7 +43,6 @@ class LLMessageSystem; class LLParcel; class LLViewerParcelMediaNavigationObserver; - // This class understands land parcels, network traffic, LSL media // transport commands, and talks to the LLViewerMedia class to actually // do playback. It allows us to remove code from LLViewerParcelMgr. diff --git a/indra/newview/llviewerpluginmanager.cpp b/indra/newview/llviewerpluginmanager.cpp new file mode 100644 index 000000000..58ee33585 --- /dev/null +++ b/indra/newview/llviewerpluginmanager.cpp @@ -0,0 +1,56 @@ +/** + * @file llviewerpluginmanager.cpp + * @brief Client interface to the plugin engine + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewerpluginmanager.h" + +void LLViewerPluginManager::destroyPlugin() +{ + delete mPluginBase; + mPluginBase = NULL; +} + +void LLViewerPluginManager::update() +{ + if (!mPluginBase) + { + return; + } + + mPluginBase->idle(); + + if (mPluginBase->isPluginExited()) + { + destroyPlugin(); + return; + } +} diff --git a/indra/newview/llviewerpluginmanager.h b/indra/newview/llviewerpluginmanager.h new file mode 100644 index 000000000..b56d11eee --- /dev/null +++ b/indra/newview/llviewerpluginmanager.h @@ -0,0 +1,115 @@ +/** + * @file llviewerpluginmanager.h + * @brief Client interface to the plugin engine + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERPLUGINMANAGER_H +#define LLVIEWERPLUGINMANAGER_H + +#include +#include "llmemory.h" +#include "llerror.h" +#include "lldir.h" +#include "llfile.h" +#include "llviewercontrol.h" +#include "llnotifications.h" +#include "llpluginclassbasic.h" + +class LLViewerPluginManager : public LLRefCount +{ + LOG_CLASS(LLViewerPluginManager); + +public: + // Construct an uninitialized LLViewerPluginManager object. + LLViewerPluginManager(void) : mPluginBase(NULL) { } + + // Create a PLUGIN_TYPE (must be derived from LLPluginClassBasic). + // This uses PLUGIN_TYPE::launcher_name() and PLUGIN_TYPE::plugin_basename(). + // If successful, returns the created LLPluginClassBasic, NULL otherwise. + template + LLPluginClassBasic* createPlugin(T* user_data); + + // Delete the plugin. + void destroyPlugin(); + + // Handle plugin messages. + virtual void update(); + + // Return pointer to plugin. + LLPluginClassBasic* getPlugin(void) const { return mPluginBase; } + +protected: + LLPluginClassBasic* mPluginBase; //!< Pointer to the base class of the underlaying plugin. +}; + +template +LLPluginClassBasic* LLViewerPluginManager::createPlugin(T* user_data) +{ + // Always delete the old plugin first. + destroyPlugin(); + + std::string plugin_name = gDirUtilp->getLLPluginFilename(PLUGIN_TYPE::plugin_basename()); + + // See if the plugin executable exists. + llstat s; + if (LLFile::stat(PLUGIN_TYPE::launcher_name(), &s)) + { + LL_WARNS("Plugin") << "Couldn't find launcher at " << PLUGIN_TYPE::launcher_name() << LL_ENDL; + } + else if (LLFile::stat(plugin_name, &s)) + { + LL_WARNS("Plugin") << "Couldn't find plugin at " << plugin_name << LL_ENDL; + } + else + { + LLPluginClassBasic* plugin = new PLUGIN_TYPE(user_data); + if (plugin->init(PLUGIN_TYPE::launcher_name(), plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) + { + mPluginBase = plugin; + } + else + { + LL_WARNS("Plugin") << "Failed to init plugin. Destroying." << LL_ENDL; + delete plugin; + } + } + + if (mPluginBase) + return mPluginBase; + + LL_WARNS("Plugin") << "plugin intialization failed for plugin: " << PLUGIN_TYPE::plugin_basename() << LL_ENDL; + LLSD args; + args["MIME_TYPE"] = PLUGIN_TYPE::plugin_basename(); // FIXME: Use different notification. + LLNotifications::instance().add("NoPlugin", args); + + return NULL; +} + +#endif // LLVIEWERPLUGINMANAGER_H diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a82fdb3d5..2139e75d8 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -89,7 +89,7 @@ #include "llmaniptranslate.h" #include "llface.h" #include "llfeaturemanager.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llfloater.h" #include "llfloateractivespeakers.h" #include "llfloaterbuildoptions.h" @@ -3988,27 +3988,27 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) +void LLViewerWindow::saveImageNumbered(LLPointer image) { if (!image) { - return FALSE; + return; } - LLFilePicker::ESaveFilter pick_type; + ESaveFilter pick_type; std::string extension("." + image->getExtension()); if (extension == ".j2c") - pick_type = LLFilePicker::FFSAVE_J2C; + pick_type = FFSAVE_J2C; else if (extension == ".bmp") - pick_type = LLFilePicker::FFSAVE_BMP; + pick_type = FFSAVE_BMP; else if (extension == ".jpg") - pick_type = LLFilePicker::FFSAVE_JPEG; + pick_type = FFSAVE_JPEG; else if (extension == ".png") - pick_type = LLFilePicker::FFSAVE_PNG; + pick_type = FFSAVE_PNG; else if (extension == ".tga") - pick_type = LLFilePicker::FFSAVE_TGA; + pick_type = FFSAVE_TGA; else - pick_type = LLFilePicker::FFSAVE_ALL; // ??? + pick_type = FFSAVE_ALL; // ??? // Get a base file location if needed. if ( ! isSnapshotLocSet()) @@ -4018,20 +4018,34 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. // pick a directory in which to save - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(pick_type, proposed_name)) - { - // Clicked cancel - return FALSE; - } + AIFilePicker* filepicker = new AIFilePicker; // Deleted in LLViewerWindow::saveImageNumbered_filepicker_callback + filepicker->open(proposed_name, pick_type, "", "snapshot"); + filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_filepicker_callback, this, image, extension, filepicker, _1)); + return; + } + // LLViewerWindow::sSnapshotBaseName and LLViewerWindow::sSnapshotDir already known. Go straight to saveImageNumbered_continued. + saveImageNumbered_continued(image, extension); +} + +void LLViewerWindow::saveImageNumbered_filepicker_callback(LLPointer image, std::string const& extension, AIFilePicker* filepicker, bool success) +{ + llassert((bool)*filepicker == success); + if (success) + { // Copy the directory + file name - std::string filepath = picker.getFirstFile(); + std::string filepath = filepicker->getFilename(); LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true); LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); - } + saveImageNumbered_continued(image, extension); + } + delete filepicker; +} + +void LLViewerWindow::saveImageNumbered_continued(LLPointer image, std::string const& extension) +{ // Look for an unused file name std::string filepath; S32 i = 1; @@ -4051,7 +4065,10 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) } while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). - return image->save(filepath); + if (image->save(filepath)) + { + playSnapshotAnimAndSound(); + } } void LLViewerWindow::resetSnapshotLoc() diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 21867f7eb..cbf3f0187 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -60,6 +60,7 @@ class LLTextBox; class LLImageRaw; class LLHUDIcon; class LLMouseHandler; +class AIFilePicker; #define PICK_HALF_WIDTH 5 #define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1) @@ -282,19 +283,21 @@ public: // snapshot functionality. // perhaps some of this should move to llfloatershapshot? -MG - typedef enum e_snapshot_type + enum ESnapshotType { SNAPSHOT_TYPE_COLOR, SNAPSHOT_TYPE_DEPTH, SNAPSHOT_TYPE_OBJECT_ID - } ESnapshotType; + }; BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f ); BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } - BOOL saveImageNumbered(LLImageFormatted *image); + void saveImageNumbered(LLPointer image); + void saveImageNumbered_filepicker_callback(LLPointer image, std::string const& extension, AIFilePicker* filepicker, bool success); + void saveImageNumbered_continued(LLPointer image, std::string const& extension); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. diff --git a/indra/newview/statemachine/aifilepicker.cpp b/indra/newview/statemachine/aifilepicker.cpp new file mode 100644 index 000000000..cd6856100 --- /dev/null +++ b/indra/newview/statemachine/aifilepicker.cpp @@ -0,0 +1,369 @@ +/** + * @file aifilepicker.cpp + * @brief Implementation of AIFilePicker + * + * Copyright (c) 2010, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 04/12/2010 + * Initial version, written by Aleric Inglewood @ SL + */ + +#include "../llviewerprecompiledheaders.h" +#include "../llviewermedia.h" +#include "../lltrans.h" +#include "llpluginclassmedia.h" +#include "llpluginmessageclasses.h" +#include "aifilepicker.h" +#if LL_WINDOWS +#include "../llviewerwindow.h" +#endif +#if LL_GTK && LL_X11 +#include "llwindowsdl.h" +#endif + +enum filepicker_state_type { + AIFilePicker_initialize_plugin = AIStateMachine::max_state, + AIFilePicker_plugin_running, + AIFilePicker_canceled, + AIFilePicker_done +}; + +char const* AIFilePicker::state_str_impl(state_type run_state) const +{ + switch(run_state) + { + AI_CASE_RETURN(AIFilePicker_initialize_plugin); + AI_CASE_RETURN(AIFilePicker_plugin_running); + AI_CASE_RETURN(AIFilePicker_canceled); + AI_CASE_RETURN(AIFilePicker_done); + } + return "UNKNOWN STATE"; +} + +AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mCanceled(false) +{ +} + +void AIFilePicker::store_folder(std::string const& context, std::string const& folder) +{ + if (!folder.empty()) + { + mContextMap[context] = folder; + } +} + +std::string AIFilePicker::get_folder(std::string const& default_path, std::string const& context) +{ + context_map_type::iterator iter = mContextMap.find(context); + if (iter != mContextMap.end()) + { + return iter->second; + } + else if (!default_path.empty()) + { + return default_path; + } + else if ((iter = mContextMap.find("savefile")) != mContextMap.end()) + { + return iter->second; + } + else + { + // This is the last resort when all else failed. Open the file chooser in directory 'home'. + char const* home = NULL; +#if LL_WINDOWS + #warning "Attention WINDOWS DEVELOPER: Set 'home' to a sensible default directory (users Desktop?)" +#else + home = getenv("HOME"); +#endif + return home ? home : ""; + } +} + +void AIFilePicker::open(ELoadFilter filter, std::string const& default_path, std::string const& context, bool multiple) +{ + mContext = context; + mFolder = get_folder(default_path, context); + mOpenType = multiple ? load_multiple : load; + switch(filter) + { + case FFLOAD_ALL: + mFilter = "all"; + break; + case FFLOAD_WAV: + mFilter = "wav"; + break; + case FFLOAD_IMAGE: + mFilter = "image"; + break; + case FFLOAD_ANIM: + mFilter = "anim"; + break; +#ifdef _CORY_TESTING + case FFLOAD_GEOMETRY: + mFilter = "geometry"; + break; +#endif + case FFLOAD_XML: + mFilter = "xml"; + break; + case FFLOAD_SLOBJECT: + mFilter = "slobject"; + break; + case FFLOAD_RAW: + mFilter = "raw"; + break; + case FFLOAD_TEXT: + mFilter = "text"; + break; + } +} + +void AIFilePicker::open(std::string const& filename, ESaveFilter filter, std::string const& default_path, std::string const& context) +{ + mFilename = filename; + mContext = context; + mFolder = get_folder(default_path, context); + mOpenType = save; + switch(filter) + { + case FFSAVE_ALL: + mFilter = "all"; + break; + case FFSAVE_WAV: + mFilter = "wav"; + break; + case FFSAVE_TGA: + mFilter = "tga"; + break; + case FFSAVE_BMP: + mFilter = "bmp"; + break; + case FFSAVE_AVI: + mFilter = "avi"; + break; + case FFSAVE_ANIM: + mFilter = "anim"; + break; +#ifdef _CORY_TESTING + case FFSAVE_GEOMETRY: + mFilter = "geometry"; + break; +#endif + case FFSAVE_XML: + mFilter = "xml"; + break; + case FFSAVE_COLLADA: + mFilter = "collada"; + break; + case FFSAVE_RAW: + mFilter = "raw"; + break; + case FFSAVE_J2C: + mFilter = "j2c"; + break; + case FFSAVE_PNG: + mFilter = "png"; + break; + case FFSAVE_JPEG: + mFilter = "jpeg"; + break; + case FFSAVE_HPA: + mFilter = "hpa"; + break; + case FFSAVE_TEXT: + mFilter = "text"; + break; + case FFSAVE_LSL: + mFilter = "lsl"; + break; + } +} + +void AIFilePicker::initialize_impl(void) +{ + mCanceled = false; + if (mFilter.empty()) + { + llwarns << "Calling AIFilePicker::initialize_impl() with empty mFilter. Call open before calling run!" << llendl; + abort(); + return; + } + mPluginManager = new LLViewerPluginManager; + if (!mPluginManager) + { + abort(); + return; + } + LLPluginClassBasic* plugin = mPluginManager->createPlugin(this); + if (!plugin) + { + abort(); + return; + } + set_state(AIFilePicker_initialize_plugin); +} + +void AIFilePicker::multiplex_impl(void) +{ + mPluginManager->update(); // Give the plugin some CPU for it's messages. + LLPluginClassBasic* plugin = mPluginManager->getPlugin(); + if (!plugin || plugin->isPluginExited()) + { + // This happens when there was a problem with the plugin (ie, it crashed). + abort(); + return; + } + switch (mRunState) + { + case AIFilePicker_initialize_plugin: + { + if (!plugin->isPluginRunning()) + { + break; // Still initializing. + } + + // Send initialization message. + LLPluginMessage initialization_message(LLPLUGIN_MESSAGE_CLASS_BASIC, "initialization"); + static char const* key_str[] = { + "all_files", "sound_files", "animation_files", "image_files", "save_file_verb", + "targa_image_files", "bitmap_image_files", "avi_movie_file", "xaf_animation_file", + "xml_file", "raw_file", "compressed_image_files", "load_file_verb", "load_files" + }; + LLSD dictionary; + for (int key = 0; key < sizeof(key_str) / sizeof(key_str[0]); ++key) + { + dictionary[key_str[key]] = LLTrans::getString(key_str[key]); + } + initialization_message.setValueLLSD("dictionary", dictionary); +#if LL_WINDOWS || (LL_GTK && LL_X11) + std::ostringstream window_id_str; +#if LL_WINDOWS + unsigned long window_id = gViewerWindow->getPlatformWindow(); +#else + unsigned long window_id = LLWindowSDL::get_SDL_XWindowID(); +#endif + if (window_id != None) + { + window_id_str << std::hex << "0x" << window_id; + initialization_message.setValue("window_id", window_id_str.str()); + } + else + { + LL_WARNS("Plugin") << "Couldn't get xwid to use for transient." << LL_ENDL; + } +#endif // LL_WINDOWS || (LL_GTK && LL_X11) + plugin->sendMessage(initialization_message); + + // Send open message. + LLPluginMessage open_message(LLPLUGIN_MESSAGE_CLASS_BASIC, "open"); + open_message.setValue("type", (mOpenType == save) ? "save" : (mOpenType == load) ? "load" : "load_multiple"); + open_message.setValue("filter", mFilter); + if (mOpenType == save) open_message.setValue("default", mFilename); + open_message.setValue("folder", mFolder); + open_message.setValue("gorgon", "block"); // Don't expect HeartBeat messages after an "open". + plugin->sendMessage(open_message); + + set_state(AIFilePicker_plugin_running); + break; + } + case AIFilePicker_plugin_running: + { + // Users are slow, no need to look for new messages from the plugin all too often. + yield_ms(250); + break; + } + case AIFilePicker_canceled: + { + mCanceled = true; + finish(); + break; + } + case AIFilePicker_done: + { + // Store folder of first filename as context. + store_folder(mContext, getFolder()); + finish(); + } + } +} + +void AIFilePicker::abort_impl(void) +{ +} + +void AIFilePicker::finish_impl(void) +{ + mPluginManager = NULL; // This deletes the plugin, since mPluginManager is a LLPointer. + mFilter.clear(); // Check that open is called before calling run (again). +} + +// This function is called when a new message is received from the plugin. +// We get here when calling mPluginManager->update() in the first line of +// AIFilePicker::multiplex_impl. +// +// Note that we can't call finish() or abort() directly in this function, +// as that deletes mPluginManager and we're using the plugin manager +// right now (to receive this message)! +void AIFilePicker::receivePluginMessage(const LLPluginMessage &message) +{ + std::string message_class = message.getClass(); + + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + std::string message_name = message.getName(); + if (message_name == "canceled") + { + set_state(AIFilePicker_canceled); + } + else if (message_name == "done") + { + LLSD filenames = message.getValueLLSD("filenames"); + mFilenames.clear(); + for(LLSD::array_iterator filename = filenames.beginArray(); filename != filenames.endArray(); ++filename) + { + mFilenames.push_back(*filename); + } + set_state(AIFilePicker_done); + } + else + { + LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; + } + } +} + +std::string const& AIFilePicker::getFilename(void) const +{ + // Only call this function after the AIFilePicker finished successfully without being canceled. + llassert_always(!mFilenames.empty()); + // This function returns the first filename in the case that more than one was selected. + return mFilenames[0]; +} + +std::string AIFilePicker::getFolder(void) const +{ + // Return the folder of the first filename. + return gDirUtilp->getDirName(getFilename()); +} + diff --git a/indra/newview/statemachine/aifilepicker.h b/indra/newview/statemachine/aifilepicker.h new file mode 100644 index 000000000..008afb1d7 --- /dev/null +++ b/indra/newview/statemachine/aifilepicker.h @@ -0,0 +1,160 @@ +/** + * @file aifilepicker.h + * @brief File picker State machine + * + * Copyright (c) 2010, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 02/12/2010 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIFILEPICKER_H +#define AIFILEPICKER_H + +#include "aistatemachine.h" +#include "llpluginclassmedia.h" +#include "../llviewermedia.h" +#include + +enum ELoadFilter +{ + FFLOAD_ALL, + FFLOAD_WAV, + FFLOAD_IMAGE, + FFLOAD_ANIM, + FFLOAD_XML, + FFLOAD_SLOBJECT, + FFLOAD_RAW, + FFLOAD_TEXT +}; + +enum ESaveFilter +{ + FFSAVE_ALL, + FFSAVE_WAV, + FFSAVE_TGA, + FFSAVE_BMP, + FFSAVE_AVI, + FFSAVE_ANIM, + FFSAVE_XML, + FFSAVE_COLLADA, + FFSAVE_RAW, + FFSAVE_J2C, + FFSAVE_PNG, + FFSAVE_JPEG, + FFSAVE_HPA, + FFSAVE_TEXT, + FFSAVE_LSL +}; + +// A file picker state machine. +// +// Before calling run(), call open() to pass needed parameters. +// +// When the state machine finishes, call isCanceled to check +// whether or not getFilename and getFolder will be valid. +// +// Objects of this type can be reused multiple times, see +// also the documentation of AIStateMachine. +class AIFilePicker : public AIStateMachine { +public: + AIFilePicker(void); + + // The starting directory that the user will be in when the file picker opens + // will be the same as the directory used the last time the file picker was + // opened with the same context. If the file picker was never opened before + // with the given context, the starting directory will be set to default_path + // unless that is the empty string, in which case it will be equal to the + // directory used the last time the filepicker was opened with context "savefile". + void open(std::string const& filename, ESaveFilter filter = FFSAVE_ALL, std::string const& default_path = "", std::string const& context = "savefile"); + void open(ELoadFilter filter = FFLOAD_ALL, std::string const& default_path = "", std::string const& context = "openfile", bool multiple = false); + + bool isCanceled(void) const { return mCanceled; } + std::string const& getFilename(void) const; + std::string getFolder(void) const; + std::vector const& getFilenames(void) const { return mFilenames; } + +private: + friend class AIPluginFilePicker; + + // This is called from AIPluginFilePicker::receivePluginMessage, see below. + void receivePluginMessage(LLPluginMessage const& message); + +public: + enum open_type { save, load, load_multiple }; + +private: + LLPointer mPluginManager; //!< Pointer to the plugin manager. + // FIXME: this should be a separate, thread-safe singleton. + typedef std::map context_map_type; //!< Type of mContextMap. + context_map_type mContextMap; //!< Map context (ie, "snapshot" or "image") to last used folder. + std::string mContext; //!< Some key to indicate the context (remembers the folder per key). + + // Input variables (cache variable between call to open and run). + open_type mOpenType; //!< Set to whether opening a filepicker to select for saving one file, for loading one file, or loading multiple files. + std::string mFilter; //!< A keyword indicating which file types (extensions) we want to see. + std::string mFilename; //!< When saving: proposed filename. + std::string mFolder; //!< Initial folder to start in. + // Output variables: + bool mCanceled; //!< True if the file picker was canceled or closed. + std::vector mFilenames; //!< Filesnames. + + // Store a folder for the given context. + void store_folder(std::string const& context, std::string const& folder); + // Return the last folder stored for 'context', or default_path if none, or context "savefile" if empty, or $HOME if none. + std::string get_folder(std::string const& default_path, std::string const& context); + +protected: + // Handle initializing the object. + /*virtual*/ void initialize_impl(void); + + // Handle mRunState. + /*virtual*/ void multiplex_impl(void); + + // Handle aborting from current bs_run state. + /*virtual*/ void abort_impl(void); + + // Handle cleaning up from initialization (or post abort) state. + /*virtual*/ void finish_impl(void); + + // Implemenation of state_str for run states. + /*virtual*/ char const* state_str_impl(state_type run_state) const; +}; + +// Viewer-side helper class for objects with a lifetime equal to the +// plugin child process (SLPlugin). Don't use directly. +class AIPluginFilePicker : public LLPluginClassBasic { + LOG_CLASS(AIPluginFilePicker); +public: + AIPluginFilePicker(AIFilePicker* state_machine) : mStateMachine(state_machine) { } + + static std::string launcher_name(void) { return gDirUtilp->getLLPluginLauncher(); } + static char const* plugin_basename(void) { return "basic_plugin_filepicker"; } + + /*virtual*/ void receivePluginMessage(LLPluginMessage const& message) { mStateMachine->receivePluginMessage(message); } + +private: + AIFilePicker* mStateMachine; +}; + +#endif diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index a663389ea..42859efbe 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -220,13 +220,18 @@ class WindowsManifest(ViewerManifest): # self.path("openjpeg.dll") # self.end_prefix() + # Plugins - FilePicker + if self.prefix(src='../plugins/filepicker/%s' % self.args['configuration'], dst="llplugin"): + self.path("basic_plugin_filepicker.dll") + self.end_prefix() + # Media plugins - QuickTime - if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): + if self.prefix(src='../plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_quicktime.dll") self.end_prefix() # Media plugins - WebKit/Qt - if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): + if self.prefix(src='../plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_webkit.dll") self.end_prefix() @@ -533,8 +538,9 @@ class DarwinManifest(ViewerManifest): # plugins if self.prefix(src="", dst="llplugin"): - self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") - self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") + self.path("../plugins/filepicker/" + self.args['configuration'] + "/basic_plugin_filepicker.dylib", "basic_plugin_filepicker.dylib") + self.path("../plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") + self.path("../plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") self.end_prefix("llplugin") @@ -689,8 +695,9 @@ class LinuxManifest(ViewerManifest): # plugins if self.prefix(src="", dst="bin/llplugin"): - self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") - self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.path("../plugins/filepicker/libbasic_plugin_filepicker.so", "libbasic_plugin_filepicker.so") + self.path("../plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") + self.path("../plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") self.end_prefix("bin/llplugin") # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 diff --git a/indra/plugins/filepicker/basic_plugin_filepicker.cpp b/indra/plugins/filepicker/basic_plugin_filepicker.cpp new file mode 100644 index 000000000..bd415c64a --- /dev/null +++ b/indra/plugins/filepicker/basic_plugin_filepicker.cpp @@ -0,0 +1,243 @@ +/** + * @file plugin_filepicker.cpp + * @brief Plugin that runs a file picker. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://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$ + * + * @endcond + */ + +#include "linden_common.h" +#include "basic_plugin_base.h" +#include "llfilepicker.h" + +class FilepickerPlugin : public BasicPluginBase +{ + public: + FilepickerPlugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance); + ~FilepickerPlugin(); + + /*virtual*/ void receiveMessage(char const* message_string); + + private: + bool init(); +}; + +FilepickerPlugin::FilepickerPlugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) : + BasicPluginBase(send_message_function, plugin_instance) +{ +} + +FilepickerPlugin::~FilepickerPlugin() +{ +} + +static LLFilePicker::ESaveFilter str2savefilter(std::string const& filter) +{ + // Complement of AIFilePicker::open(std::string const& filename, ESaveFilter filter, std::string const& folder) + if (filter == "wav") + return LLFilePicker::FFSAVE_WAV; + else if (filter == "tga") + return LLFilePicker::FFSAVE_TGA; + else if (filter == "bmp") + return LLFilePicker::FFSAVE_BMP; + else if (filter == "avi") + return LLFilePicker::FFSAVE_AVI; + else if (filter == "anim") + return LLFilePicker::FFSAVE_ANIM; +#ifdef _CORY_TESTING + else if (filter == "geometry") + return LLFilePicker::FFSAVE_GEOMETRY; +#endif + else if (filter == "xml") + return LLFilePicker::FFSAVE_XML; + else if (filter == "collada") + return LLFilePicker::FFSAVE_COLLADA; + else if (filter == "raw") + return LLFilePicker::FFSAVE_RAW; + else if (filter == "j2c") + return LLFilePicker::FFSAVE_J2C; + else if (filter == "png") + return LLFilePicker::FFSAVE_PNG; + else if (filter == "jpeg") + return LLFilePicker::FFSAVE_JPEG; + else if (filter == "hpa") + return LLFilePicker::FFSAVE_HPA; + else if (filter == "text") + return LLFilePicker::FFSAVE_TEXT; + else if (filter == "lsl") + return LLFilePicker::FFSAVE_LSL; + else + return LLFilePicker::FFSAVE_ALL; +} + +static LLFilePicker::ELoadFilter str2loadfilter(std::string const& filter) +{ + // Complement of AIFilePicker::open(ELoadFilter filter, std::string const& folder) + if (filter == "wav") + return LLFilePicker::FFLOAD_WAV; + else if (filter == "image") + return LLFilePicker::FFLOAD_IMAGE; + else if (filter == "anim") + return LLFilePicker::FFLOAD_ANIM; +#ifdef _CORY_TESTING + else if (filter == "geometry") + return LLFilePicker::FFLOAD_GEOMETRY; +#endif + else if (filter == "xml") + return LLFilePicker::FFLOAD_XML; + else if (filter == "slobject") + return LLFilePicker::FFLOAD_SLOBJECT; + else if (filter == "raw") + return LLFilePicker::FFLOAD_RAW; + else if (filter == "text") + return LLFilePicker::FFLOAD_TEXT; + else + return LLFilePicker::FFLOAD_ALL; +} + +// This is the SLPlugin process. +// This is part of the loaded DSO. +// +// This function is called from LLPluginInstance::sendMessage +// for messages received from the viewer (that are not 'internal'). +void FilepickerPlugin::receiveMessage(char const* message_string) +{ + 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_BASIC] = LLPLUGIN_MESSAGE_CLASS_BASIC_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Filepicker Plugin, version 1.0.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + // This whole message should not have existed imho -- Aleric + } + else + { + std::cerr << "FilepickerPlugin::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + // This message should be sent at most once per SLPlugin invokation. + if (message_name == "initialization") + { + LLSD dictionary = message_in.getValueLLSD("dictionary"); + for (LLSD::map_iterator iter = dictionary.beginMap(); iter != dictionary.endMap(); ++iter) + { + translation::add(iter->first, iter->second.asString()); + } + if (message_in.hasValue("window_id")) + { + unsigned long window_id = strtoul(message_in.getValue("window_id").c_str(), NULL, 16); + LLFilePicker::instance().setWindowID(window_id); + } + } + // This message may theoretically be repeated (though currently the plugin is terminated after returning). + else if (message_name == "open") + { + std::string type = message_in.getValue("type"); + std::string filter = message_in.getValue("filter"); + std::string folder = message_in.getValue("folder"); + + bool canceled; + if (type == "save") + { + canceled = !LLFilePicker::instance().getSaveFile(str2savefilter(filter), message_in.getValue("default"), folder); + } + else if (type == "load") + { + canceled = !LLFilePicker::instance().getLoadFile(str2loadfilter(filter), folder); + } + else // type == "load_multiple" + { + canceled = !LLFilePicker::instance().getMultipleLoadFiles(str2loadfilter(filter), folder); + } + if (canceled) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "canceled"); + message.setValue("perseus", "unblock"); + sendMessage(message); + } + else + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "done"); + message.setValue("perseus", "unblock"); + LLSD filenames; + for (std::string filename = LLFilePicker::instance().getFirstFile(); !filename.empty(); filename = LLFilePicker::instance().getNextFile()) + { + filenames.append(filename); + } + message.setValueLLSD("filenames", filenames); + sendMessage(message); + } + } + else + { + std::cerr << "FilepickerPlugin::receiveMessage: unknown basic message: " << message_name << std::endl; + } + } + else + { + std::cerr << "FilepickerPlugin::receiveMessage: unknown message class: " << message_class << std::endl; + } + } +} + +bool FilepickerPlugin::init(void) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "name_text"); + message.setValue("name", "Filepicker Plugin"); + sendMessage(message); + + return true; +} + +int create_plugin(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, BasicPluginBase** plugin_object) +{ + *plugin_object = new FilepickerPlugin(send_message_function, plugin_instance); + return 0; +} +