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.
This commit is contained in:
Aleric Inglewood
2011-05-06 15:00:50 +02:00
parent e89d6d9d66
commit 784fdd4f37
12 changed files with 457 additions and 226 deletions

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 <string>
#include <queue>
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<LLPluginMessage> 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

View File

@@ -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)

View File

@@ -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 <queue>
#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<LLPluginMessage> 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

View File

@@ -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.
*

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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"

View File

@@ -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;

View File

@@ -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();

View File

@@ -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.