From 784fdd4f379dc340a94c4ab88e6b15a9ce3495f7 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 6 May 2011 15:00:50 +0200 Subject: [PATCH] Split plugin classes and derive AIFilePicker from BasicPluginBase (part 2). This commit contains all changes to indra/llplugin. Since there were no differences at all between Singularity and imprudence before this patch, it's a perfect port. --- indra/llplugin/CMakeLists.txt | 2 + indra/llplugin/llpluginclassbasic.cpp | 189 +++++++++++++++++++++++ indra/llplugin/llpluginclassbasic.h | 126 +++++++++++++++ indra/llplugin/llpluginclassmedia.cpp | 163 +++---------------- indra/llplugin/llpluginclassmedia.h | 83 ++-------- indra/llplugin/llplugininstance.cpp | 33 ++-- indra/llplugin/llplugininstance.h | 14 +- indra/llplugin/llpluginmessage.h | 6 +- indra/llplugin/llpluginmessageclasses.h | 3 + indra/llplugin/llpluginprocesschild.cpp | 28 +++- indra/llplugin/llpluginprocessparent.cpp | 35 +++++ indra/llplugin/llpluginprocessparent.h | 1 + 12 files changed, 457 insertions(+), 226 deletions(-) create mode 100644 indra/llplugin/llpluginclassbasic.cpp create mode 100644 indra/llplugin/llpluginclassbasic.h diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 7a7f4e583..270a95d54 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ) set(llplugin_SOURCE_FILES + llpluginclassbasic.cpp llpluginclassmedia.cpp llplugincookiestore.cpp llplugininstance.cpp @@ -37,6 +38,7 @@ set(llplugin_SOURCE_FILES set(llplugin_HEADER_FILES CMakeLists.txt + llpluginclassbasic.h llpluginclassmedia.h llpluginclassmediaowner.h llplugincookiestore.h diff --git a/indra/llplugin/llpluginclassbasic.cpp b/indra/llplugin/llpluginclassbasic.cpp new file mode 100644 index 000000000..0567b157f --- /dev/null +++ b/indra/llplugin/llpluginclassbasic.cpp @@ -0,0 +1,189 @@ +/** + * @file llpluginclassbasic.cpp + * @brief LLPluginClassBasic handles a plugin which knows about the "basic" message class. + * + * @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 "indra_constants.h" + +#include "llpluginclassbasic.h" +#include "llpluginmessageclasses.h" + +LLPluginClassBasic::LLPluginClassBasic(void) : mPlugin(NULL), mDeleteOK(true) +{ + // Note that this only initializes the base class, the derived class doesn't exist yet! + // Derived classes must therefore call their own reset_impl() from their constructor. + reset(); +} + +LLPluginClassBasic::~LLPluginClassBasic() +{ + llassert_always(mDeleteOK); + delete mPlugin; +} + +bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug) +{ + LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; + + mPlugin = new LLPluginProcessParent(this); + mPlugin->setSleepTime(mSleepTime); + + mPlugin->init(launcher_filename, plugin_filename, debug); + + return init_impl(); +} + +void LLPluginClassBasic::reset() +{ + if (mPlugin != NULL) + { + delete mPlugin; + mPlugin = NULL; + } + mSleepTime = 1.0f / 50.0f; + mPriority = PRIORITY_NORMAL; + reset_impl(); +} + +void LLPluginClassBasic::idle(void) +{ + if(mPlugin) + { + mPlugin->idle(); + } + + idle_impl(); + + if(mPlugin && mPlugin->isRunning()) + { + // Send queued messages + while(!mSendQueue.empty()) + { + LLPluginMessage message = mSendQueue.front(); + mSendQueue.pop(); + mPlugin->sendMessage(message); + } + } +} + +char const* LLPluginClassBasic::priorityToString(EPriority priority) +{ + const char* result = "UNKNOWN"; + switch(priority) + { + case PRIORITY_SLEEP: result = "sleep"; break; + case PRIORITY_LOW: result = "low"; break; + case PRIORITY_NORMAL: result = "normal"; break; + case PRIORITY_HIGH: result = "high"; break; + } + + return result; +} + +void LLPluginClassBasic::setPriority(EPriority priority) +{ + if (mPriority != priority) + { + mPriority = priority; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "set_priority"); + + std::string priority_string = priorityToString(priority); + switch(priority) + { + case PRIORITY_SLEEP: + mSleepTime = 1.0f; + break; + case PRIORITY_LOW: + mSleepTime = 1.0f / 25.0f; + break; + case PRIORITY_NORMAL: + mSleepTime = 1.0f / 50.0f; + break; + case PRIORITY_HIGH: + mSleepTime = 1.0f / 100.0f; + break; + } + + message.setValue("priority", priority_string); + sendMessage(message); + + if(mPlugin) + { + mPlugin->setSleepTime(mSleepTime); + } + + LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; + + priorityChanged(mPriority); + } +} + +/* virtual */ +void LLPluginClassBasic::receivePluginMessage(const LLPluginMessage &message) +{ + std::string message_class = message.getClass(); + + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + std::string message_name = message.getName(); + + // This class hasn't defined any incoming messages yet. +// if (message_name == "message_name") +// { +// } +// else + { + LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; + } + } +} + +// This is the viewer process (the parent process) +// +// Call this function to send a message to a plugin. +// It calls LLPluginProcessParent::sendMessage. +void LLPluginClassBasic::sendMessage(LLPluginMessage const& message) +{ + if(mPlugin && mPlugin->isRunning()) + { + mPlugin->sendMessage(message); + } + else + { + // The plugin isn't set up yet -- queue this message to be sent after initialization. + mSendQueue.push(message); + } +} diff --git a/indra/llplugin/llpluginclassbasic.h b/indra/llplugin/llpluginclassbasic.h new file mode 100644 index 000000000..a9e4dba46 --- /dev/null +++ b/indra/llplugin/llpluginclassbasic.h @@ -0,0 +1,126 @@ +/** + * @file llpluginclassbasic.h + * @brief LLPluginClassBasic handles interaction with a plugin which knows about the "basic" message class. + * + * @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 + */ + +#ifndef LL_LLPLUGINCLASSBASIC_H +#define LL_LLPLUGINCLASSBASIC_H + +#include "llerror.h" // Needed for LOG_CLASS +#include "stdtypes.h" // Needed for F64 +#include "llpluginprocessparent.h" +#include "llpluginclassmediaowner.h" +#include "llpluginmessage.h" +#include +#include + +class LLPluginClassBasic : public LLPluginProcessParentOwner +{ + LOG_CLASS(LLPluginClassBasic); + +public: + LLPluginClassBasic(void); + virtual ~LLPluginClassBasic(); + + // Local initialization, called when creating a plugin process. Return true if successful. + bool init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug); + + // Undoes everything init did. Called when destroying a plugin process. + void reset(void); + + void idle(void); + + // Send message to the plugin, either queueing or sending directly. + void sendMessage(LLPluginMessage const& message); + + // "Loading" means uninitialized or any state prior to fully running (processing commands). + bool isPluginLoading(void) const { return mPlugin ? mPlugin->isLoading() : false; } + + // "Running" means the steady state -- i.e. processing messages. + bool isPluginRunning(void) const { return mPlugin ? mPlugin->isRunning() : false; } + + // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally). + bool isPluginExited(void) const { return mPlugin ? mPlugin->isDone() : false; } + + std::string getPluginVersion() const { return mPlugin ? mPlugin->getPluginVersion() : std::string(""); } + + bool getDisableTimeout() const { return mPlugin ? mPlugin->getDisableTimeout() : false; } + + void setDisableTimeout(bool disable) { if (mPlugin) mPlugin->setDisableTimeout(disable); } + + enum EPriority + { + PRIORITY_SLEEP, // Sleep 1 second every message. + PRIORITY_LOW, // Sleep 1/25 second. + PRIORITY_NORMAL, // Sleep 1/50 second. + PRIORITY_HIGH // Sleep 1/100 second. + }; + + static char const* priorityToString(EPriority priority); + void setPriority(EPriority priority); + +protected: + EPriority mPriority; + LLPluginProcessParent* mPlugin; + +private: + F64 mSleepTime; + std::queue mSendQueue; // Used to queue messages while the plugin initializes. + +protected: + // Called as last function when calling 'init()'. + virtual bool init_impl(void) { return true; } + + // Called as last function when calling 'reset()'. + virtual void reset_impl(void) { } + + // Called from idle() before flushing messages to the plugin. + virtual void idle_impl(void) { } + + // Called from setPriority. + virtual void priorityChanged(EPriority priority) { } + + // Inherited from LLPluginProcessParentOwner. + /*virtual*/ void receivePluginMessage(LLPluginMessage const&); + + //-------------------------------------- + // Debug use only + // +private: + bool mDeleteOK; + +public: + void setDeleteOK(bool flag) { mDeleteOK = flag; } +}; + +#endif // LL_LLPLUGINCLASSBASIC_H diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 85241bec1..2bbad6011 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -54,49 +54,24 @@ static int nextPowerOf2( int value ) return next_power_of_2; } -LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) +LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner): mOwner(owner) { - mOwner = owner; - mPlugin = NULL; - reset(); - - //debug use - mDeleteOK = true ; + // Most initialization is done with reset_impl(), which we call here + // in order to avoid code duplication. + LLPluginClassMedia::reset_impl(); } - -LLPluginClassMedia::~LLPluginClassMedia() +bool LLPluginClassMedia::init_impl(void) { - llassert_always(mDeleteOK) ; - reset(); -} - -bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) -{ - LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; - LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; - - mPlugin = new LLPluginProcessParent(this); - mPlugin->setSleepTime(mSleepTime); - // Queue up the media init message -- it will be sent after all the currently queued messages. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init"); sendMessage(message); - - mPlugin->init(launcher_filename, plugin_filename, debug); return true; } - -void LLPluginClassMedia::reset() +void LLPluginClassMedia::reset_impl(void) { - if(mPlugin != NULL) - { - delete mPlugin; - mPlugin = NULL; - } - mTextureParamsReceived = false; mRequestedTextureDepth = 0; mRequestedTextureInternalFormat = 0; @@ -125,14 +100,12 @@ void LLPluginClassMedia::reset() mDirtyRect = LLRect::null; mAutoScaleMedia = false; mRequestedVolume = 1.0f; - mPriority = PRIORITY_NORMAL; mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; mAllowDownsample = false; mPadding = 0; mLastMouseX = 0; mLastMouseY = 0; mStatus = LLPluginClassMediaOwner::MEDIA_NONE; - mSleepTime = 1.0f / 100.0f; mCanCut = false; mCanCopy = false; mCanPaste = false; @@ -158,13 +131,8 @@ void LLPluginClassMedia::reset() mLoadedDuration = 0.0f; } -void LLPluginClassMedia::idle(void) +void LLPluginClassMedia::idle_impl(void) { - if(mPlugin) - { - mPlugin->idle(); - } - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked())) { // Can't process a size change at this time @@ -260,17 +228,6 @@ void LLPluginClassMedia::idle(void) LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; } } - - if(mPlugin && mPlugin->isRunning()) - { - // Send queued messages - while(!mSendQueue.empty()) - { - LLPluginMessage message = mSendQueue.front(); - mSendQueue.pop(); - mPlugin->sendMessage(message); - } - } } int LLPluginClassMedia::getTextureWidth() const @@ -295,18 +252,16 @@ unsigned char* LLPluginClassMedia::getBitsData() void LLPluginClassMedia::setSize(int width, int height) { - if((width > 0) && (height > 0)) + if (width <= 0 || height <= 0) + { + width = height = -1; + } + if (mSetMediaWidth != width || mSetMediaHeight != height) { mSetMediaWidth = width; mSetMediaHeight = height; + setSizeInternal(); } - else - { - mSetMediaWidth = -1; - mSetMediaHeight = -1; - } - - setSizeInternal(); } void LLPluginClassMedia::setSizeInternal(void) @@ -335,7 +290,7 @@ void LLPluginClassMedia::setSizeInternal(void) { switch(mPriority) { - case PRIORITY_SLIDESHOW: + case PRIORITY_SLEEP: case PRIORITY_LOW: // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) @@ -584,71 +539,10 @@ void LLPluginClassMedia::loadURI(const std::string &uri) sendMessage(message); } -const char* LLPluginClassMedia::priorityToString(EPriority priority) +void LLPluginClassMedia::priorityChanged(EPriority priority) { - const char* result = "UNKNOWN"; - switch(priority) - { - case PRIORITY_UNLOADED: result = "unloaded"; break; - case PRIORITY_STOPPED: result = "stopped"; break; - case PRIORITY_HIDDEN: result = "hidden"; break; - case PRIORITY_SLIDESHOW: result = "slideshow"; break; - case PRIORITY_LOW: result = "low"; break; - case PRIORITY_NORMAL: result = "normal"; break; - case PRIORITY_HIGH: result = "high"; break; - } - - return result; -} - -void LLPluginClassMedia::setPriority(EPriority priority) -{ - if(mPriority != priority) - { - mPriority = priority; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority"); - - std::string priority_string = priorityToString(priority); - switch(priority) - { - case PRIORITY_UNLOADED: - mSleepTime = 1.0f; - break; - case PRIORITY_STOPPED: - mSleepTime = 1.0f; - break; - case PRIORITY_HIDDEN: - mSleepTime = 1.0f; - break; - case PRIORITY_SLIDESHOW: - mSleepTime = 1.0f; - break; - case PRIORITY_LOW: - mSleepTime = 1.0f / 25.0f; - break; - case PRIORITY_NORMAL: - mSleepTime = 1.0f / 50.0f; - break; - case PRIORITY_HIGH: - mSleepTime = 1.0f / 100.0f; - break; - } - - message.setValue("priority", priority_string); - - sendMessage(message); - - if(mPlugin) - { - mPlugin->setSleepTime(mSleepTime); - } - - LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; - - // This may affect the calculated size, so recalculate it here. - setSizeInternal(); - } + // This may affect the calculated size, so recalculate it here. + setSizeInternal(); } void LLPluginClassMedia::setLowPrioritySizeLimit(int size) @@ -657,7 +551,6 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size) if(mLowPrioritySizeLimit != power) { mLowPrioritySizeLimit = power; - // This may affect the calculated size, so recalculate it here. setSizeInternal(); } @@ -726,7 +619,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + LLPluginClassBasic::receivePluginMessage(message); + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { std::string message_name = message.getName(); if(message_name == "texture_params") @@ -1003,10 +900,9 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) // } // else { - LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; + LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; } } - } /* virtual */ @@ -1029,19 +925,6 @@ void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event) } } -void LLPluginClassMedia::sendMessage(const LLPluginMessage &message) -{ - if(mPlugin && mPlugin->isRunning()) - { - mPlugin->sendMessage(message); - } - else - { - // The plugin isn't set up yet -- queue this message to be sent after initialization. - mSendQueue.push(message); - } -} - //////////////////////////////////////////////////////////// // MARK: media_browser class functions bool LLPluginClassMedia::pluginSupportsMediaBrowser(void) diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 0004971c6..1996c6588 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -36,29 +36,17 @@ #ifndef LL_LLPLUGINCLASSMEDIA_H #define LL_LLPLUGINCLASSMEDIA_H +#include "llpluginclassbasic.h" #include "llgltypes.h" -#include "llpluginprocessparent.h" #include "llrect.h" -#include "llpluginclassmediaowner.h" -#include #include "v4color.h" -class LLPluginClassMedia : public LLPluginProcessParentOwner +class LLPluginClassMedia : public LLPluginClassBasic { LOG_CLASS(LLPluginClassMedia); + public: LLPluginClassMedia(LLPluginClassMediaOwner *owner); - virtual ~LLPluginClassMedia(); - - // local initialization, called by the media manager when creating a source - virtual bool init(const std::string &launcher_filename, - const std::string &plugin_filename, - bool debug); - - // undoes everything init() didm called by the media manager when destroying a source - virtual void reset(); - - void idle(void); // All of these may return 0 or an actual valid value. // Callers need to check the return for 0, and not use the values in that case. @@ -101,22 +89,22 @@ public: bool getDirty(LLRect *dirty_rect = NULL); void resetDirty(void); - typedef enum + enum EMouseEventType { MOUSE_EVENT_DOWN, MOUSE_EVENT_UP, MOUSE_EVENT_MOVE, MOUSE_EVENT_DOUBLE_CLICK - }EMouseEventType; + }; void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers); - typedef enum + enum EKeyEventType { KEY_EVENT_DOWN, KEY_EVENT_UP, KEY_EVENT_REPEAT - }EKeyEventType; + }; bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data); @@ -127,39 +115,13 @@ public: void loadURI(const std::string &uri); - // "Loading" means uninitialized or any state prior to fully running (processing commands) - bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; }; - - // "Running" means the steady state -- i.e. processing messages - bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; }; - - // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally) - bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; }; - - std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); }; - - bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; }; - void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); }; - // Inherited from LLPluginProcessParentOwner /* virtual */ void receivePluginMessage(const LLPluginMessage &message); /* virtual */ void pluginLaunchFailed(); /* virtual */ void pluginDied(); + // Inherited from LLPluginClassBasic + /* virtual */ void priorityChanged(EPriority priority); - - typedef enum - { - PRIORITY_UNLOADED, // media plugin isn't even loaded. - PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all. - PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc. - PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently - PRIORITY_LOW, // media is in the distance, may be rendered at reduced size - PRIORITY_NORMAL, // normal (default) priority - PRIORITY_HIGH // media has user focus and/or is taking up most of the screen - }EPriority; - - static const char* priorityToString(EPriority priority); - void setPriority(EPriority priority); void setLowPrioritySizeLimit(int size); F64 getCPUUsage(); @@ -256,17 +218,18 @@ public: void initializeUrlHistory(const LLSD& url_history); protected: - - LLPluginClassMediaOwner *mOwner; + virtual bool init_impl(void); + virtual void reset_impl(void); + virtual void idle_impl(void); // Notify this object's owner that an event has occurred. void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event); - void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly. - std::queue mSendQueue; // Used to queue messages while the plugin initializes. - void setSizeInternal(void); +protected: + LLPluginClassMediaOwner *mOwner; + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true S32 mRequestedTextureDepth; LLGLenum mRequestedTextureInternalFormat; @@ -313,16 +276,11 @@ protected: float mRequestedVolume; - // Priority of this media stream - EPriority mPriority; int mLowPrioritySizeLimit; bool mAllowDownsample; int mPadding; - - LLPluginProcessParent *mPlugin; - LLRect mDirtyRect; std::string translateModifiers(MASK modifiers); @@ -332,8 +290,6 @@ protected: int mLastMouseY; LLPluginClassMediaOwner::EMediaStatus mStatus; - - F64 mSleepTime; bool mCanCut; bool mCanCopy; @@ -363,15 +319,6 @@ protected: F64 mDuration; F64 mCurrentRate; F64 mLoadedDuration; - -//-------------------------------------- - //debug use only - // -private: - bool mDeleteOK ; -public: - void setDeleteOK(bool flag) { mDeleteOK = flag ;} -//-------------------------------------- }; #endif // LL_LLPLUGINCLASSMEDIA_H diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index 3a1395cd2..914eadcce 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -55,8 +55,8 @@ const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoin */ LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) : mDSOHandle(NULL), - mPluginUserData(NULL), - mPluginSendMessageFunction(NULL) + mPluginObject(NULL), + mReceiveMessageFunction(NULL) { mOwner = owner; } @@ -109,9 +109,9 @@ int LLPluginInstance::load(std::string &plugin_file) if(result == APR_SUCCESS) { - result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData); + result = init_function(&LLPluginInstance::staticReceiveMessage, this, &mReceiveMessageFunction, &mPluginObject); - if(result != APR_SUCCESS) + if(result != 0) { LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL; } @@ -120,6 +120,14 @@ int LLPluginInstance::load(std::string &plugin_file) return (int)result; } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called from LLPluginProcessChild::receiveMessageRaw +// for messages received from the viewer that are not internal. +// +// It sends the message to the DSO by calling the registered 'received' +// function (for example, FilepickerPlugin::receiveMessage). /** * Sends a message to the plugin. * @@ -127,10 +135,10 @@ int LLPluginInstance::load(std::string &plugin_file) */ void LLPluginInstance::sendMessage(const std::string &message) { - if(mPluginSendMessageFunction) + if(mReceiveMessageFunction) { LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL; - mPluginSendMessageFunction(message.c_str(), &mPluginUserData); + mReceiveMessageFunction(message.c_str(), &mPluginObject); } else { @@ -147,14 +155,19 @@ void LLPluginInstance::idle(void) } // static -void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data) +void LLPluginInstance::staticReceiveMessage(char const* message_string, LLPluginInstance** self_ptr) { - // TODO: validate that the user_data argument is still a valid LLPluginInstance pointer + // TODO: validate that the self argument is still a valid LLPluginInstance pointer // we could also use a key that's looked up in a map (instead of a direct pointer) for safety, but that's probably overkill - LLPluginInstance *self = (LLPluginInstance*)*user_data; - self->receiveMessage(message_string); + (*self_ptr)->receiveMessage(message_string); } +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called by a loaded DSO (through a function pointer, it +// is called from BasicPluginBase::sendMessage) for messages it wants to +// send to the viewer. It calls LLPluginProcessChild::receivePluginMessage. /** * Plugin receives message from plugin loader shell. * diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index 9cf6075ff..faa1cbb7f 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -51,6 +51,8 @@ public: virtual void receivePluginMessage(const std::string &message) = 0; }; +class BasicPluginBase; + /** * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. */ @@ -79,26 +81,28 @@ public: * @param[in] message_string Null-terminated C string * @param[in] user_data The opaque reference that the callee supplied during setup. */ - typedef void (*sendMessageFunction) (const char *message_string, void **user_data); + typedef void (*receiveMessageFunction)(char const* message_string, BasicPluginBase** plugin_object); + + typedef void (*sendMessageFunction)(char const* message_string, LLPluginInstance** plugin_instance); /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?) * * @param[in] host_user_data Data from plugin loader shell. * @param[in] plugin_send_function Function for sending from the plugin loader shell to plugin. */ - typedef int (*pluginInitFunction) (sendMessageFunction host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data); + typedef int (*pluginInitFunction)(sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, receiveMessageFunction* receive_message_function, BasicPluginBase** plugin_object); /** Name of plugin init function */ static const char *PLUGIN_INIT_FUNCTION_NAME; private: - static void staticReceiveMessage(const char *message_string, void **user_data); + static void staticReceiveMessage(char const* message_string, LLPluginInstance** plugin_instance); void receiveMessage(const char *message_string); apr_dso_handle_t *mDSOHandle; - void *mPluginUserData; - sendMessageFunction mPluginSendMessageFunction; + BasicPluginBase* mPluginObject; + receiveMessageFunction mReceiveMessageFunction; LLPluginInstanceMessageListener *mOwner; }; diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h index fe504c8b9..3c7b91750 100644 --- a/indra/llplugin/llpluginmessage.h +++ b/indra/llplugin/llpluginmessage.h @@ -99,8 +99,10 @@ public: // (this clears out all existing state before starting the parse) // Returns -1 on failure, otherwise returns the number of key/value pairs in the message. int parse(const std::string &message); - - + + // For debugging purposes. + friend std::ostream& operator<<(std::ostream& os, LLPluginMessage const& message) { return os << message.mMessage; } + private: LLSD mMessage; diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h index 8812a1676..b61720ab4 100644 --- a/indra/llplugin/llpluginmessageclasses.h +++ b/indra/llplugin/llpluginmessageclasses.h @@ -48,6 +48,9 @@ #define LLPLUGIN_MESSAGE_CLASS_BASE "base" #define LLPLUGIN_MESSAGE_CLASS_BASE_VERSION "1.0" +#define LLPLUGIN_MESSAGE_CLASS_BASIC "basic" +#define LLPLUGIN_MESSAGE_CLASS_BASIC_VERSION "1.0" + #define LLPLUGIN_MESSAGE_CLASS_MEDIA "media" #define LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION "1.0" diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index d2238236f..2c47087ab 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -286,6 +286,11 @@ bool LLPluginProcessChild::isDone(void) return result; } +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called by SLPlugin to send a message (originating from +// SLPlugin itself) to the loaded DSO. It calls LLPluginInstance::sendMessage. void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) { if (mInstance) @@ -305,15 +310,26 @@ void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) } } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called by SLPlugin to send 'message' to the viewer (the parent process). void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message) { std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL; + // Write the serialized message to the pipe. writeMessageRaw(buffer); } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called when the serialized message 'message' was received from the viewer. +// It parses the message and handles LLPLUGIN_MESSAGE_CLASS_INTERNAL. +// Other message classes are passed on to LLPluginInstance::sendMessage. void LLPluginProcessChild::receiveMessageRaw(const std::string &message) { // Incoming message from the TCP Socket @@ -449,7 +465,17 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) } } -/* virtual */ +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called from LLPluginInstance::receiveMessage +// for messages from a loaded DSO that have to be passed to the +// viewer. +// +// It handles the base messages that are responses to messages sent by this +// class, and passes the rest on to LLPluginMessagePipeOwner::writeMessageRaw +// to be written to the pipe. +/* virtual */ void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 2be917be6..35931426d 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -579,6 +579,9 @@ void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send) } } +// This is the viewer process (the parent process) +// +// This function is called to send a message to the plugin. void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { if(message.hasValue("blocking_response")) @@ -588,6 +591,11 @@ void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); } + if (message.hasValue("gorgon")) + { + // After this message it is expected that the plugin will not send any more messages for a long time. + mBlocked = true; + } std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; @@ -636,6 +644,16 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) } } +apr_status_t LLPluginProcessParent::socketError(apr_status_t error) +{ + mSocketError = error; + if (APR_STATUS_IS_EPIPE(error)) + { + errorState(); + } + return error; +}; + //static void LLPluginProcessParent::dirtyPollSet() { @@ -852,6 +870,10 @@ void LLPluginProcessParent::servicePoll() } } +// This the viewer process (the parent process). +// +// This function is called when a message is received from a plugin. +// It parses the message and passes it on to LLPluginProcessParent::receiveMessage. void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; @@ -863,6 +885,13 @@ void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { mBlocked = true; } + if(parsed.hasValue("perseus")) + { + mBlocked = false; + + // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + } if(mPolledInput) { @@ -905,6 +934,12 @@ void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) } } +// This is the viewer process (the parent process). +// +// This function is called for messages that have to +// be written to the plugin. +// Note that LLPLUGIN_MESSAGE_CLASS_INTERNAL messages +// are not sent to the plugin, but are handled here. void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index bba3643d6..a82407d05 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -99,6 +99,7 @@ public: /*virtual*/ void receiveMessageRaw(const std::string &message); /*virtual*/ void receiveMessageEarly(const LLPluginMessage &message); /*virtual*/ void setMessagePipe(LLPluginMessagePipe *message_pipe) ; + /*virtual*/ apr_status_t socketError(apr_status_t error); // This adds a memory segment shared with the client, generating a name for the segment. The name generated is guaranteed to be unique on the host. // The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name.