summaryrefslogtreecommitdiff
path: root/indra/llplugin
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llplugin')
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp2134
-rw-r--r--indra/llplugin/llpluginclassmedia.h840
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h74
-rw-r--r--indra/llplugin/llplugininstance.cpp182
-rw-r--r--indra/llplugin/llplugininstance.h80
-rw-r--r--indra/llplugin/llpluginmessage.cpp266
-rw-r--r--indra/llplugin/llpluginmessage.h150
-rw-r--r--indra/llplugin/llpluginmessageclasses.h12
-rw-r--r--indra/llplugin/llpluginmessagepipe.cpp596
-rw-r--r--indra/llplugin/llpluginmessagepipe.h96
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp962
-rw-r--r--indra/llplugin/llpluginprocesschild.h142
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp1724
-rw-r--r--indra/llplugin/llpluginprocessparent.h272
-rw-r--r--indra/llplugin/llpluginsharedmemory.cpp522
-rw-r--r--indra/llplugin/llpluginsharedmemory.h90
-rw-r--r--indra/llplugin/slplugin/slplugin-objc.h10
-rw-r--r--indra/llplugin/slplugin/slplugin.cpp284
18 files changed, 4218 insertions, 4218 deletions
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index d45600763d..0ab79c4901 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -42,331 +42,331 @@ static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
static int nextPowerOf2( int value )
{
- int next_power_of_2 = 1;
- while ( next_power_of_2 < value )
- {
- next_power_of_2 <<= 1;
- }
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
- return next_power_of_2;
+ return next_power_of_2;
}
LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
{
- mOwner = owner;
- reset();
+ mOwner = owner;
+ reset();
- //debug use
- mDeleteOK = true ;
+ //debug use
+ mDeleteOK = true ;
}
LLPluginClassMedia::~LLPluginClassMedia()
{
- llassert_always(mDeleteOK) ;
- reset();
+ llassert_always(mDeleteOK) ;
+ reset();
}
bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
{
- LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
- LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
- LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
- mPlugin = LLPluginProcessParent::create(this);
- mPlugin->setSleepTime(mSleepTime);
+ mPlugin = LLPluginProcessParent::create(this);
+ mPlugin->setSleepTime(mSleepTime);
- // Queue up the media init message -- it will be sent after all the currently queued messages.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
- message.setValue("target", mTarget);
- message.setValueReal("factor", mZoomFactor);
- sendMessage(message);
+ // Queue up the media init message -- it will be sent after all the currently queued messages.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+ message.setValue("target", mTarget);
+ message.setValueReal("factor", mZoomFactor);
+ sendMessage(message);
- mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
- return true;
+ return true;
}
void LLPluginClassMedia::reset()
{
- if(mPlugin)
- {
+ if(mPlugin)
+ {
mPlugin->requestShutdown();
mPlugin.reset();
- }
-
- mTextureParamsReceived = false;
- mRequestedTextureDepth = 0;
- mRequestedTextureInternalFormat = 0;
- mRequestedTextureFormat = 0;
- mRequestedTextureType = 0;
- mRequestedTextureSwapBytes = false;
- mRequestedTextureCoordsOpenGL = false;
- mTextureSharedMemorySize = 0;
- mTextureSharedMemoryName.clear();
- mDefaultMediaWidth = 0;
- mDefaultMediaHeight = 0;
- mNaturalMediaWidth = 0;
- mNaturalMediaHeight = 0;
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- mRequestedMediaWidth = 0;
- mRequestedMediaHeight = 0;
- mRequestedTextureWidth = 0;
- mRequestedTextureHeight = 0;
- mFullMediaWidth = 0;
- mFullMediaHeight = 0;
- mTextureWidth = 0;
- mTextureHeight = 0;
- mMediaWidth = 0;
- mMediaHeight = 0;
- mDirtyRect = LLRect::null;
- mAutoScaleMedia = false;
- mRequestedVolume = 0.0f;
- mPriority = PRIORITY_NORMAL;
- mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
- mAllowDownsample = false;
- mPadding = 0;
- mLastMouseX = 0;
- mLastMouseY = 0;
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- mSleepTime = 1.0f / 100.0f;
- mCanCut = false;
- mCanCopy = false;
- mCanPaste = false;
- mMediaName.clear();
- mMediaDescription.clear();
- mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-
- // media_browser class
- mNavigateURI.clear();
- mNavigateResultCode = -1;
- mNavigateResultString.clear();
- mHistoryBackAvailable = false;
- mHistoryForwardAvailable = false;
- mStatusText.clear();
- mProgressPercent = 0;
- mClickURL.clear();
- mClickNavType.clear();
- mClickTarget.clear();
- mClickUUID.clear();
- mStatusCode = 0;
-
- mClickEnforceTarget = false;
-
- // media_time class
- mCurrentTime = 0.0f;
- mDuration = 0.0f;
- mCurrentRate = 0.0f;
- mLoadedDuration = 0.0f;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mRequestedTextureWidth = 0;
+ mRequestedTextureHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 0.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickNavType.clear();
+ mClickTarget.clear();
+ mClickUUID.clear();
+ mStatusCode = 0;
+
+ mClickEnforceTarget = false;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
}
void LLPluginClassMedia::idle(void)
{
- if(mPlugin)
- {
- mPlugin->idle();
- }
-
- if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
- {
- // Can't process a size change at this time
- }
- else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
- {
- // Calculate the correct size for the media texture
- mRequestedTextureHeight = mRequestedMediaHeight;
- if(mPadding < 0)
- {
- // negative values indicate the plugin wants a power of 2
- mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
- }
- else
- {
- mRequestedTextureWidth = mRequestedMediaWidth;
-
- if(mPadding > 1)
- {
- // Pad up to a multiple of the specified number of bytes per row
- int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
- int pad = rowbytes % mPadding;
- if(pad != 0)
- {
- rowbytes += mPadding - pad;
- }
-
- if(rowbytes % mRequestedTextureDepth == 0)
- {
- mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
- }
- else
- {
- LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
- }
- }
- }
-
-
- // Size change has been requested but not initiated yet.
- size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
- // Add an extra line for padding, just in case.
- newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
- if(newsize != mTextureSharedMemorySize)
- {
- if(!mTextureSharedMemoryName.empty())
- {
- // Tell the plugin to remove the old memory segment
- mPlugin->removeSharedMemory(mTextureSharedMemoryName);
- mTextureSharedMemoryName.clear();
- }
-
- mTextureSharedMemorySize = newsize;
- mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
- if(!mTextureSharedMemoryName.empty())
- {
- void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-
- // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
- if (addr)
- {
- memset( addr, 0x00, newsize );
- }
- else
- {
- LL_WARNS("Plugin") << "Failed to get previously created shared memory address: " << mTextureSharedMemoryName << " size: " << mTextureSharedMemorySize << LL_ENDL;
- }
-
- // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
- // so it may not be worthwhile.
- // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
- }
- }
-
- // This is our local indicator that a change is in progress.
- mTextureWidth = -1;
- mTextureHeight = -1;
- mMediaWidth = -1;
- mMediaHeight = -1;
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // Send a size change message to the plugin
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
- message.setValue("name", mTextureSharedMemoryName);
- message.setValueS32("width", mRequestedMediaWidth);
- message.setValueS32("height", mRequestedMediaHeight);
- message.setValueS32("texture_width", mRequestedTextureWidth);
- message.setValueS32("texture_height", mRequestedTextureHeight);
- message.setValueReal("background_r", mBackgroundColor.mV[VX]);
- message.setValueReal("background_g", mBackgroundColor.mV[VY]);
- message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
- message.setValueReal("background_a", mBackgroundColor.mV[VW]);
- mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-
- LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
- }
- }
-
- if(mPlugin && mPlugin->isRunning())
- {
- // Send queued messages
- while(!mSendQueue.empty())
- {
- LLPluginMessage message = mSendQueue.front();
- mSendQueue.pop();
- mPlugin->sendMessage(message);
- }
- }
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ if (addr)
+ {
+ memset( addr, 0x00, newsize );
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Failed to get previously created shared memory address: " << mTextureSharedMemoryName << " size: " << mTextureSharedMemorySize << LL_ENDL;
+ }
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
}
int LLPluginClassMedia::getTextureWidth() const
{
- return nextPowerOf2(mTextureWidth);
+ return nextPowerOf2(mTextureWidth);
}
int LLPluginClassMedia::getTextureHeight() const
{
- return nextPowerOf2(mTextureHeight);
+ return nextPowerOf2(mTextureHeight);
}
unsigned char* LLPluginClassMedia::getBitsData()
{
- unsigned char *result = NULL;
- if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
- {
- result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
- }
- return result;
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
}
void LLPluginClassMedia::setSize(int width, int height)
{
- if((width > 0) && (height > 0))
- {
- mSetMediaWidth = width;
- mSetMediaHeight = height;
- }
- else
- {
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- }
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
- setSizeInternal();
+ setSizeInternal();
}
void LLPluginClassMedia::setSizeInternal(void)
{
- if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
- {
- mRequestedMediaWidth = mSetMediaWidth;
- mRequestedMediaHeight = mSetMediaHeight;
- }
- else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
- {
- mRequestedMediaWidth = mNaturalMediaWidth;
- mRequestedMediaHeight = mNaturalMediaHeight;
- }
- else
- {
- mRequestedMediaWidth = mDefaultMediaWidth;
- mRequestedMediaHeight = mDefaultMediaHeight;
- }
-
- // Save these for size/interest calculations
- mFullMediaWidth = mRequestedMediaWidth;
- mFullMediaHeight = mRequestedMediaHeight;
-
- if(mAllowDownsample)
- {
- switch(mPriority)
- {
- case PRIORITY_SLIDESHOW:
- case PRIORITY_LOW:
- // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
- while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
- {
- mRequestedMediaWidth /= 2;
- mRequestedMediaHeight /= 2;
- }
- break;
-
- default:
- // Don't adjust texture size
- break;
- }
- }
-
- if(mAutoScaleMedia)
- {
- mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
- mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
- }
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
#if LL_DARWIN
if (!gHiDPISupport)
@@ -382,312 +382,312 @@ void LLPluginClassMedia::setSizeInternal(void)
void LLPluginClassMedia::setAutoScale(bool auto_scale)
{
- if(auto_scale != mAutoScaleMedia)
- {
- mAutoScaleMedia = auto_scale;
- setSizeInternal();
- }
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
}
bool LLPluginClassMedia::textureValid(void)
{
- if(
- !mTextureParamsReceived ||
- mTextureWidth <= 0 ||
- mTextureHeight <= 0 ||
- mMediaWidth <= 0 ||
- mMediaHeight <= 0 ||
- mRequestedMediaWidth != mMediaWidth ||
- mRequestedMediaHeight != mMediaHeight ||
- getBitsData() == NULL
- )
- return false;
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
- return true;
+ return true;
}
bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
{
- bool result = !mDirtyRect.isEmpty();
+ bool result = !mDirtyRect.isEmpty();
- if(dirty_rect != NULL)
- {
- *dirty_rect = mDirtyRect;
- }
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
- return result;
+ return result;
}
void LLPluginClassMedia::resetDirty(void)
{
- mDirtyRect = LLRect::null;
+ mDirtyRect = LLRect::null;
}
std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
{
- std::string result;
+ std::string result;
- if(modifiers & MASK_CONTROL)
- {
- result += "control|";
- }
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
- if(modifiers & MASK_ALT)
- {
- result += "alt|";
- }
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
- if(modifiers & MASK_SHIFT)
- {
- result += "shift|";
- }
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
- // TODO: should I deal with platform differences here or in callers?
- // TODO: how do we deal with the Mac "command" key?
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
/*
- if(modifiers & MASK_SOMETHING)
- {
- result += "meta|";
- }
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
*/
- return result;
+ return result;
}
void LLPluginClassMedia::jsEnableObject( bool enable )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
- message.setValueBoolean( "enable", enable );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
- message.setValueReal( "angle", angle );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+ message.setValueReal( "angle", angle );
- sendMessage( message );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
- message.setValue( "language", language );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+ message.setValue( "language", language );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
- message.setValue( "region", region );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+ message.setValue( "region", region );
+ sendMessage( message );
}
void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
- message.setValue( "maturity", maturity );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+ message.setValue( "maturity", maturity );
+ sendMessage( message );
}
void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
{
- if(type == MOUSE_EVENT_MOVE)
- {
- if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
- {
- // Don't queue up mouse move events that can't be delivered.
- return;
- }
-
- if((x == mLastMouseX) && (y == mLastMouseY))
- {
- // Don't spam unnecessary mouse move events.
- return;
- }
-
- mLastMouseX = x;
- mLastMouseY = y;
- }
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+ {
+ // Don't queue up mouse move events that can't be delivered.
+ return;
+ }
+
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
- std::string temp;
- switch(type)
- {
- case MOUSE_EVENT_DOWN: temp = "down"; break;
- case MOUSE_EVENT_UP: temp = "up"; break;
- case MOUSE_EVENT_MOVE: temp = "move"; break;
- case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
- }
- message.setValue("event", temp);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
- message.setValueS32("button", button);
+ message.setValueS32("button", button);
- message.setValueS32("x", x);
+ message.setValueS32("x", x);
- // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
- if(!mRequestedTextureCoordsOpenGL)
- {
- // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
- y = mMediaHeight - y;
- }
- message.setValueS32("y", y);
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
- message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValue("modifiers", translateModifiers(modifiers));
- sendMessage(message);
+ sendMessage(message);
}
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
{
- bool result = true;
-
- // FIXME:
- // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
- // For now, return false for the ones the webkit plugin won't handle properly.
-
- switch(key_code)
- {
- case KEY_BACKSPACE:
- case KEY_TAB:
- case KEY_RETURN:
- case KEY_PAD_RETURN:
- case KEY_SHIFT:
- case KEY_CONTROL:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_ESCAPE:
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_END:
- case KEY_HOME:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_INSERT:
- case KEY_DELETE:
- // These will be handled
- break;
-
- default:
- // regular ASCII characters will also be handled
- if(key_code >= KEY_SPECIAL)
- {
- // Other "special" codes will not work properly.
- result = false;
- }
- break;
- }
+ bool result = true;
-#if LL_DARWIN
- if(modifiers & MASK_ALT)
- {
- // Option-key modified characters should be handled by the unicode input path instead of this one.
- result = false;
- }
-#endif
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
- if(result)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
- std::string temp;
- switch(type)
- {
- case KEY_EVENT_DOWN: temp = "down"; break;
- case KEY_EVENT_UP: temp = "up"; break;
- case KEY_EVENT_REPEAT: temp = "repeat"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("key", key_code);
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
- sendMessage(message);
- }
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+ }
- return result;
+ return result;
}
void LLPluginClassMedia::scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
- message.setValueS32("x", x);
- message.setValueS32("y", y);
- message.setValueS32("clicks_x", clicks_x);
- message.setValueS32("clicks_y", clicks_y);
- message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValueS32("clicks_x", clicks_x);
+ message.setValueS32("clicks_y", clicks_y);
+ message.setValue("modifiers", translateModifiers(modifiers));
- sendMessage(message);
+ sendMessage(message);
}
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
- message.setValue("text", text);
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
- sendMessage(message);
+ sendMessage(message);
- return true;
+ return true;
}
// This function injects a previously stored OpenID cookie into
@@ -695,7 +695,7 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
// that the way we use the cache, shared between multiple CEF
// instances means that sometimes the OpenID cookie cannot be read
// even though it appears to be there. The long term solution to
-// this is to create a separate cache directory for each instance
+// this is to create a separate cache directory for each instance
// but that has its own set of problems. This short term approach
// "forces" each new media instance to have a copy of the cookie
// so that a page that needs it - e.g. Profiles - finds it and
@@ -703,7 +703,7 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
void LLPluginClassMedia::injectOpenIDCookie()
{
// can be called before we know who the user is at login
- // and there is no OpenID cookie at that point so no
+ // and there is no OpenID cookie at that point so no
// need to try to set it (these values will all be empty)
if (sOIDcookieName.length() && sOIDcookieValue.length())
{
@@ -715,9 +715,9 @@ void LLPluginClassMedia::injectOpenIDCookie()
// We store each component of the OpenI cookie individuality here
// because previously, there was some significant parsing to
// break up the raw string into these components and we do not
-// want to have to do that again here. Stored as statics because
-// we want to share their value between all instances of this
-// class - the ones that receive it at login and any others
+// want to have to do that again here. Stored as statics because
+// we want to share their value between all instances of this
+// class - the ones that receive it at login and any others
// that open afterwards (e.g. the Profiles floater)
std::string LLPluginClassMedia::sOIDcookieUrl = std::string();
std::string LLPluginClassMedia::sOIDcookieName = std::string();
@@ -752,766 +752,766 @@ void LLPluginClassMedia::storeOpenIDCookie(const std::string url,
void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
- message.setValue("uri", uri);
- message.setValue("name", name);
- message.setValue("value", value);
- message.setValue("domain", domain);
- message.setValue("path", path);
- message.setValueBoolean("httponly", httponly);
- message.setValueBoolean("secure", secure);
+ message.setValue("uri", uri);
+ message.setValue("name", name);
+ message.setValue("value", value);
+ message.setValue("domain", domain);
+ message.setValue("path", path);
+ message.setValueBoolean("httponly", httponly);
+ message.setValueBoolean("secure", secure);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::loadURI(const std::string &uri)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
- message.setValue("uri", uri);
+ message.setValue("uri", uri);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::executeJavaScript(const std::string &code)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "execute_javascript");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "execute_javascript");
- message.setValue("code", code);
+ message.setValue("code", code);
- sendMessage(message);
+ sendMessage(message);
}
const char* LLPluginClassMedia::priorityToString(EPriority priority)
{
- const char* result = "UNKNOWN";
- switch(priority)
- {
- case PRIORITY_UNLOADED: result = "unloaded"; break;
- case PRIORITY_STOPPED: result = "stopped"; break;
- case PRIORITY_HIDDEN: result = "hidden"; break;
- case PRIORITY_SLIDESHOW: result = "slideshow"; break;
- case PRIORITY_LOW: result = "low"; break;
- case PRIORITY_NORMAL: result = "normal"; break;
- case PRIORITY_HIGH: result = "high"; break;
- }
+ 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;
+ 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();
- }
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
}
void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
{
- int power = nextPowerOf2(size);
- if(mLowPrioritySizeLimit != power)
- {
- mLowPrioritySizeLimit = power;
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
}
F64 LLPluginClassMedia::getCPUUsage()
{
- F64 result = 0.0f;
+ F64 result = 0.0f;
- if(mPlugin)
- {
- result = mPlugin->getCPUUsage();
- }
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
- return result;
+ return result;
}
void LLPluginClassMedia::sendPickFileResponse(const std::vector<std::string> files)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
- LLSD file_list = LLSD::emptyArray();
- for (std::vector<std::string>::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter)
- {
- file_list.append(LLSD::String(*in_iter));
- }
- message.setValueLLSD("file_list", file_list);
+ LLSD file_list = LLSD::emptyArray();
+ for (std::vector<std::string>::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter)
+ {
+ file_list.append(LLSD::String(*in_iter));
+ }
+ message.setValueLLSD("file_list", file_list);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
- message.setValueBoolean("ok", ok);
- message.setValue("username", username);
- message.setValue("password", password);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
}
void LLPluginClassMedia::cut()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
}
void LLPluginClassMedia::copy()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
}
void LLPluginClassMedia::paste()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
}
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache,
- const std::string &username,
- const std::string &user_data_path_cef_log)
+ const std::string &username,
+ const std::string &user_data_path_cef_log)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
message.setValue("cache_path", user_data_path_cache);
message.setValue("username", username); // cef shares cache between users but creates user-based contexts
- message.setValue("cef_log_file", user_data_path_cef_log);
+ message.setValue("cef_log_file", user_data_path_cef_log);
- bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog");
- message.setValueBoolean("cef_verbose_log", cef_verbose_log);
- sendMessage(message);
+ bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog");
+ message.setValueBoolean("cef_verbose_log", cef_verbose_log);
+ sendMessage(message);
}
void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
- message.setValue("language", language_code);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+ message.setValue("language", language_code);
+ sendMessage(message);
}
void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "plugins_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "plugins_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
}
void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "javascript_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "javascript_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
}
void LLPluginClassMedia::setWebSecurityDisabled(const bool disabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "web_security_disabled");
- message.setValueBoolean("disabled", disabled);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "web_security_disabled");
+ message.setValueBoolean("disabled", disabled);
+ sendMessage(message);
}
void LLPluginClassMedia::setFileAccessFromFileUrlsEnabled(const bool enabled)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "file_access_from_file_urls");
- message.setValueBoolean("enabled", enabled);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "file_access_from_file_urls");
+ message.setValueBoolean("enabled", enabled);
+ sendMessage(message);
}
void LLPluginClassMedia::enableMediaPluginDebugging( bool enable )
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_media_plugin_debugging");
- message.setValueBoolean( "enable", enable );
- sendMessage( message );
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_media_plugin_debugging");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
}
void LLPluginClassMedia::setTarget(const std::string &target)
{
- mTarget = target;
+ mTarget = target;
}
/* virtual */
void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
- std::string message_class = message.getClass();
-
- if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- std::string message_name = message.getName();
- if(message_name == "texture_params")
- {
- mRequestedTextureDepth = message.getValueS32("depth");
- mRequestedTextureInternalFormat = message.getValueU32("internalformat");
- mRequestedTextureFormat = message.getValueU32("format");
- mRequestedTextureType = message.getValueU32("type");
- mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
- mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
-
- // These two are optional, and will default to 0 if they're not specified.
- mDefaultMediaWidth = message.getValueS32("default_width");
- mDefaultMediaHeight = message.getValueS32("default_height");
-
- mAllowDownsample = message.getValueBoolean("allow_downsample");
- mPadding = message.getValueS32("padding");
-
- setSizeInternal();
-
- mTextureParamsReceived = true;
- }
- else if(message_name == "updated")
- {
- if(message.hasValue("left"))
- {
- LLRect newDirtyRect;
- newDirtyRect.mLeft = message.getValueS32("left");
- newDirtyRect.mTop = message.getValueS32("top");
- newDirtyRect.mRight = message.getValueS32("right");
- newDirtyRect.mBottom = message.getValueS32("bottom");
-
- // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
- // If they're backwards, swap them.
- if(newDirtyRect.mTop < newDirtyRect.mBottom)
- {
- S32 temp = newDirtyRect.mTop;
- newDirtyRect.mTop = newDirtyRect.mBottom;
- newDirtyRect.mBottom = temp;
- }
-
- if(mDirtyRect.isEmpty())
- {
- mDirtyRect = newDirtyRect;
- }
- else
- {
- mDirtyRect.unionWith(newDirtyRect);
- }
-
- LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
- << newDirtyRect.mLeft << ", "
- << newDirtyRect.mTop << ", "
- << newDirtyRect.mRight << ", "
- << newDirtyRect.mBottom << "), new dirty rect is: ("
- << mDirtyRect.mLeft << ", "
- << mDirtyRect.mTop << ", "
- << mDirtyRect.mRight << ", "
- << mDirtyRect.mBottom << ")"
- << LL_ENDL;
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
- }
-
-
- bool time_duration_updated = false;
- int previous_percent = mProgressPercent;
-
- if(message.hasValue("current_time"))
- {
- mCurrentTime = message.getValueReal("current_time");
- time_duration_updated = true;
- }
- if(message.hasValue("duration"))
- {
- mDuration = message.getValueReal("duration");
- time_duration_updated = true;
- }
-
- if(message.hasValue("current_rate"))
- {
- mCurrentRate = message.getValueReal("current_rate");
- }
-
- if(message.hasValue("loaded_duration"))
- {
- mLoadedDuration = message.getValueReal("loaded_duration");
- time_duration_updated = true;
- }
- else
- {
- // If the message doesn't contain a loaded_duration param, assume it's equal to duration
- mLoadedDuration = mDuration;
- }
-
- // Calculate a percentage based on the loaded duration and total duration.
- if(mDuration != 0.0f) // Don't divide by zero.
- {
- mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
- }
-
- if(time_duration_updated)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
- }
-
- if(previous_percent != mProgressPercent)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- }
- else if(message_name == "media_status")
- {
- std::string status = message.getValue("status");
-
- LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-
- if(status == "loading")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
- }
- else if(status == "loaded")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
- }
- else if(status == "error")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
- }
- else if(status == "playing")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
- }
- else if(status == "paused")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
- }
- else if(status == "done")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
- }
- else
- {
- // empty string or any unknown string
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- }
- }
- else if(message_name == "size_change_request")
- {
- S32 width = message.getValueS32("width");
- S32 height = message.getValueS32("height");
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
- mNaturalMediaWidth = width;
- mNaturalMediaHeight = height;
-
- setSizeInternal();
- }
- else if(message_name == "size_change_response")
- {
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
-
- mTextureWidth = message.getValueS32("texture_width");
- mTextureHeight = message.getValueS32("texture_height");
- mMediaWidth = message.getValueS32("width");
- mMediaHeight = message.getValueS32("height");
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // TODO: should we verify that the plugin sent back the right values?
- // Two size changes in a row may cause them to not match, due to queueing, etc.
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
- }
- else if(message_name == "cursor_changed")
- {
- mCursorName = message.getValue("name");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
- }
- else if(message_name == "edit_state")
- {
- if(message.hasValue("cut"))
- {
- mCanCut = message.getValueBoolean("cut");
- }
- if(message.hasValue("copy"))
- {
- mCanCopy = message.getValueBoolean("copy");
- }
- if(message.hasValue("paste"))
- {
- mCanPaste = message.getValueBoolean("paste");
- }
- }
- else if(message_name == "name_text")
- {
- mHistoryBackAvailable = message.getValueBoolean("history_back_available");
- mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
- mMediaName = message.getValue("name");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
- }
- else if(message_name == "pick_file")
- {
- mIsMultipleFilePick = message.getValueBoolean("multiple_files");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
- }
- else if(message_name == "auth_request")
- {
- mAuthURL = message.getValue("url");
- mAuthRealm = message.getValue("realm");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
- }
- else if (message_name == "file_download")
- {
- mFileDownloadFilename = message.getValue("filename");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD);
- }
- else if(message_name == "debug_message")
- {
- mDebugMessageText = message.getValue("message_text");
- mDebugMessageLevel = message.getValue("message_level");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
- }
- else if (message_name == "tooltip_text")
- {
- mHoverText = message.getValue("tooltip");
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
- {
- std::string message_name = message.getName();
- if(message_name == "navigate_begin")
- {
- mNavigateURI = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
- }
- else if(message_name == "navigate_complete")
- {
- mNavigateURI = message.getValue("uri");
- mNavigateResultCode = message.getValueS32("result_code");
- mNavigateResultString = message.getValue("result_string");
- mHistoryBackAvailable = message.getValueBoolean("history_back_available");
- mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
- }
- else if(message_name == "progress")
- {
- mProgressPercent = message.getValueS32("percent");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- else if(message_name == "status_text")
- {
- mStatusText = message.getValue("status");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
- }
- else if(message_name == "location_changed")
- {
- mLocation = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
- }
- else if(message_name == "click_href")
- {
- mClickURL = message.getValue("uri");
- mClickTarget = message.getValue("target");
-
- // need a link to have a UUID that identifies it to a system further
- // upstream - plugin could make it but we have access to LLUUID here
- // so why don't we use it
- mClickUUID = LLUUID::generateNewID().asString();
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
- }
- else if(message_name == "click_nofollow")
- {
- mClickURL = message.getValue("uri");
- mClickNavType = message.getValue("nav_type");
- mClickTarget.clear();
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
- }
- else if(message_name == "navigate_error_page")
- {
- mStatusCode = message.getValueS32("status_code");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
- }
- else if(message_name == "close_request")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
- }
- else if(message_name == "geometry_change")
- {
- mClickUUID = message.getValue("uuid");
- mGeometryX = message.getValueS32("x");
- mGeometryY = message.getValueS32("y");
- mGeometryWidth = message.getValueS32("width");
- mGeometryHeight = message.getValueS32("height");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
- }
- else if(message_name == "link_hovered")
- {
- // text is not currently used -- the tooltip hover text is taken from the "title".
- mHoverLink = message.getValue("link");
- mHoverText = message.getValue("title");
- // message.getValue("text");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- std::string message_name = message.getName();
-
- // This class hasn't defined any incoming messages yet.
-// if(message_name == "message_name")
-// {
-// }
-// else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else if(message_name == "pick_file")
+ {
+ mIsMultipleFilePick = message.getValueBoolean("multiple_files");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+ }
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
+ else if (message_name == "file_download")
+ {
+ mFileDownloadFilename = message.getValue("filename");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD);
+ }
+ else if(message_name == "debug_message")
+ {
+ mDebugMessageText = message.getValue("message_text");
+ mDebugMessageLevel = message.getValue("message_level");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
+ }
+ else if (message_name == "tooltip_text")
+ {
+ mHoverText = message.getValue("tooltip");
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+
+ // need a link to have a UUID that identifies it to a system further
+ // upstream - plugin could make it but we have access to LLUUID here
+ // so why don't we use it
+ mClickUUID = LLUUID::generateNewID().asString();
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickNavType = message.getValue("nav_type");
+ mClickTarget.clear();
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else if(message_name == "navigate_error_page")
+ {
+ mStatusCode = message.getValueS32("status_code");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+ }
+ else if(message_name == "close_request")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+ }
+ else if(message_name == "geometry_change")
+ {
+ mClickUUID = message.getValue("uuid");
+ mGeometryX = message.getValueS32("x");
+ mGeometryY = message.getValueS32("y");
+ mGeometryWidth = message.getValueS32("width");
+ mGeometryHeight = message.getValueS32("height");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+ }
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
}
/* virtual */
void LLPluginClassMedia::pluginLaunchFailed()
{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
}
/* virtual */
void LLPluginClassMedia::pluginDied()
{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
}
void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
{
- if(mOwner)
- {
- mOwner->handleMediaEvent(this, event);
- }
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
}
void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
{
- if(mPlugin && mPlugin->isRunning())
- {
- mPlugin->sendMessage(message);
- }
- else
- {
- // The plugin isn't set up yet -- queue this message to be sent after initialization.
- mSendQueue.push(message);
- }
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
}
////////////////////////////////////////////////////////////
// MARK: media_browser class functions
bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
- return !version.empty();
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
}
void LLPluginClassMedia::focus(bool focused)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
- message.setValueBoolean("focused", focused);
+ message.setValueBoolean("focused", focused);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::set_page_zoom_factor( F64 factor )
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor");
- message.setValueReal("factor", factor);
- sendMessage(message);
+ message.setValueReal("factor", factor);
+ sendMessage(message);
}
void LLPluginClassMedia::clear_cache()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
}
void LLPluginClassMedia::clear_cookies()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
}
void LLPluginClassMedia::cookies_enabled(bool enable)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookies_enabled");
- message.setValueBoolean("enable", enable);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookies_enabled");
+ message.setValueBoolean("enable", enable);
+ sendMessage(message);
}
void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
- message.setValueBoolean("enable", enable);
- message.setValue("host", host);
- message.setValueS32("port", port);
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::browse_stop()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
}
void LLPluginClassMedia::browse_reload(bool ignore_cache)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
- message.setValueBoolean("ignore_cache", ignore_cache);
+ message.setValueBoolean("ignore_cache", ignore_cache);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::browse_forward()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
}
void LLPluginClassMedia::browse_back()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
}
void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
- message.setValue("user_agent", user_agent);
+ message.setValue("user_agent", user_agent);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::showWebInspector( bool show )
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "show_web_inspector");
- message.setValueBoolean("show", true); // only open for now - closed manually by user
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "show_web_inspector");
+ message.setValueBoolean("show", true); // only open for now - closed manually by user
+ sendMessage(message);
}
void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
- message.setValue("target", target);
- message.setValue("uuid", uuid);
+ message.setValue("target", target);
+ message.setValue("uuid", uuid);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
- message.setValue("uuid", uuid);
+ message.setValue("uuid", uuid);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
- message.setValueBoolean("ignore", ignore);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
}
void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
- message.setValue("path", path);
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
}
void LLPluginClassMedia::setOverrideClickTarget(const std::string &target)
{
- mClickEnforceTarget = true;
- mOverrideClickTarget = target;
+ mClickEnforceTarget = true;
+ mOverrideClickTarget = target;
}
void LLPluginClassMedia::crashPlugin()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::hangPlugin()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
- sendMessage(message);
+ sendMessage(message);
}
@@ -1519,75 +1519,75 @@ void LLPluginClassMedia::hangPlugin()
// MARK: media_time class functions
bool LLPluginClassMedia::pluginSupportsMediaTime(void)
{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
- return !version.empty();
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
}
void LLPluginClassMedia::stop()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
}
void LLPluginClassMedia::start(float rate)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
- message.setValueReal("rate", rate);
+ message.setValueReal("rate", rate);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::pause()
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
- sendMessage(message);
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
}
void LLPluginClassMedia::seek(float time)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
- message.setValueReal("time", time);
+ message.setValueReal("time", time);
mCurrentTime = time; // assume that it worked and we will receive an update later
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::setLoop(bool loop)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
- message.setValueBoolean("loop", loop);
+ message.setValueBoolean("loop", loop);
- sendMessage(message);
+ sendMessage(message);
}
void LLPluginClassMedia::setVolume(float volume)
{
- if(volume != mRequestedVolume)
- {
- mRequestedVolume = volume;
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
- message.setValueReal("volume", volume);
+ message.setValueReal("volume", volume);
- sendMessage(message);
- }
+ sendMessage(message);
+ }
}
float LLPluginClassMedia::getVolume()
{
- return mRequestedVolume;
+ return mRequestedVolume;
}
void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
{
- // Send URL history to plugin
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
- message.setValueLLSD("history", url_history);
- sendMessage(message);
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
- LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
}
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index d56712257b..d74b790d8f 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginclassmedia.h
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -38,103 +38,103 @@
class LLPluginClassMedia : public LLPluginProcessParentOwner
{
- LOG_CLASS(LLPluginClassMedia);
+ LOG_CLASS(LLPluginClassMedia);
public:
- LLPluginClassMedia(LLPluginClassMediaOwner *owner);
- virtual ~LLPluginClassMedia();
-
- // local initialization, called by the media manager when creating a source
- bool init(const std::string &launcher_filename,
- const std::string &plugin_dir,
- const std::string &plugin_filename,
- bool debug);
-
- // undoes everything init() didm called by the media manager when destroying a source
- 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.
- int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
- int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
- int getNaturalWidth() const { return mNaturalMediaWidth; };
- int getNaturalHeight() const { return mNaturalMediaHeight; };
- int getSetWidth() const { return mSetMediaWidth; };
- int getSetHeight() const { return mSetMediaHeight; };
- int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
- int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
- int getTextureWidth() const;
- int getTextureHeight() const;
- int getFullWidth() const { return mFullMediaWidth; };
- int getFullHeight() const { return mFullMediaHeight; };
- F64 getZoomFactor() const { return mZoomFactor; };
-
- // This may return NULL. Callers need to check for and handle this case.
- unsigned char* getBitsData();
-
- // gets the format details of the texture data
- // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
- int getTextureDepth() const { return mRequestedTextureDepth; };
- int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
- int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
- int getTextureFormatType() const { return mRequestedTextureType; };
- bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
- bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
-
- void setSize(int width, int height);
- void setAutoScale(bool auto_scale);
- void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; }
-
- void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
-
- void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
-
- // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
- // This will initially be false, and will also be false for some time after setSize while the resize is processed.
- // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
- // until you call idle() again.
- bool textureValid(void);
-
- bool getDirty(LLRect *dirty_rect = NULL);
- void resetDirty(void);
-
- typedef enum
- {
- 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
- {
- KEY_EVENT_DOWN,
- KEY_EVENT_UP,
- KEY_EVENT_REPEAT
- }EKeyEventType;
-
- bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
-
- void scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers);
-
- // enable/disable media plugin debugging messages and info spam
- void enableMediaPluginDebugging( bool enable );
-
- // Javascript <-> viewer events
- void jsEnableObject( bool enable );
- void jsAgentLocationEvent( double x, double y, double z );
- void jsAgentGlobalLocationEvent( double x, double y, double z );
- void jsAgentOrientationEvent( double angle );
- void jsAgentLanguageEvent( const std::string& language );
- void jsAgentRegionEvent( const std::string& region_name );
- void jsAgentMaturityEvent( const std::string& maturity );
-
- // Text may be unicode (utf8 encoded)
- bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-
+ LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+ virtual ~LLPluginClassMedia();
+
+ // local initialization, called by the media manager when creating a source
+ bool init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
+ const std::string &plugin_filename,
+ bool debug);
+
+ // undoes everything init() didm called by the media manager when destroying a source
+ 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.
+ int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+ int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+ int getNaturalWidth() const { return mNaturalMediaWidth; };
+ int getNaturalHeight() const { return mNaturalMediaHeight; };
+ int getSetWidth() const { return mSetMediaWidth; };
+ int getSetHeight() const { return mSetMediaHeight; };
+ int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+ int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+ int getTextureWidth() const;
+ int getTextureHeight() const;
+ int getFullWidth() const { return mFullMediaWidth; };
+ int getFullHeight() const { return mFullMediaHeight; };
+ F64 getZoomFactor() const { return mZoomFactor; };
+
+ // This may return NULL. Callers need to check for and handle this case.
+ unsigned char* getBitsData();
+
+ // gets the format details of the texture data
+ // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
+ int getTextureDepth() const { return mRequestedTextureDepth; };
+ int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+ int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+ int getTextureFormatType() const { return mRequestedTextureType; };
+ bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+ bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+ void setSize(int width, int height);
+ void setAutoScale(bool auto_scale);
+ void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; }
+
+ void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+
+ void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+
+ // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+ // This will initially be false, and will also be false for some time after setSize while the resize is processed.
+ // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+ // until you call idle() again.
+ bool textureValid(void);
+
+ bool getDirty(LLRect *dirty_rect = NULL);
+ void resetDirty(void);
+
+ typedef enum
+ {
+ 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
+ {
+ KEY_EVENT_DOWN,
+ KEY_EVENT_UP,
+ KEY_EVENT_REPEAT
+ }EKeyEventType;
+
+ bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
+
+ void scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers);
+
+ // enable/disable media plugin debugging messages and info spam
+ void enableMediaPluginDebugging( bool enable );
+
+ // Javascript <-> viewer events
+ void jsEnableObject( bool enable );
+ void jsAgentLocationEvent( double x, double y, double z );
+ void jsAgentGlobalLocationEvent( double x, double y, double z );
+ void jsAgentOrientationEvent( double angle );
+ void jsAgentLanguageEvent( const std::string& language );
+ void jsAgentRegionEvent( const std::string& region_name );
+ void jsAgentMaturityEvent( const std::string& maturity );
+
+ // Text may be unicode (utf8 encoded)
+ bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+
static std::string sOIDcookieUrl;
static std::string sOIDcookieName;
static std::string sOIDcookieValue;
@@ -149,331 +149,331 @@ public:
void injectOpenIDCookie();
- void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
-
- void loadURI(const std::string &uri);
-
- void executeJavaScript(const std::string &code);
-
- // "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();
-
-
- 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();
-
- void sendPickFileResponse(const std::vector<std::string> files);
-
- void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
-
- // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
- std::string getCursorName() const { return mCursorName; };
-
- LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
-
- void cut();
- bool canCut() const { return mCanCut; };
-
- void copy();
- bool canCopy() const { return mCanCopy; };
-
- void paste();
- bool canPaste() const { return mCanPaste; };
-
- // These can be called before init(), and they will be queued and sent before the media init message.
- void setUserDataPath(const std::string &user_data_path_cache, const std::string &username, const std::string &user_data_path_cef_log);
- void setLanguageCode(const std::string &language_code);
- void setPluginsEnabled(const bool enabled);
- void setJavascriptEnabled(const bool enabled);
- void setWebSecurityDisabled(const bool disabled);
- void setFileAccessFromFileUrlsEnabled(const bool enabled);
- void setTarget(const std::string &target);
-
- ///////////////////////////////////
- // media browser class functions
- bool pluginSupportsMediaBrowser(void);
-
- void focus(bool focused);
- void set_page_zoom_factor( F64 factor );
- void clear_cache();
- void clear_cookies();
- void set_cookies(const std::string &cookies);
- void cookies_enabled(bool enable);
- void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
- void browse_stop();
- void browse_reload(bool ignore_cache = false);
- void browse_forward();
- void browse_back();
- void setBrowserUserAgent(const std::string& user_agent);
- void showWebInspector( bool show );
- void proxyWindowOpened(const std::string &target, const std::string &uuid);
- void proxyWindowClosed(const std::string &uuid);
- void ignore_ssl_cert_errors(bool ignore);
- void addCertificateFilePath(const std::string& path);
-
- // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
- std::string getNavigateURI() const { return mNavigateURI; };
-
- // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
- S32 getNavigateResultCode() const { return mNavigateResultCode; };
- std::string getNavigateResultString() const { return mNavigateResultString; };
- bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
- bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
-
- // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
- int getProgressPercent() const { return mProgressPercent; };
-
- // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
- std::string getStatusText() const { return mStatusText; };
-
- // This is valid after MEDIA_EVENT_LOCATION_CHANGED
- std::string getLocation() const { return mLocation; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickURL() const { return mClickURL; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickNavType() const { return mClickNavType; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
- std::string getClickTarget() const { return mClickTarget; };
-
- // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
- std::string getClickUUID() const { return mClickUUID; };
-
- // mClickTarget is received from message and governs how link will be opened
- // use this to enforce your own way of opening links inside plugins
- void setOverrideClickTarget(const std::string &target);
- void resetOverrideClickTarget() { mClickEnforceTarget = false; };
- bool isOverrideClickTarget() const { return mClickEnforceTarget; }
- std::string getOverrideClickTarget() const { return mOverrideClickTarget; };
-
- // These are valid during MEDIA_EVENT_DEBUG_MESSAGE
- std::string getDebugMessageText() const { return mDebugMessageText; };
- std::string getDebugMessageLevel() const { return mDebugMessageLevel; };
-
- // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
- S32 getStatusCode() const { return mStatusCode; };
-
- // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
- S32 getGeometryX() const { return mGeometryX; };
- S32 getGeometryY() const { return mGeometryY; };
- S32 getGeometryWidth() const { return mGeometryWidth; };
- S32 getGeometryHeight() const { return mGeometryHeight; };
-
- // These are valid during MEDIA_EVENT_AUTH_REQUEST
- std::string getAuthURL() const { return mAuthURL; };
- std::string getAuthRealm() const { return mAuthRealm; };
-
- // These are valid during MEDIA_EVENT_PICK_FILE_REQUEST
- bool getIsMultipleFilePick() const { return mIsMultipleFilePick; }
-
- // These are valid during MEDIA_EVENT_LINK_HOVERED
- std::string getHoverText() const { return mHoverText; };
- std::string getHoverLink() const { return mHoverLink; };
-
- // these are valid during MEDIA_EVENT_LINK_HOVERED
- std::string getFileDownloadFilename() const { return mFileDownloadFilename; }
-
-
- const std::string& getMediaName() const { return mMediaName; };
- std::string getMediaDescription() const { return mMediaDescription; };
-
- // Crash the plugin. If you use this outside of a testbed, you will be punished.
- void crashPlugin();
-
- // Hang the plugin. If you use this outside of a testbed, you will be punished.
- void hangPlugin();
-
- ///////////////////////////////////
- // media time class functions
- bool pluginSupportsMediaTime(void);
- void stop();
- void start(float rate = 0.0f);
- void pause();
- void seek(float time);
- void setLoop(bool loop);
- void setVolume(float volume);
- float getVolume();
-
- F64 getCurrentTime(void) const { return mCurrentTime; };
- F64 getDuration(void) const { return mDuration; };
- F64 getCurrentPlayRate(void) { return mCurrentRate; };
- F64 getLoadedDuration(void) const { return mLoadedDuration; };
-
- // Initialize the URL history of the plugin by sending
- // "init_history" message
- void initializeUrlHistory(const LLSD& url_history);
-
- std::shared_ptr<LLPluginClassMedia> getSharedPtr() { return std::dynamic_pointer_cast<LLPluginClassMedia>(shared_from_this()); } // due to enable_shared_from_this
+ void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
+
+ void loadURI(const std::string &uri);
+
+ void executeJavaScript(const std::string &code);
+
+ // "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();
+
+
+ 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();
+
+ void sendPickFileResponse(const std::vector<std::string> files);
+
+ void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
+ // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+ std::string getCursorName() const { return mCursorName; };
+
+ LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+ void cut();
+ bool canCut() const { return mCanCut; };
+
+ void copy();
+ bool canCopy() const { return mCanCopy; };
+
+ void paste();
+ bool canPaste() const { return mCanPaste; };
+
+ // These can be called before init(), and they will be queued and sent before the media init message.
+ void setUserDataPath(const std::string &user_data_path_cache, const std::string &username, const std::string &user_data_path_cef_log);
+ void setLanguageCode(const std::string &language_code);
+ void setPluginsEnabled(const bool enabled);
+ void setJavascriptEnabled(const bool enabled);
+ void setWebSecurityDisabled(const bool disabled);
+ void setFileAccessFromFileUrlsEnabled(const bool enabled);
+ void setTarget(const std::string &target);
+
+ ///////////////////////////////////
+ // media browser class functions
+ bool pluginSupportsMediaBrowser(void);
+
+ void focus(bool focused);
+ void set_page_zoom_factor( F64 factor );
+ void clear_cache();
+ void clear_cookies();
+ void set_cookies(const std::string &cookies);
+ void cookies_enabled(bool enable);
+ void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+ void browse_stop();
+ void browse_reload(bool ignore_cache = false);
+ void browse_forward();
+ void browse_back();
+ void setBrowserUserAgent(const std::string& user_agent);
+ void showWebInspector( bool show );
+ void proxyWindowOpened(const std::string &target, const std::string &uuid);
+ void proxyWindowClosed(const std::string &uuid);
+ void ignore_ssl_cert_errors(bool ignore);
+ void addCertificateFilePath(const std::string& path);
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+ std::string getNavigateURI() const { return mNavigateURI; };
+
+ // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+ S32 getNavigateResultCode() const { return mNavigateResultCode; };
+ std::string getNavigateResultString() const { return mNavigateResultString; };
+ bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+ bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+ // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+ int getProgressPercent() const { return mProgressPercent; };
+
+ // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+ std::string getStatusText() const { return mStatusText; };
+
+ // This is valid after MEDIA_EVENT_LOCATION_CHANGED
+ std::string getLocation() const { return mLocation; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickURL() const { return mClickURL; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickNavType() const { return mClickNavType; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ std::string getClickTarget() const { return mClickTarget; };
+
+ // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
+ std::string getClickUUID() const { return mClickUUID; };
+
+ // mClickTarget is received from message and governs how link will be opened
+ // use this to enforce your own way of opening links inside plugins
+ void setOverrideClickTarget(const std::string &target);
+ void resetOverrideClickTarget() { mClickEnforceTarget = false; };
+ bool isOverrideClickTarget() const { return mClickEnforceTarget; }
+ std::string getOverrideClickTarget() const { return mOverrideClickTarget; };
+
+ // These are valid during MEDIA_EVENT_DEBUG_MESSAGE
+ std::string getDebugMessageText() const { return mDebugMessageText; };
+ std::string getDebugMessageLevel() const { return mDebugMessageLevel; };
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
+ S32 getStatusCode() const { return mStatusCode; };
+
+ // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
+ S32 getGeometryX() const { return mGeometryX; };
+ S32 getGeometryY() const { return mGeometryY; };
+ S32 getGeometryWidth() const { return mGeometryWidth; };
+ S32 getGeometryHeight() const { return mGeometryHeight; };
+
+ // These are valid during MEDIA_EVENT_AUTH_REQUEST
+ std::string getAuthURL() const { return mAuthURL; };
+ std::string getAuthRealm() const { return mAuthRealm; };
+
+ // These are valid during MEDIA_EVENT_PICK_FILE_REQUEST
+ bool getIsMultipleFilePick() const { return mIsMultipleFilePick; }
+
+ // These are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getHoverText() const { return mHoverText; };
+ std::string getHoverLink() const { return mHoverLink; };
+
+ // these are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getFileDownloadFilename() const { return mFileDownloadFilename; }
+
+
+ const std::string& getMediaName() const { return mMediaName; };
+ std::string getMediaDescription() const { return mMediaDescription; };
+
+ // Crash the plugin. If you use this outside of a testbed, you will be punished.
+ void crashPlugin();
+
+ // Hang the plugin. If you use this outside of a testbed, you will be punished.
+ void hangPlugin();
+
+ ///////////////////////////////////
+ // media time class functions
+ bool pluginSupportsMediaTime(void);
+ void stop();
+ void start(float rate = 0.0f);
+ void pause();
+ void seek(float time);
+ void setLoop(bool loop);
+ void setVolume(float volume);
+ float getVolume();
+
+ F64 getCurrentTime(void) const { return mCurrentTime; };
+ F64 getDuration(void) const { return mDuration; };
+ F64 getCurrentPlayRate(void) { return mCurrentRate; };
+ F64 getLoadedDuration(void) const { return mLoadedDuration; };
+
+ // Initialize the URL history of the plugin by sending
+ // "init_history" message
+ void initializeUrlHistory(const LLSD& url_history);
+
+ std::shared_ptr<LLPluginClassMedia> getSharedPtr() { return std::dynamic_pointer_cast<LLPluginClassMedia>(shared_from_this()); } // due to enable_shared_from_this
protected:
- LLPluginClassMediaOwner *mOwner;
-
- // 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);
-
- bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
- S32 mRequestedTextureDepth;
- LLGLenum mRequestedTextureInternalFormat;
- LLGLenum mRequestedTextureFormat;
- LLGLenum mRequestedTextureType;
- bool mRequestedTextureSwapBytes;
- bool mRequestedTextureCoordsOpenGL;
-
- std::string mTextureSharedMemoryName;
- size_t mTextureSharedMemorySize;
-
- // True to scale requested media up to the full size of the texture (i.e. next power of two)
- bool mAutoScaleMedia;
-
- // default media size for the plugin, from the texture_params message.
- int mDefaultMediaWidth;
- int mDefaultMediaHeight;
-
- // Size that has been requested by the plugin itself
- int mNaturalMediaWidth;
- int mNaturalMediaHeight;
-
- // Size that has been requested with setSize()
- int mSetMediaWidth;
- int mSetMediaHeight;
-
- // Full calculated media size (before auto-scale and downsample calculations)
- int mFullMediaWidth;
- int mFullMediaHeight;
-
- // Actual media size being set (after auto-scale)
- int mRequestedMediaWidth;
- int mRequestedMediaHeight;
-
- // Texture size calculated from actual media size
- int mRequestedTextureWidth;
- int mRequestedTextureHeight;
-
- // Size that the plugin has acknowledged
- int mTextureWidth;
- int mTextureHeight;
- int mMediaWidth;
- int mMediaHeight;
-
- F64 mZoomFactor;
-
- float mRequestedVolume;
-
- // Priority of this media stream
- EPriority mPriority;
- int mLowPrioritySizeLimit;
-
- bool mAllowDownsample;
- int mPadding;
-
-
- LLPluginProcessParent::ptr_t mPlugin;
-
- LLRect mDirtyRect;
-
- std::string translateModifiers(MASK modifiers);
-
- std::string mCursorName;
- int mLastMouseX;
- int mLastMouseY;
-
- LLPluginClassMediaOwner::EMediaStatus mStatus;
-
- F64 mSleepTime;
-
- bool mCanCut;
- bool mCanCopy;
- bool mCanPaste;
-
- std::string mMediaName;
- std::string mMediaDescription;
-
- LLColor4 mBackgroundColor;
-
- std::string mTarget;
-
- /////////////////////////////////////////
- // media_browser class
- std::string mNavigateURI;
- S32 mNavigateResultCode;
- std::string mNavigateResultString;
- bool mHistoryBackAvailable;
- bool mHistoryForwardAvailable;
- std::string mStatusText;
- int mProgressPercent;
- std::string mLocation;
- std::string mClickURL;
- std::string mClickNavType;
- std::string mClickTarget;
- std::string mClickUUID;
- bool mClickEnforceTarget;
- std::string mOverrideClickTarget;
- std::string mDebugMessageText;
- std::string mDebugMessageLevel;
- S32 mGeometryX;
- S32 mGeometryY;
- S32 mGeometryWidth;
- S32 mGeometryHeight;
- S32 mStatusCode;
- std::string mAuthURL;
- std::string mAuthRealm;
- std::string mHoverText;
- std::string mHoverLink;
- std::string mFileDownloadFilename;
- bool mIsMultipleFilePick;
-
- /////////////////////////////////////////
- // media_time class
- F64 mCurrentTime;
- F64 mDuration;
- F64 mCurrentRate;
- F64 mLoadedDuration;
-
+ LLPluginClassMediaOwner *mOwner;
+
+ // 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);
+
+ bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
+ S32 mRequestedTextureDepth;
+ LLGLenum mRequestedTextureInternalFormat;
+ LLGLenum mRequestedTextureFormat;
+ LLGLenum mRequestedTextureType;
+ bool mRequestedTextureSwapBytes;
+ bool mRequestedTextureCoordsOpenGL;
+
+ std::string mTextureSharedMemoryName;
+ size_t mTextureSharedMemorySize;
+
+ // True to scale requested media up to the full size of the texture (i.e. next power of two)
+ bool mAutoScaleMedia;
+
+ // default media size for the plugin, from the texture_params message.
+ int mDefaultMediaWidth;
+ int mDefaultMediaHeight;
+
+ // Size that has been requested by the plugin itself
+ int mNaturalMediaWidth;
+ int mNaturalMediaHeight;
+
+ // Size that has been requested with setSize()
+ int mSetMediaWidth;
+ int mSetMediaHeight;
+
+ // Full calculated media size (before auto-scale and downsample calculations)
+ int mFullMediaWidth;
+ int mFullMediaHeight;
+
+ // Actual media size being set (after auto-scale)
+ int mRequestedMediaWidth;
+ int mRequestedMediaHeight;
+
+ // Texture size calculated from actual media size
+ int mRequestedTextureWidth;
+ int mRequestedTextureHeight;
+
+ // Size that the plugin has acknowledged
+ int mTextureWidth;
+ int mTextureHeight;
+ int mMediaWidth;
+ int mMediaHeight;
+
+ F64 mZoomFactor;
+
+ float mRequestedVolume;
+
+ // Priority of this media stream
+ EPriority mPriority;
+ int mLowPrioritySizeLimit;
+
+ bool mAllowDownsample;
+ int mPadding;
+
+
+ LLPluginProcessParent::ptr_t mPlugin;
+
+ LLRect mDirtyRect;
+
+ std::string translateModifiers(MASK modifiers);
+
+ std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
+
+ LLPluginClassMediaOwner::EMediaStatus mStatus;
+
+ F64 mSleepTime;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+
+ std::string mMediaName;
+ std::string mMediaDescription;
+
+ LLColor4 mBackgroundColor;
+
+ std::string mTarget;
+
+ /////////////////////////////////////////
+ // media_browser class
+ std::string mNavigateURI;
+ S32 mNavigateResultCode;
+ std::string mNavigateResultString;
+ bool mHistoryBackAvailable;
+ bool mHistoryForwardAvailable;
+ std::string mStatusText;
+ int mProgressPercent;
+ std::string mLocation;
+ std::string mClickURL;
+ std::string mClickNavType;
+ std::string mClickTarget;
+ std::string mClickUUID;
+ bool mClickEnforceTarget;
+ std::string mOverrideClickTarget;
+ std::string mDebugMessageText;
+ std::string mDebugMessageLevel;
+ S32 mGeometryX;
+ S32 mGeometryY;
+ S32 mGeometryWidth;
+ S32 mGeometryHeight;
+ S32 mStatusCode;
+ std::string mAuthURL;
+ std::string mAuthRealm;
+ std::string mHoverText;
+ std::string mHoverLink;
+ std::string mFileDownloadFilename;
+ bool mIsMultipleFilePick;
+
+ /////////////////////////////////////////
+ // media_time class
+ F64 mCurrentTime;
+ F64 mDuration;
+ F64 mCurrentRate;
+ F64 mLoadedDuration;
+
//--------------------------------------
- //debug use only
- //
+ //debug use only
+ //
private:
- bool mDeleteOK ;
+ bool mDeleteOK ;
public:
- void setDeleteOK(bool flag) { mDeleteOK = flag ;}
+ void setDeleteOK(bool flag) { mDeleteOK = flag ;}
//--------------------------------------
};
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index 89f55eaf71..a75d0b9960 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -38,53 +38,53 @@ class LLPluginClassMedia;
class LLPluginClassMediaOwner
{
public:
- typedef enum
- {
- MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated
- MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated
- MEDIA_EVENT_SIZE_CHANGED, // media size has changed
- MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change
+ typedef enum
+ {
+ MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated
+ MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated
+ MEDIA_EVENT_SIZE_CHANGED, // media size has changed
+ MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change
- MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation
- MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation
- MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress
- MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text
- MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically <title> tag)
- MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc)
- MEDIA_EVENT_NAVIGATE_ERROR_PAGE, // browser navigated to a page that resulted in an HTTP error
- MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
- MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
- MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit)
- MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file
- MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface)
+ MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation
+ MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation
+ MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress
+ MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text
+ MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically <title> tag)
+ MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc)
+ MEDIA_EVENT_NAVIGATE_ERROR_PAGE, // browser navigated to a page that resulted in an HTTP error
+ MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
+ MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
+ MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit)
+ MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file
+ MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface)
- MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
- MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly
+ MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
+ MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly
- MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
+ MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
- MEDIA_EVENT_FILE_DOWNLOAD, // the plugin wants to download a file
+ MEDIA_EVENT_FILE_DOWNLOAD, // the plugin wants to download a file
- MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process
+ MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process
- MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin
+ MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin
- } EMediaEvent;
+ } EMediaEvent;
- typedef enum
- {
- MEDIA_NONE, // Uninitialized -- no useful state
- MEDIA_LOADING, // loading or navigating
- MEDIA_LOADED, // navigation/preroll complete
- MEDIA_ERROR, // navigation/preroll failed
- MEDIA_PLAYING, // playing (only for time-based media)
- MEDIA_PAUSED, // paused (only for time-based media)
- MEDIA_DONE // finished playing (only for time-based media)
+ typedef enum
+ {
+ MEDIA_NONE, // Uninitialized -- no useful state
+ MEDIA_LOADING, // loading or navigating
+ MEDIA_LOADED, // navigation/preroll complete
+ MEDIA_ERROR, // navigation/preroll failed
+ MEDIA_PLAYING, // playing (only for time-based media)
+ MEDIA_PAUSED, // paused (only for time-based media)
+ MEDIA_DONE // finished playing (only for time-based media)
- } EMediaStatus;
+ } EMediaStatus;
- virtual ~LLPluginClassMediaOwner() {};
- virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {};
+ virtual ~LLPluginClassMediaOwner() {};
+ virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {};
};
#endif // LL_LLPLUGINCLASSMEDIAOWNER_H
diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp
index 7cde82a20e..67c12820e8 100644
--- a/indra/llplugin/llplugininstance.cpp
+++ b/indra/llplugin/llplugininstance.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llplugininstance.cpp
* @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -33,7 +33,7 @@
#include "llapr.h"
#if LL_WINDOWS
-#include "direct.h" // needed for _chdir()
+#include "direct.h" // needed for _chdir()
#endif
/** Virtual destructor. */
@@ -41,37 +41,37 @@ LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
{
}
-/**
+/**
* TODO:DOC describe how it's used
*/
const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoint";
-/**
+/**
* Constructor.
*
* @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is?
*/
LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
- mDSOHandle(NULL),
- mPluginUserData(NULL),
- mPluginSendMessageFunction(NULL)
+ mDSOHandle(NULL),
+ mPluginUserData(NULL),
+ mPluginSendMessageFunction(NULL)
{
- mOwner = owner;
+ mOwner = owner;
}
-/**
+/**
* Destructor.
*/
LLPluginInstance::~LLPluginInstance()
{
- if(mDSOHandle != NULL)
- {
- apr_dso_unload(mDSOHandle);
- mDSOHandle = NULL;
- }
+ if(mDSOHandle != NULL)
+ {
+ apr_dso_unload(mDSOHandle);
+ mDSOHandle = NULL;
+ }
}
-/**
+/**
* Dynamically loads the plugin and runs the plugin's init function.
*
* @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h
@@ -79,75 +79,75 @@ LLPluginInstance::~LLPluginInstance()
*/
int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_file)
{
- pluginInitFunction init_function = NULL;
-
- if ( plugin_dir.length() )
- {
+ pluginInitFunction init_function = NULL;
+
+ if ( plugin_dir.length() )
+ {
#if LL_WINDOWS
- // VWR-21275:
- // *SOME* Windows systems fail to load the Qt plugins if the current working
- // directory is not the same as the directory with the Qt DLLs in.
- // This should not cause any run time issues since we are changing the cwd for the
- // plugin shell process and not the viewer.
- // Changing back to the previous directory is not necessary since the plugin shell
- // quits once the plugin exits.
- _chdir( plugin_dir.c_str() );
+ // VWR-21275:
+ // *SOME* Windows systems fail to load the Qt plugins if the current working
+ // directory is not the same as the directory with the Qt DLLs in.
+ // This should not cause any run time issues since we are changing the cwd for the
+ // plugin shell process and not the viewer.
+ // Changing back to the previous directory is not necessary since the plugin shell
+ // quits once the plugin exits.
+ _chdir( plugin_dir.c_str() );
#endif
- };
-
- int result = apr_dso_load(&mDSOHandle,
- plugin_file.c_str(),
- gAPRPoolp);
- if(result != APR_SUCCESS)
- {
- char buf[1024];
- apr_dso_error(mDSOHandle, buf, sizeof(buf));
-
- LL_WARNS("Plugin") << "apr_dso_load of " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL;
-
- }
-
- if(result == APR_SUCCESS)
- {
- result = apr_dso_sym((apr_dso_handle_sym_t*)&init_function,
- mDSOHandle,
- PLUGIN_INIT_FUNCTION_NAME);
-
- if(result != APR_SUCCESS)
- {
- LL_WARNS("Plugin") << "apr_dso_sym failed with error " << result << LL_ENDL;
- }
- }
-
- if(result == APR_SUCCESS)
- {
- result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData);
-
- if(result != APR_SUCCESS)
- {
- LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL;
- }
- }
-
- return (int)result;
+ };
+
+ int result = apr_dso_load(&mDSOHandle,
+ plugin_file.c_str(),
+ gAPRPoolp);
+ if(result != APR_SUCCESS)
+ {
+ char buf[1024];
+ apr_dso_error(mDSOHandle, buf, sizeof(buf));
+
+ LL_WARNS("Plugin") << "apr_dso_load of " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL;
+
+ }
+
+ if(result == APR_SUCCESS)
+ {
+ result = apr_dso_sym((apr_dso_handle_sym_t*)&init_function,
+ mDSOHandle,
+ PLUGIN_INIT_FUNCTION_NAME);
+
+ if(result != APR_SUCCESS)
+ {
+ LL_WARNS("Plugin") << "apr_dso_sym failed with error " << result << LL_ENDL;
+ }
+ }
+
+ if(result == APR_SUCCESS)
+ {
+ result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData);
+
+ if(result != APR_SUCCESS)
+ {
+ LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL;
+ }
+ }
+
+ return (int)result;
}
-/**
+/**
* Sends a message to the plugin.
*
* @param[in] message Message
*/
void LLPluginInstance::sendMessage(const std::string &message)
{
- if(mPluginSendMessageFunction)
- {
- LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL;
- mPluginSendMessageFunction(message.c_str(), &mPluginUserData);
- }
- else
- {
- LL_WARNS("Plugin") << "dropping message: \"" << message << "\"" << LL_ENDL;
- }
+ if(mPluginSendMessageFunction)
+ {
+ LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL;
+ mPluginSendMessageFunction(message.c_str(), &mPluginUserData);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping message: \"" << message << "\"" << LL_ENDL;
+ }
}
/**
@@ -161,10 +161,10 @@ void LLPluginInstance::idle(void)
// static
void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data)
{
- // TODO: validate that the user_data 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);
+ // TODO: validate that the user_data 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);
}
/**
@@ -174,13 +174,13 @@ void LLPluginInstance::staticReceiveMessage(const char *message_string, void **u
*/
void LLPluginInstance::receiveMessage(const char *message_string)
{
- if(mOwner)
- {
- LL_DEBUGS("Plugin") << "processing incoming message: \"" << message_string << "\"" << LL_ENDL;
- mOwner->receivePluginMessage(message_string);
- }
- else
- {
- LL_WARNS("Plugin") << "dropping incoming message: \"" << message_string << "\"" << LL_ENDL;
- }
+ if(mOwner)
+ {
+ LL_DEBUGS("Plugin") << "processing incoming message: \"" << message_string << "\"" << LL_ENDL;
+ mOwner->receivePluginMessage(message_string);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping incoming message: \"" << message_string << "\"" << LL_ENDL;
+ }
}
diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h
index e6926c3e37..4ab46b4290 100644
--- a/indra/llplugin/llplugininstance.h
+++ b/indra/llplugin/llplugininstance.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llplugininstance.h
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -39,9 +39,9 @@
class LLPluginInstanceMessageListener
{
public:
- virtual ~LLPluginInstanceMessageListener();
+ virtual ~LLPluginInstanceMessageListener();
/** Plugin receives message from plugin loader shell. */
- virtual void receivePluginMessage(const std::string &message) = 0;
+ virtual void receivePluginMessage(const std::string &message) = 0;
};
/**
@@ -49,51 +49,51 @@ public:
*/
class LLPluginInstance
{
- LOG_CLASS(LLPluginInstance);
+ LOG_CLASS(LLPluginInstance);
public:
- LLPluginInstance(LLPluginInstanceMessageListener *owner);
- virtual ~LLPluginInstance();
-
- // Load a plugin dll/dylib/so
- // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure.
- int load(const std::string& plugin_dir, std::string &plugin_file);
-
- // Sends a message to the plugin.
- void sendMessage(const std::string &message);
-
+ LLPluginInstance(LLPluginInstanceMessageListener *owner);
+ virtual ~LLPluginInstance();
+
+ // Load a plugin dll/dylib/so
+ // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure.
+ int load(const std::string& plugin_dir, std::string &plugin_file);
+
+ // Sends a message to the plugin.
+ void sendMessage(const std::string &message);
+
// TODO:DOC is this comment obsolete? can't find "send_count" anywhere in indra tree.
- // send_count is the maximum number of message to process from the send queue. If negative, it will drain the queue completely.
- // The receive queue is always drained completely.
- // Returns the total number of messages processed from both queues.
- void idle(void);
-
- /** The signature of the function for sending a message from plugin to plugin loader shell.
+ // send_count is the maximum number of message to process from the send queue. If negative, it will drain the queue completely.
+ // The receive queue is always drained completely.
+ // Returns the total number of messages processed from both queues.
+ void idle(void);
+
+ /** The signature of the function for sending a message from plugin to plugin loader shell.
*
- * @param[in] message_string Null-terminated C string
+ * @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 (*sendMessageFunction) (const char *message_string, void **user_data);
- /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?)
+ /** 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 host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data);
+
/** Name of plugin init function */
- static const char *PLUGIN_INIT_FUNCTION_NAME;
-
+ static const char *PLUGIN_INIT_FUNCTION_NAME;
+
private:
- static void staticReceiveMessage(const char *message_string, void **user_data);
- void receiveMessage(const char *message_string);
-
- apr_dso_handle_t *mDSOHandle;
-
- void *mPluginUserData;
- sendMessageFunction mPluginSendMessageFunction;
-
- LLPluginInstanceMessageListener *mOwner;
+ static void staticReceiveMessage(const char *message_string, void **user_data);
+ void receiveMessage(const char *message_string);
+
+ apr_dso_handle_t *mDSOHandle;
+
+ void *mPluginUserData;
+ sendMessageFunction mPluginSendMessageFunction;
+
+ LLPluginInstanceMessageListener *mOwner;
};
#endif // LL_LLPLUGININSTANCE_H
diff --git a/indra/llplugin/llpluginmessage.cpp b/indra/llplugin/llpluginmessage.cpp
index b39e951155..188d71227b 100644
--- a/indra/llplugin/llpluginmessage.cpp
+++ b/indra/llplugin/llpluginmessage.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginmessage.cpp
* @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -46,7 +46,7 @@ LLPluginMessage::LLPluginMessage()
*/
LLPluginMessage::LLPluginMessage(const LLPluginMessage &p)
{
- mMessage = p.mMessage;
+ mMessage = p.mMessage;
}
/**
@@ -57,7 +57,7 @@ LLPluginMessage::LLPluginMessage(const LLPluginMessage &p)
*/
LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name)
{
- setMessage(message_class, message_name);
+ setMessage(message_class, message_name);
}
@@ -73,8 +73,8 @@ LLPluginMessage::~LLPluginMessage()
*/
void LLPluginMessage::clear()
{
- mMessage = LLSD::emptyMap();
- mMessage["params"] = LLSD::emptyMap();
+ mMessage = LLSD::emptyMap();
+ mMessage["params"] = LLSD::emptyMap();
}
/**
@@ -85,9 +85,9 @@ void LLPluginMessage::clear()
*/
void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name)
{
- clear();
- mMessage["class"] = message_class;
- mMessage["name"] = message_name;
+ clear();
+ mMessage["class"] = message_class;
+ mMessage["name"] = message_name;
}
/**
@@ -98,7 +98,7 @@ void LLPluginMessage::setMessage(const std::string &message_class, const std::st
*/
void LLPluginMessage::setValue(const std::string &key, const std::string &value)
{
- mMessage["params"][key] = value;
+ mMessage["params"][key] = value;
}
/**
@@ -109,7 +109,7 @@ void LLPluginMessage::setValue(const std::string &key, const std::string &value)
*/
void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value)
{
- mMessage["params"][key] = value;
+ mMessage["params"][key] = value;
}
/**
@@ -120,7 +120,7 @@ void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value)
*/
void LLPluginMessage::setValueS32(const std::string &key, S32 value)
{
- mMessage["params"][key] = value;
+ mMessage["params"][key] = value;
}
/**
@@ -131,9 +131,9 @@ void LLPluginMessage::setValueS32(const std::string &key, S32 value)
*/
void LLPluginMessage::setValueU32(const std::string &key, U32 value)
{
- std::stringstream temp;
- temp << "0x" << std::hex << value;
- setValue(key, temp.str());
+ std::stringstream temp;
+ temp << "0x" << std::hex << value;
+ setValue(key, temp.str());
}
/**
@@ -144,7 +144,7 @@ void LLPluginMessage::setValueU32(const std::string &key, U32 value)
*/
void LLPluginMessage::setValueBoolean(const std::string &key, bool value)
{
- mMessage["params"][key] = value;
+ mMessage["params"][key] = value;
}
/**
@@ -155,7 +155,7 @@ void LLPluginMessage::setValueBoolean(const std::string &key, bool value)
*/
void LLPluginMessage::setValueReal(const std::string &key, F64 value)
{
- mMessage["params"][key] = value;
+ mMessage["params"][key] = value;
}
/**
@@ -166,10 +166,10 @@ void LLPluginMessage::setValueReal(const std::string &key, F64 value)
*/
void LLPluginMessage::setValuePointer(const std::string &key, void* value)
{
- std::stringstream temp;
- // iostreams should output pointer values in hex with an initial 0x by default.
- temp << value;
- setValue(key, temp.str());
+ std::stringstream temp;
+ // iostreams should output pointer values in hex with an initial 0x by default.
+ temp << value;
+ setValue(key, temp.str());
}
/**
@@ -179,7 +179,7 @@ void LLPluginMessage::setValuePointer(const std::string &key, void* value)
*/
std::string LLPluginMessage::getClass(void) const
{
- return mMessage["class"];
+ return mMessage["class"];
}
/**
@@ -189,11 +189,11 @@ std::string LLPluginMessage::getClass(void) const
*/
std::string LLPluginMessage::getName(void) const
{
- return mMessage["name"];
+ return mMessage["name"];
}
/**
- * Returns true if the specified key exists in this message (useful for optional parameters).
+ * Returns true if the specified key exists in this message (useful for optional parameters).
*
* @param[in] key Key
*
@@ -201,18 +201,18 @@ std::string LLPluginMessage::getName(void) const
*/
bool LLPluginMessage::hasValue(const std::string &key) const
{
- bool result = false;
-
- if(mMessage["params"].has(key))
- {
- result = true;
- }
-
- return result;
+ bool result = false;
+
+ if(mMessage["params"].has(key))
+ {
+ result = true;
+ }
+
+ return result;
}
/**
- * Gets the value of a key as a string. If the key does not exist, an empty string will be returned.
+ * Gets the value of a key as a string. If the key does not exist, an empty string will be returned.
*
* @param[in] key Key
*
@@ -220,18 +220,18 @@ bool LLPluginMessage::hasValue(const std::string &key) const
*/
std::string LLPluginMessage::getValue(const std::string &key) const
{
- std::string result;
-
- if(mMessage["params"].has(key))
- {
- result = mMessage["params"][key].asString();
- }
-
- return result;
+ std::string result;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asString();
+ }
+
+ return result;
}
/**
- * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned.
+ * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned.
*
* @param[in] key Key
*
@@ -239,18 +239,18 @@ std::string LLPluginMessage::getValue(const std::string &key) const
*/
LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
{
- LLSD result;
-
- if(mMessage["params"].has(key))
- {
- result = mMessage["params"][key];
- }
-
- return result;
+ LLSD result;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key];
+ }
+
+ return result;
}
/**
- * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned.
+ * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned.
*
* @param[in] key Key
*
@@ -258,18 +258,18 @@ LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
*/
S32 LLPluginMessage::getValueS32(const std::string &key) const
{
- S32 result = 0;
-
- if(mMessage["params"].has(key))
- {
- result = mMessage["params"][key].asInteger();
- }
-
- return result;
+ S32 result = 0;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asInteger();
+ }
+
+ return result;
}
/**
- * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned.
+ * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned.
*
* @param[in] key Key
*
@@ -277,20 +277,20 @@ S32 LLPluginMessage::getValueS32(const std::string &key) const
*/
U32 LLPluginMessage::getValueU32(const std::string &key) const
{
- U32 result = 0;
-
- if(mMessage["params"].has(key))
- {
- std::string value = mMessage["params"][key].asString();
-
- result = (U32)strtoul(value.c_str(), NULL, 16);
- }
-
- return result;
+ U32 result = 0;
+
+ if(mMessage["params"].has(key))
+ {
+ std::string value = mMessage["params"][key].asString();
+
+ result = (U32)strtoul(value.c_str(), NULL, 16);
+ }
+
+ return result;
}
/**
- * Gets the value of a key as a bool. If the key does not exist, false will be returned.
+ * Gets the value of a key as a bool. If the key does not exist, false will be returned.
*
* @param[in] key Key
*
@@ -298,18 +298,18 @@ U32 LLPluginMessage::getValueU32(const std::string &key) const
*/
bool LLPluginMessage::getValueBoolean(const std::string &key) const
{
- bool result = false;
-
- if(mMessage["params"].has(key))
- {
- result = mMessage["params"][key].asBoolean();
- }
-
- return result;
+ bool result = false;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asBoolean();
+ }
+
+ return result;
}
/**
- * Gets the value of a key as a double. If the key does not exist, 0 will be returned.
+ * Gets the value of a key as a double. If the key does not exist, 0 will be returned.
*
* @param[in] key Key
*
@@ -317,18 +317,18 @@ bool LLPluginMessage::getValueBoolean(const std::string &key) const
*/
F64 LLPluginMessage::getValueReal(const std::string &key) const
{
- F64 result = 0.0f;
-
- if(mMessage["params"].has(key))
- {
- result = mMessage["params"][key].asReal();
- }
-
- return result;
+ F64 result = 0.0f;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asReal();
+ }
+
+ return result;
}
/**
- * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned.
+ * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned.
*
* @param[in] key Key
*
@@ -336,49 +336,49 @@ F64 LLPluginMessage::getValueReal(const std::string &key) const
*/
void* LLPluginMessage::getValuePointer(const std::string &key) const
{
- void* result = NULL;
-
- if(mMessage["params"].has(key))
- {
- std::string value = mMessage["params"][key].asString();
-
- result = (void*)llstrtou64(value.c_str(), NULL, 16);
- }
-
- return result;
+ void* result = NULL;
+
+ if(mMessage["params"].has(key))
+ {
+ std::string value = mMessage["params"][key].asString();
+
+ result = (void*)llstrtou64(value.c_str(), NULL, 16);
+ }
+
+ return result;
}
/**
- * Flatten the message into a string.
+ * Flatten the message into a string.
*
* @return Message as a string.
*/
std::string LLPluginMessage::generate(void) const
{
- std::ostringstream result;
-
- // Pretty XML may be slightly easier to deal with while debugging...
-// LLSDSerialize::toXML(mMessage, result);
- LLSDSerialize::toPrettyXML(mMessage, result);
-
- return result.str();
+ std::ostringstream result;
+
+ // Pretty XML may be slightly easier to deal with while debugging...
+// LLSDSerialize::toXML(mMessage, result);
+ LLSDSerialize::toPrettyXML(mMessage, result);
+
+ return result.str();
}
/**
- * Parse an incoming message into component parts. Clears all existing state before starting the parse.
+ * Parse an incoming message into component parts. Clears all existing state before starting the parse.
*
* @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message.
*/
int LLPluginMessage::parse(const std::string &message)
{
- // clear any previous state
- clear();
-
- std::istringstream input(message);
-
- S32 parse_result = LLSDSerialize::fromXML(mMessage, input);
-
- return (int)parse_result;
+ // clear any previous state
+ clear();
+
+ std::istringstream input(message);
+
+ S32 parse_result = LLSDSerialize::fromXML(mMessage, input);
+
+ return (int)parse_result;
}
@@ -387,7 +387,7 @@ int LLPluginMessage::parse(const std::string &message)
*/
LLPluginMessageListener::~LLPluginMessageListener()
{
- // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted?
+ // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted?
}
@@ -396,9 +396,9 @@ LLPluginMessageListener::~LLPluginMessageListener()
*/
LLPluginMessageDispatcher::~LLPluginMessageDispatcher()
{
-
+
}
-
+
/**
* Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed?
*
@@ -406,7 +406,7 @@ LLPluginMessageDispatcher::~LLPluginMessageDispatcher()
*/
void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener)
{
- mListeners.insert(listener);
+ mListeners.insert(listener);
}
/**
@@ -416,7 +416,7 @@ void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener
*/
void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener)
{
- mListeners.erase(listener);
+ mListeners.erase(listener);
}
/**
@@ -426,13 +426,13 @@ void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListe
*/
void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message)
{
- for (listener_set_t::iterator it = mListeners.begin();
- it != mListeners.end();
- )
- {
- LLPluginMessageListener* listener = *it;
- listener->receivePluginMessage(message);
- // In case something deleted an entry.
- it = mListeners.upper_bound(listener);
- }
+ for (listener_set_t::iterator it = mListeners.begin();
+ it != mListeners.end();
+ )
+ {
+ LLPluginMessageListener* listener = *it;
+ listener->receivePluginMessage(message);
+ // In case something deleted an entry.
+ it = mListeners.upper_bound(listener);
+ }
}
diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h
index f86b68d16e..93756cd0dc 100644
--- a/indra/llplugin/llpluginmessage.h
+++ b/indra/llplugin/llpluginmessage.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpluginmessage.h
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -35,68 +35,68 @@
*/
class LLPluginMessage
{
- LOG_CLASS(LLPluginMessage);
+ LOG_CLASS(LLPluginMessage);
public:
- LLPluginMessage();
- LLPluginMessage(const LLPluginMessage &p);
- LLPluginMessage(const std::string &message_class, const std::string &message_name);
- ~LLPluginMessage();
-
- // reset all internal state
- void clear(void);
-
- // Sets the message class and name
- // Also has the side-effect of clearing any key/value pairs in the message.
- void setMessage(const std::string &message_class, const std::string &message_name);
-
- // Sets a key/value pair in the message
- void setValue(const std::string &key, const std::string &value);
- void setValueLLSD(const std::string &key, const LLSD &value);
- void setValueS32(const std::string &key, S32 value);
- void setValueU32(const std::string &key, U32 value);
- void setValueBoolean(const std::string &key, bool value);
- void setValueReal(const std::string &key, F64 value);
- void setValuePointer(const std::string &key, void *value);
-
- std::string getClass(void) const;
- std::string getName(void) const;
-
- // Returns true if the specified key exists in this message (useful for optional parameters)
- bool hasValue(const std::string &key) const;
-
- // get the value of a particular key as a string. If the key doesn't exist in the message, an empty string will be returned.
- std::string getValue(const std::string &key) const;
-
- // get the value of a particular key as LLSD. If the key doesn't exist in the message, a null LLSD will be returned.
- LLSD getValueLLSD(const std::string &key) const;
-
- // get the value of a key as a S32. If the value wasn't set as a S32, behavior is undefined.
- S32 getValueS32(const std::string &key) const;
-
- // get the value of a key as a U32. Since there isn't an LLSD type for this, we use a hexadecimal string instead.
- U32 getValueU32(const std::string &key) const;
-
- // get the value of a key as a Boolean.
- bool getValueBoolean(const std::string &key) const;
-
- // get the value of a key as a float.
- F64 getValueReal(const std::string &key) const;
-
- // get the value of a key as a pointer.
- void* getValuePointer(const std::string &key) const;
-
- // Flatten the message into a string
- std::string generate(void) const;
-
- // Parse an incoming message into component parts
- // (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);
-
-
+ LLPluginMessage();
+ LLPluginMessage(const LLPluginMessage &p);
+ LLPluginMessage(const std::string &message_class, const std::string &message_name);
+ ~LLPluginMessage();
+
+ // reset all internal state
+ void clear(void);
+
+ // Sets the message class and name
+ // Also has the side-effect of clearing any key/value pairs in the message.
+ void setMessage(const std::string &message_class, const std::string &message_name);
+
+ // Sets a key/value pair in the message
+ void setValue(const std::string &key, const std::string &value);
+ void setValueLLSD(const std::string &key, const LLSD &value);
+ void setValueS32(const std::string &key, S32 value);
+ void setValueU32(const std::string &key, U32 value);
+ void setValueBoolean(const std::string &key, bool value);
+ void setValueReal(const std::string &key, F64 value);
+ void setValuePointer(const std::string &key, void *value);
+
+ std::string getClass(void) const;
+ std::string getName(void) const;
+
+ // Returns true if the specified key exists in this message (useful for optional parameters)
+ bool hasValue(const std::string &key) const;
+
+ // get the value of a particular key as a string. If the key doesn't exist in the message, an empty string will be returned.
+ std::string getValue(const std::string &key) const;
+
+ // get the value of a particular key as LLSD. If the key doesn't exist in the message, a null LLSD will be returned.
+ LLSD getValueLLSD(const std::string &key) const;
+
+ // get the value of a key as a S32. If the value wasn't set as a S32, behavior is undefined.
+ S32 getValueS32(const std::string &key) const;
+
+ // get the value of a key as a U32. Since there isn't an LLSD type for this, we use a hexadecimal string instead.
+ U32 getValueU32(const std::string &key) const;
+
+ // get the value of a key as a Boolean.
+ bool getValueBoolean(const std::string &key) const;
+
+ // get the value of a key as a float.
+ F64 getValueReal(const std::string &key) const;
+
+ // get the value of a key as a pointer.
+ void* getValuePointer(const std::string &key) const;
+
+ // Flatten the message into a string
+ std::string generate(void) const;
+
+ // Parse an incoming message into component parts
+ // (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);
+
+
private:
-
- LLSD mMessage;
+
+ LLSD mMessage;
};
@@ -106,10 +106,10 @@ private:
class LLPluginMessageListener
{
public:
- virtual ~LLPluginMessageListener();
+ virtual ~LLPluginMessageListener();
/** Plugin receives message from plugin loader shell. */
- virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
-
+ virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
+
};
/**
@@ -120,17 +120,17 @@ public:
class LLPluginMessageDispatcher
{
public:
- virtual ~LLPluginMessageDispatcher();
-
- void addPluginMessageListener(LLPluginMessageListener *);
- void removePluginMessageListener(LLPluginMessageListener *);
+ virtual ~LLPluginMessageDispatcher();
+
+ void addPluginMessageListener(LLPluginMessageListener *);
+ void removePluginMessageListener(LLPluginMessageListener *);
protected:
- void dispatchPluginMessage(const LLPluginMessage &message);
+ void dispatchPluginMessage(const LLPluginMessage &message);
/** A set of message listeners. */
- typedef std::set<LLPluginMessageListener*> listener_set_t;
+ typedef std::set<LLPluginMessageListener*> listener_set_t;
/** The set of message listeners. */
- listener_set_t mListeners;
+ listener_set_t mListeners;
};
diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h
index 65fc8cb5ff..465e2d7530 100644
--- a/indra/llplugin/llpluginmessageclasses.h
+++ b/indra/llplugin/llpluginmessageclasses.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginmessageclasses.h
* @brief This file defines the versions of existing message classes for LLPluginMessage.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -29,7 +29,7 @@
#ifndef LL_LLPLUGINMESSAGECLASSES_H
#define LL_LLPLUGINMESSAGECLASSES_H
-// Version strings for each plugin message class.
+// Version strings for each plugin message class.
// Backwards-compatible changes (i.e. changes which only add new messges) should increment the minor version (i.e. "1.0" -> "1.1").
// Non-backwards-compatible changes (which delete messages or change their semantics) should increment the major version (i.e. "1.1" -> "2.0").
// Plugins will supply the set of message classes they understand, with version numbers, as part of their init_response message.
diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp
index 9766e1bfed..2cbc16ceec 100644
--- a/indra/llplugin/llpluginmessagepipe.cpp
+++ b/indra/llplugin/llpluginmessagepipe.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginmessagepipe.cpp
* @brief Classes that implement connections from the plugin system to pipes/pumps.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -36,362 +36,362 @@
static const char MESSAGE_DELIMITER = '\0';
LLPluginMessagePipeOwner::LLPluginMessagePipeOwner() :
- mMessagePipe(NULL),
- mSocketError(APR_SUCCESS)
+ mMessagePipe(NULL),
+ mSocketError(APR_SUCCESS)
{
}
-// virtual
+// virtual
LLPluginMessagePipeOwner::~LLPluginMessagePipeOwner()
{
- killMessagePipe();
+ killMessagePipe();
}
-// virtual
+// virtual
apr_status_t LLPluginMessagePipeOwner::socketError(apr_status_t error)
-{
- mSocketError = error;
- return error;
+{
+ mSocketError = error;
+ return error;
};
-//virtual
+//virtual
void LLPluginMessagePipeOwner::setMessagePipe(LLPluginMessagePipe *read_pipe)
{
- // Save a reference to this pipe
- mMessagePipe = read_pipe;
+ // Save a reference to this pipe
+ mMessagePipe = read_pipe;
}
bool LLPluginMessagePipeOwner::canSendMessage(void)
{
- return (mMessagePipe != NULL);
+ return (mMessagePipe != NULL);
}
bool LLPluginMessagePipeOwner::writeMessageRaw(const std::string &message)
{
- bool result = true;
- if(mMessagePipe != NULL)
- {
- result = mMessagePipe->addMessage(message);
- }
- else
- {
- LL_WARNS("Plugin") << "dropping message: " << message << LL_ENDL;
- result = false;
- }
-
- return result;
+ bool result = true;
+ if(mMessagePipe != NULL)
+ {
+ result = mMessagePipe->addMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping message: " << message << LL_ENDL;
+ result = false;
+ }
+
+ return result;
}
void LLPluginMessagePipeOwner::killMessagePipe(void)
{
- if(mMessagePipe != NULL)
- {
- delete mMessagePipe;
- mMessagePipe = NULL;
- }
+ if(mMessagePipe != NULL)
+ {
+ delete mMessagePipe;
+ mMessagePipe = NULL;
+ }
}
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
- mInputMutex(),
- mOutputMutex(),
- mOutputStartIndex(0),
- mOwner(owner),
- mSocket(socket)
+ mInputMutex(),
+ mOutputMutex(),
+ mOutputStartIndex(0),
+ mOwner(owner),
+ mSocket(socket)
{
- mOwner->setMessagePipe(this);
+ mOwner->setMessagePipe(this);
}
LLPluginMessagePipe::~LLPluginMessagePipe()
{
- if(mOwner != NULL)
- {
- mOwner->setMessagePipe(NULL);
- }
+ if(mOwner != NULL)
+ {
+ mOwner->setMessagePipe(NULL);
+ }
}
bool LLPluginMessagePipe::addMessage(const std::string &message)
{
- // queue the message for later output
- LLMutexLock lock(&mOutputMutex);
-
- // If we're starting to use up too much memory, clear
- if (mOutputStartIndex > 1024 * 1024)
- {
- mOutput = mOutput.substr(mOutputStartIndex);
- mOutputStartIndex = 0;
- }
-
- mOutput += message;
- mOutput += MESSAGE_DELIMITER; // message separator
-
- return true;
+ // queue the message for later output
+ LLMutexLock lock(&mOutputMutex);
+
+ // If we're starting to use up too much memory, clear
+ if (mOutputStartIndex > 1024 * 1024)
+ {
+ mOutput = mOutput.substr(mOutputStartIndex);
+ mOutputStartIndex = 0;
+ }
+
+ mOutput += message;
+ mOutput += MESSAGE_DELIMITER; // message separator
+
+ return true;
}
void LLPluginMessagePipe::clearOwner(void)
{
- // The owner is done with this pipe. The next call to process_impl should send any remaining data and exit.
- mOwner = NULL;
+ // The owner is done with this pipe. The next call to process_impl should send any remaining data and exit.
+ mOwner = NULL;
}
void LLPluginMessagePipe::setSocketTimeout(apr_interval_time_t timeout_usec)
{
- // We never want to sleep forever, so force negative timeouts to become non-blocking.
-
- // according to this page: http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html
- // blocking/non-blocking with apr sockets is somewhat non-portable.
-
- if(timeout_usec <= 0)
- {
- // Make the socket non-blocking
- apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
- apr_socket_timeout_set(mSocket->getSocket(), 0);
- }
- else
- {
- // Make the socket blocking-with-timeout
- apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
- apr_socket_timeout_set(mSocket->getSocket(), timeout_usec);
- }
+ // We never want to sleep forever, so force negative timeouts to become non-blocking.
+
+ // according to this page: http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html
+ // blocking/non-blocking with apr sockets is somewhat non-portable.
+
+ if(timeout_usec <= 0)
+ {
+ // Make the socket non-blocking
+ apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(mSocket->getSocket(), 0);
+ }
+ else
+ {
+ // Make the socket blocking-with-timeout
+ apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(mSocket->getSocket(), timeout_usec);
+ }
}
bool LLPluginMessagePipe::pump(F64 timeout)
{
- bool result = pumpOutput();
-
- if(result)
- {
- result = pumpInput(timeout);
- }
-
- return result;
+ bool result = pumpOutput();
+
+ if(result)
+ {
+ result = pumpInput(timeout);
+ }
+
+ return result;
}
bool LLPluginMessagePipe::pumpOutput()
{
- bool result = true;
-
- if(mSocket)
- {
- apr_status_t status;
- apr_size_t in_size, out_size;
-
- LLMutexLock lock(&mOutputMutex);
-
- const char * output_data = &(mOutput.data()[mOutputStartIndex]);
- if(*output_data != '\0')
- {
- // write any outgoing messages
- in_size = (apr_size_t) (mOutput.size() - mOutputStartIndex);
- out_size = in_size;
-
- setSocketTimeout(0);
-
-// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;
-
- status = apr_socket_send(mSocket->getSocket(),
- output_data,
- &out_size);
-
-// LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
-
- if((status == APR_SUCCESS) || APR_STATUS_IS_EAGAIN(status))
- {
- // Success or Socket buffer is full...
-
- // If we've pumped the entire string, clear it
- if (out_size == in_size)
- {
- mOutputStartIndex = 0;
- mOutput.clear();
- }
- else
- {
- llassert(in_size > out_size);
-
- // Remove the written part from the buffer and try again later.
- mOutputStartIndex += out_size;
- }
- }
- else if(APR_STATUS_IS_EOF(status))
- {
- // This is what we normally expect when a plugin exits.
- //LL_INFOS() << "Got EOF from plugin socket. " << LL_ENDL;
-
- if(mOwner)
- {
- mOwner->socketError(status);
- }
- result = false;
- }
- else
- {
- // some other error
- // Treat this as fatal.
- ll_apr_warn_status(status);
-
- if(mOwner)
- {
- mOwner->socketError(status);
- }
- result = false;
- }
- }
- }
-
- return result;
+ bool result = true;
+
+ if(mSocket)
+ {
+ apr_status_t status;
+ apr_size_t in_size, out_size;
+
+ LLMutexLock lock(&mOutputMutex);
+
+ const char * output_data = &(mOutput.data()[mOutputStartIndex]);
+ if(*output_data != '\0')
+ {
+ // write any outgoing messages
+ in_size = (apr_size_t) (mOutput.size() - mOutputStartIndex);
+ out_size = in_size;
+
+ setSocketTimeout(0);
+
+// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;
+
+ status = apr_socket_send(mSocket->getSocket(),
+ output_data,
+ &out_size);
+
+// LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
+
+ if((status == APR_SUCCESS) || APR_STATUS_IS_EAGAIN(status))
+ {
+ // Success or Socket buffer is full...
+
+ // If we've pumped the entire string, clear it
+ if (out_size == in_size)
+ {
+ mOutputStartIndex = 0;
+ mOutput.clear();
+ }
+ else
+ {
+ llassert(in_size > out_size);
+
+ // Remove the written part from the buffer and try again later.
+ mOutputStartIndex += out_size;
+ }
+ }
+ else if(APR_STATUS_IS_EOF(status))
+ {
+ // This is what we normally expect when a plugin exits.
+ //LL_INFOS() << "Got EOF from plugin socket. " << LL_ENDL;
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ }
+ else
+ {
+ // some other error
+ // Treat this as fatal.
+ ll_apr_warn_status(status);
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ }
+ }
+ }
+
+ return result;
}
bool LLPluginMessagePipe::pumpInput(F64 timeout)
{
- bool result = true;
+ bool result = true;
- if(mSocket)
- {
- apr_status_t status;
- apr_size_t size;
+ if(mSocket)
+ {
+ apr_status_t status;
+ apr_size_t size;
- // FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
- // Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
+ // FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
+ // Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
#if LL_WINDOWS
- if(result)
- {
- if(timeout != 0.0f)
- {
- ms_sleep((int)(timeout * 1000.0f));
- timeout = 0.0f;
- }
- }
+ if(result)
+ {
+ if(timeout != 0.0f)
+ {
+ ms_sleep((int)(timeout * 1000.0f));
+ timeout = 0.0f;
+ }
+ }
#endif
-
- // Check for incoming messages
- if(result)
- {
- char input_buf[1024];
- apr_size_t request_size;
-
- if(timeout == 0.0f)
- {
- // If we have no timeout, start out with a full read.
- request_size = sizeof(input_buf);
- }
- else
- {
- // Start out by reading one byte, so that any data received will wake us up.
- request_size = 1;
- }
-
- // and use the timeout so we'll sleep if no data is available.
- setSocketTimeout((apr_interval_time_t)(timeout * 1000000));
-
- while(1)
- {
- size = request_size;
-
-// LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;
-
- status = apr_socket_recv(
- mSocket->getSocket(),
- input_buf,
- &size);
-
-// LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
-
- if(size > 0)
- {
- LLMutexLock lock(&mInputMutex);
- mInput.append(input_buf, size);
- }
-
- if(status == APR_SUCCESS)
- {
- LL_DEBUGS("PluginSocket") << "success, read " << size << LL_ENDL;
-
- if(size != request_size)
- {
- // This was a short read, so we're done.
- break;
- }
- }
- else if(APR_STATUS_IS_TIMEUP(status))
- {
- LL_DEBUGS("PluginSocket") << "TIMEUP, read " << size << LL_ENDL;
-
- // Timeout was hit. Since the initial read is 1 byte, this should never be a partial read.
- break;
- }
- else if(APR_STATUS_IS_EAGAIN(status))
- {
- LL_DEBUGS("PluginSocket") << "EAGAIN, read " << size << LL_ENDL;
-
- // Non-blocking read returned immediately.
- break;
- }
- else if(APR_STATUS_IS_EOF(status))
- {
- // This is what we normally expect when a plugin exits.
- //LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL;
-
- if(mOwner)
- {
- mOwner->socketError(status);
- }
- result = false;
- break;
- }
- else
- {
- // some other error
- // Treat this as fatal.
- ll_apr_warn_status(status);
-
- if(mOwner)
- {
- mOwner->socketError(status);
- }
- result = false;
- break;
- }
-
- if(timeout != 0.0f)
- {
- // Second and subsequent reads should not use the timeout
- setSocketTimeout(0);
- // and should try to fill the input buffer
- request_size = sizeof(input_buf);
- }
- }
-
- processInput();
- }
- }
-
- return result;
+
+ // Check for incoming messages
+ if(result)
+ {
+ char input_buf[1024];
+ apr_size_t request_size;
+
+ if(timeout == 0.0f)
+ {
+ // If we have no timeout, start out with a full read.
+ request_size = sizeof(input_buf);
+ }
+ else
+ {
+ // Start out by reading one byte, so that any data received will wake us up.
+ request_size = 1;
+ }
+
+ // and use the timeout so we'll sleep if no data is available.
+ setSocketTimeout((apr_interval_time_t)(timeout * 1000000));
+
+ while(1)
+ {
+ size = request_size;
+
+// LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;
+
+ status = apr_socket_recv(
+ mSocket->getSocket(),
+ input_buf,
+ &size);
+
+// LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
+
+ if(size > 0)
+ {
+ LLMutexLock lock(&mInputMutex);
+ mInput.append(input_buf, size);
+ }
+
+ if(status == APR_SUCCESS)
+ {
+ LL_DEBUGS("PluginSocket") << "success, read " << size << LL_ENDL;
+
+ if(size != request_size)
+ {
+ // This was a short read, so we're done.
+ break;
+ }
+ }
+ else if(APR_STATUS_IS_TIMEUP(status))
+ {
+ LL_DEBUGS("PluginSocket") << "TIMEUP, read " << size << LL_ENDL;
+
+ // Timeout was hit. Since the initial read is 1 byte, this should never be a partial read.
+ break;
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+ LL_DEBUGS("PluginSocket") << "EAGAIN, read " << size << LL_ENDL;
+
+ // Non-blocking read returned immediately.
+ break;
+ }
+ else if(APR_STATUS_IS_EOF(status))
+ {
+ // This is what we normally expect when a plugin exits.
+ //LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL;
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ break;
+ }
+ else
+ {
+ // some other error
+ // Treat this as fatal.
+ ll_apr_warn_status(status);
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ break;
+ }
+
+ if(timeout != 0.0f)
+ {
+ // Second and subsequent reads should not use the timeout
+ setSocketTimeout(0);
+ // and should try to fill the input buffer
+ request_size = sizeof(input_buf);
+ }
+ }
+
+ processInput();
+ }
+ }
+
+ return result;
}
void LLPluginMessagePipe::processInput(void)
{
- // Look for input delimiter(s) in the input buffer.
- int delim;
- mInputMutex.lock();
- while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos)
- {
- // Let the owner process this message
- if (mOwner)
- {
- // Pull the message out of the input buffer before calling receiveMessageRaw.
- // It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request)
- // and this guarantees that the messages will get dequeued correctly.
- std::string message(mInput, 0, delim);
- mInput.erase(0, delim + 1);
- mInputMutex.unlock();
- mOwner->receiveMessageRaw(message);
- mInputMutex.lock();
- }
- else
- {
- LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
- }
- }
- mInputMutex.unlock();
+ // Look for input delimiter(s) in the input buffer.
+ int delim;
+ mInputMutex.lock();
+ while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos)
+ {
+ // Let the owner process this message
+ if (mOwner)
+ {
+ // Pull the message out of the input buffer before calling receiveMessageRaw.
+ // It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request)
+ // and this guarantees that the messages will get dequeued correctly.
+ std::string message(mInput, 0, delim);
+ mInput.erase(0, delim + 1);
+ mInputMutex.unlock();
+ mOwner->receiveMessageRaw(message);
+ mInputMutex.lock();
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
+ }
+ }
+ mInputMutex.unlock();
}
diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h
index 9d5835eb82..20b1ee06a8 100644
--- a/indra/llplugin/llpluginmessagepipe.h
+++ b/indra/llplugin/llpluginmessagepipe.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginmessagepipe.h
* @brief Classes that implement connections from the plugin system to pipes/pumps.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -38,59 +38,59 @@ class LLPluginMessagePipe;
// Inherit from this to be able to receive messages from the LLPluginMessagePipe
class LLPluginMessagePipeOwner
{
- LOG_CLASS(LLPluginMessagePipeOwner);
+ LOG_CLASS(LLPluginMessagePipeOwner);
public:
- LLPluginMessagePipeOwner();
- virtual ~LLPluginMessagePipeOwner();
+ LLPluginMessagePipeOwner();
+ virtual ~LLPluginMessagePipeOwner();
- // called with incoming messages
- virtual void receiveMessageRaw(const std::string &message) = 0;
- // called when the socket has an error
- virtual apr_status_t socketError(apr_status_t error);
+ // called with incoming messages
+ virtual void receiveMessageRaw(const std::string &message) = 0;
+ // called when the socket has an error
+ virtual apr_status_t socketError(apr_status_t error);
- // called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use!
- virtual void setMessagePipe(LLPluginMessagePipe *message_pipe);
+ // called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use!
+ virtual void setMessagePipe(LLPluginMessagePipe *message_pipe);
protected:
- // returns false if writeMessageRaw() would drop the message
- bool canSendMessage(void);
- // call this to send a message over the pipe
- bool writeMessageRaw(const std::string &message);
- // call this to close the pipe
- void killMessagePipe(void);
-
- LLPluginMessagePipe *mMessagePipe;
- apr_status_t mSocketError;
+ // returns false if writeMessageRaw() would drop the message
+ bool canSendMessage(void);
+ // call this to send a message over the pipe
+ bool writeMessageRaw(const std::string &message);
+ // call this to close the pipe
+ void killMessagePipe(void);
+
+ LLPluginMessagePipe *mMessagePipe;
+ apr_status_t mSocketError;
};
class LLPluginMessagePipe
{
- LOG_CLASS(LLPluginMessagePipe);
+ LOG_CLASS(LLPluginMessagePipe);
public:
- LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket);
- virtual ~LLPluginMessagePipe();
-
- bool addMessage(const std::string &message);
- void clearOwner(void);
-
- bool pump(F64 timeout = 0.0f);
- bool pumpOutput();
- bool pumpInput(F64 timeout = 0.0f);
-
-protected:
- void processInput(void);
-
- // used internally by pump()
- void setSocketTimeout(apr_interval_time_t timeout_usec);
-
- LLMutex mInputMutex;
- std::string mInput;
- LLMutex mOutputMutex;
- std::string mOutput;
- std::string::size_type mOutputStartIndex;
-
- LLPluginMessagePipeOwner *mOwner;
- LLSocket::ptr_t mSocket;
+ LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket);
+ virtual ~LLPluginMessagePipe();
+
+ bool addMessage(const std::string &message);
+ void clearOwner(void);
+
+ bool pump(F64 timeout = 0.0f);
+ bool pumpOutput();
+ bool pumpInput(F64 timeout = 0.0f);
+
+protected:
+ void processInput(void);
+
+ // used internally by pump()
+ void setSocketTimeout(apr_interval_time_t timeout_usec);
+
+ LLMutex mInputMutex;
+ std::string mInput;
+ LLMutex mOutputMutex;
+ std::string mOutput;
+ std::string::size_type mOutputStartIndex;
+
+ LLPluginMessagePipeOwner *mOwner;
+ LLSocket::ptr_t mSocket;
};
#endif // LL_LLPLUGINMESSAGE_H
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index d93ec8cf4b..a854ced7aa 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -39,192 +39,192 @@ static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will
LLPluginProcessChild::LLPluginProcessChild()
{
- mState = STATE_UNINITIALIZED;
- mInstance = NULL;
- mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
- mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
- mCPUElapsed = 0.0f;
- mBlockingRequest = false;
- mBlockingResponseReceived = false;
+ mState = STATE_UNINITIALIZED;
+ mInstance = NULL;
+ mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
+ mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
+ mCPUElapsed = 0.0f;
+ mBlockingRequest = false;
+ mBlockingResponseReceived = false;
}
LLPluginProcessChild::~LLPluginProcessChild()
{
- if (mInstance != NULL)
- {
- sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
-
- // IMPORTANT: under some (unknown) circumstances the apr_dso_unload() triggered when mInstance is deleted
- // appears to fail and lock up which means that a given instance of the slplugin process never exits.
- // This is bad, especially when users try to update their version of SL - it fails because the slplugin
- // process as well as a bunch of plugin specific files are locked and cannot be overwritten.
- exit(0);
- //delete mInstance;
- //mInstance = NULL;
- }
+ if (mInstance != NULL)
+ {
+ sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
+
+ // IMPORTANT: under some (unknown) circumstances the apr_dso_unload() triggered when mInstance is deleted
+ // appears to fail and lock up which means that a given instance of the slplugin process never exits.
+ // This is bad, especially when users try to update their version of SL - it fails because the slplugin
+ // process as well as a bunch of plugin specific files are locked and cannot be overwritten.
+ exit(0);
+ //delete mInstance;
+ //mInstance = NULL;
+ }
}
void LLPluginProcessChild::killSockets(void)
{
- killMessagePipe();
- mSocket.reset();
+ killMessagePipe();
+ mSocket.reset();
}
void LLPluginProcessChild::init(U32 launcher_port)
{
- mLauncherHost = LLHost("127.0.0.1", launcher_port);
- setState(STATE_INITIALIZED);
+ mLauncherHost = LLHost("127.0.0.1", launcher_port);
+ setState(STATE_INITIALIZED);
}
void LLPluginProcessChild::idle(void)
{
- bool idle_again;
- do
- {
- if (mState < STATE_SHUTDOWNREQ)
- { // Once we have hit the shutdown request state checking for errors might put us in a spurious
- // error state... don't do that.
-
- if (APR_STATUS_IS_EOF(mSocketError))
- {
- // Plugin socket was closed. This covers both normal plugin termination and host crashes.
- setState(STATE_ERROR);
- }
- else if (mSocketError != APR_SUCCESS)
- {
- LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR" << LL_ENDL;
- setState(STATE_ERROR);
- }
-
- if ((mState > STATE_INITIALIZED) && (mMessagePipe == NULL))
- {
- // The pipe has been closed -- we're done.
- // TODO: This could be slightly more subtle, but I'm not sure it needs to be.
- LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR" << LL_ENDL;
- setState(STATE_ERROR);
- }
- }
-
- // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
- // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
- // When in doubt, don't do it.
- idle_again = false;
-
- if (mInstance != NULL)
- {
- // Provide some time to the plugin
- mInstance->idle();
- }
-
- switch (mState)
- {
- case STATE_UNINITIALIZED:
- break;
-
- case STATE_INITIALIZED:
- if (mSocket->blockingConnect(mLauncherHost))
- {
- // This automatically sets mMessagePipe
- new LLPluginMessagePipe(this, mSocket);
-
- setState(STATE_CONNECTED);
- }
- else
- {
- // connect failed
- setState(STATE_ERROR);
- }
- break;
-
- case STATE_CONNECTED:
- sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello"));
- setState(STATE_PLUGIN_LOADING);
- break;
-
- case STATE_PLUGIN_LOADING:
- if (!mPluginFile.empty())
- {
- mInstance = new LLPluginInstance(this);
- if (mInstance->load(mPluginDir, mPluginFile) == 0)
- {
- mHeartbeat.start();
- mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
- mCPUElapsed = 0.0f;
- setState(STATE_PLUGIN_LOADED);
- }
- else
- {
- setState(STATE_ERROR);
- }
- }
- break;
-
- case STATE_PLUGIN_LOADED:
- {
- setState(STATE_PLUGIN_INITIALIZING);
- LLPluginMessage message("base", "init");
- sendMessageToPlugin(message);
- }
- break;
-
- case STATE_PLUGIN_INITIALIZING:
- // waiting for init_response...
- break;
-
- case STATE_RUNNING:
- if (mInstance != NULL)
- {
- // Provide some time to the plugin
- LLPluginMessage message("base", "idle");
- message.setValueReal("time", PLUGIN_IDLE_SECONDS);
- sendMessageToPlugin(message);
-
- mInstance->idle();
-
- if (mHeartbeat.hasExpired())
- {
-
- // This just proves that we're not stuck down inside the plugin code.
- LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat");
-
- // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle.
- // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation.
- // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation.
- heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64());
-
- sendMessageToParent(heartbeat);
-
- mHeartbeat.reset();
- mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
- mCPUElapsed = 0.0f;
- }
- }
- // receivePluginMessage will transition to STATE_UNLOADING
- break;
-
- case STATE_SHUTDOWNREQ:
- // set next state first thing in case "cleanup" message advances state.
- setState(STATE_UNLOADING);
- mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS);
-
- if (mInstance != NULL)
- {
- sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
- }
- break;
-
- case STATE_UNLOADING:
- // waiting for goodbye from plugin.
- if (mWaitGoodbye.hasExpired())
- {
- LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL;
- if (mInstance != NULL)
- {
- // Something went wrong, at least make sure plugin will terminate
- sendMessageToPlugin(LLPluginMessage("base", "force_exit"));
- }
- setState(STATE_UNLOADED);
- }
+ bool idle_again;
+ do
+ {
+ if (mState < STATE_SHUTDOWNREQ)
+ { // Once we have hit the shutdown request state checking for errors might put us in a spurious
+ // error state... don't do that.
+
+ if (APR_STATUS_IS_EOF(mSocketError))
+ {
+ // Plugin socket was closed. This covers both normal plugin termination and host crashes.
+ setState(STATE_ERROR);
+ }
+ else if (mSocketError != APR_SUCCESS)
+ {
+ LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR" << LL_ENDL;
+ setState(STATE_ERROR);
+ }
+
+ if ((mState > STATE_INITIALIZED) && (mMessagePipe == NULL))
+ {
+ // The pipe has been closed -- we're done.
+ // TODO: This could be slightly more subtle, but I'm not sure it needs to be.
+ LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR" << LL_ENDL;
+ setState(STATE_ERROR);
+ }
+ }
+
+ // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
+ // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
+ // When in doubt, don't do it.
+ idle_again = false;
+
+ if (mInstance != NULL)
+ {
+ // Provide some time to the plugin
+ mInstance->idle();
+ }
+
+ switch (mState)
+ {
+ case STATE_UNINITIALIZED:
+ break;
+
+ case STATE_INITIALIZED:
+ if (mSocket->blockingConnect(mLauncherHost))
+ {
+ // This automatically sets mMessagePipe
+ new LLPluginMessagePipe(this, mSocket);
+
+ setState(STATE_CONNECTED);
+ }
+ else
+ {
+ // connect failed
+ setState(STATE_ERROR);
+ }
+ break;
+
+ case STATE_CONNECTED:
+ sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello"));
+ setState(STATE_PLUGIN_LOADING);
+ break;
+
+ case STATE_PLUGIN_LOADING:
+ if (!mPluginFile.empty())
+ {
+ mInstance = new LLPluginInstance(this);
+ if (mInstance->load(mPluginDir, mPluginFile) == 0)
+ {
+ mHeartbeat.start();
+ mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
+ mCPUElapsed = 0.0f;
+ setState(STATE_PLUGIN_LOADED);
+ }
+ else
+ {
+ setState(STATE_ERROR);
+ }
+ }
+ break;
+
+ case STATE_PLUGIN_LOADED:
+ {
+ setState(STATE_PLUGIN_INITIALIZING);
+ LLPluginMessage message("base", "init");
+ sendMessageToPlugin(message);
+ }
+ break;
+
+ case STATE_PLUGIN_INITIALIZING:
+ // waiting for init_response...
+ break;
+
+ case STATE_RUNNING:
+ if (mInstance != NULL)
+ {
+ // Provide some time to the plugin
+ LLPluginMessage message("base", "idle");
+ message.setValueReal("time", PLUGIN_IDLE_SECONDS);
+ sendMessageToPlugin(message);
+
+ mInstance->idle();
+
+ if (mHeartbeat.hasExpired())
+ {
+
+ // This just proves that we're not stuck down inside the plugin code.
+ LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat");
+
+ // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle.
+ // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation.
+ // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation.
+ heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64());
+
+ sendMessageToParent(heartbeat);
+
+ mHeartbeat.reset();
+ mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
+ mCPUElapsed = 0.0f;
+ }
+ }
+ // receivePluginMessage will transition to STATE_UNLOADING
+ break;
+
+ case STATE_SHUTDOWNREQ:
+ // set next state first thing in case "cleanup" message advances state.
+ setState(STATE_UNLOADING);
+ mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS);
+
+ if (mInstance != NULL)
+ {
+ sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
+ }
+ break;
+
+ case STATE_UNLOADING:
+ // waiting for goodbye from plugin.
+ if (mWaitGoodbye.hasExpired())
+ {
+ LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL;
+ if (mInstance != NULL)
+ {
+ // Something went wrong, at least make sure plugin will terminate
+ sendMessageToPlugin(LLPluginMessage("base", "force_exit"));
+ }
+ setState(STATE_UNLOADED);
+ }
if (mInstance)
{
@@ -237,370 +237,370 @@ void LLPluginProcessChild::idle(void)
mInstance->idle();
}
- break;
+ break;
- case STATE_UNLOADED:
- killSockets();
- delete mInstance;
- mInstance = NULL;
- setState(STATE_DONE);
- break;
+ case STATE_UNLOADED:
+ killSockets();
+ delete mInstance;
+ mInstance = NULL;
+ setState(STATE_DONE);
+ break;
- case STATE_ERROR:
- // Close the socket to the launcher
- killSockets();
- // TODO: Where do we go from here? Just exit()?
- setState(STATE_DONE);
- break;
+ case STATE_ERROR:
+ // Close the socket to the launcher
+ killSockets();
+ // TODO: Where do we go from here? Just exit()?
+ setState(STATE_DONE);
+ break;
- case STATE_DONE:
- // just sit here.
- break;
- }
+ case STATE_DONE:
+ // just sit here.
+ break;
+ }
- } while (idle_again);
+ } while (idle_again);
}
void LLPluginProcessChild::sleep(F64 seconds)
{
- deliverQueuedMessages();
- if (mMessagePipe)
- {
- mMessagePipe->pump(seconds);
- }
- else
- {
+ deliverQueuedMessages();
+ if (mMessagePipe)
+ {
+ mMessagePipe->pump(seconds);
+ }
+ else
+ {
ms_sleep((int)(seconds * 1000.0f));
- }
+ }
}
void LLPluginProcessChild::pump(void)
{
- deliverQueuedMessages();
- if (mMessagePipe)
- {
- mMessagePipe->pump(0.0f);
- }
- else
- {
- // Should we warn here?
- }
+ deliverQueuedMessages();
+ if (mMessagePipe)
+ {
+ mMessagePipe->pump(0.0f);
+ }
+ else
+ {
+ // Should we warn here?
+ }
}
bool LLPluginProcessChild::isRunning(void)
{
- bool result = false;
+ bool result = false;
- if (mState == STATE_RUNNING)
- result = true;
+ if (mState == STATE_RUNNING)
+ result = true;
- return result;
+ return result;
}
bool LLPluginProcessChild::isDone(void)
{
- bool result = false;
-
- switch (mState)
- {
- case STATE_DONE:
- result = true;
- break;
- default:
- break;
- }
-
- return result;
+ bool result = false;
+
+ switch (mState)
+ {
+ case STATE_DONE:
+ result = true;
+ break;
+ default:
+ break;
+ }
+
+ return result;
}
void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message)
{
- if (mInstance)
- {
- std::string buffer = message.generate();
+ if (mInstance)
+ {
+ std::string buffer = message.generate();
- LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
- LLTimer elapsed;
+ LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
+ LLTimer elapsed;
- mInstance->sendMessage(buffer);
+ mInstance->sendMessage(buffer);
- mCPUElapsed += elapsed.getElapsedTimeF64();
- }
- else
- {
- LL_WARNS("Plugin") << "mInstance == NULL" << LL_ENDL;
- }
+ mCPUElapsed += elapsed.getElapsedTimeF64();
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "mInstance == NULL" << LL_ENDL;
+ }
}
void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message)
{
- std::string buffer = message.generate();
+ std::string buffer = message.generate();
- LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL;
+ LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL;
- writeMessageRaw(buffer);
+ writeMessageRaw(buffer);
}
void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
{
- // Incoming message from the TCP Socket
-
- LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL;
-
- // Decode this message
- LLPluginMessage parsed;
- parsed.parse(message);
-
- if (mBlockingRequest)
- {
- // We're blocking the plugin waiting for a response.
-
- if (parsed.hasValue("blocking_response"))
- {
- // This is the message we've been waiting for -- fall through and send it immediately.
- mBlockingResponseReceived = true;
- }
- else
- {
- // Still waiting. Queue this message and don't process it yet.
- mMessageQueue.push(message);
- return;
- }
- }
-
- bool passMessage = true;
-
- // FIXME: how should we handle queueing here?
-
- {
- std::string message_class = parsed.getClass();
- if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
- {
- passMessage = false;
-
- std::string message_name = parsed.getName();
- if (message_name == "load_plugin")
- {
- mPluginFile = parsed.getValue("file");
- mPluginDir = parsed.getValue("dir");
- }
- else if (message_name == "shutdown_plugin")
- {
- setState(STATE_SHUTDOWNREQ);
- }
- else if (message_name == "shm_add")
- {
- std::string name = parsed.getValue("name");
- size_t size = (size_t)parsed.getValueS32("size");
-
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
- if (iter != mSharedMemoryRegions.end())
- {
- // Need to remove the old region first
- LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL;
- }
- else
- {
- // This is a new region
- LLPluginSharedMemory *region = new LLPluginSharedMemory;
- if (region->attach(name, size))
- {
- mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
-
- std::stringstream addr;
- addr << region->getMappedAddress();
-
- // Send the add notification to the plugin
- LLPluginMessage message("base", "shm_added");
- message.setValue("name", name);
- message.setValueS32("size", (S32)size);
- message.setValuePointer("address", region->getMappedAddress());
- sendMessageToPlugin(message);
-
- // and send the response to the parent
- message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response");
- message.setValue("name", name);
- sendMessageToParent(message);
- }
- else
- {
- LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
- delete region;
- }
- }
-
- }
- else if (message_name == "shm_remove")
- {
- std::string name = parsed.getValue("name");
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
- if (iter != mSharedMemoryRegions.end())
- {
- // forward the remove request to the plugin -- its response will trigger us to detach the segment.
- LLPluginMessage message("base", "shm_remove");
- message.setValue("name", name);
- sendMessageToPlugin(message);
- }
- else
- {
- LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL;
- }
- }
- else if (message_name == "sleep_time")
- {
- mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz
- }
- else if (message_name == "crash")
- {
- // Crash the plugin
- LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL;
- }
- else if (message_name == "hang")
- {
- // Hang the plugin
- LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL;
- while (1)
- {
- // wheeeeeeeee......
- }
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown internal message from parent: " << message_name << LL_ENDL;
- }
- }
- }
-
- if (passMessage && mInstance != NULL)
- {
- LLTimer elapsed;
-
- mInstance->sendMessage(message);
-
- mCPUElapsed += elapsed.getElapsedTimeF64();
- }
+ // Incoming message from the TCP Socket
+
+ LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL;
+
+ // Decode this message
+ LLPluginMessage parsed;
+ parsed.parse(message);
+
+ if (mBlockingRequest)
+ {
+ // We're blocking the plugin waiting for a response.
+
+ if (parsed.hasValue("blocking_response"))
+ {
+ // This is the message we've been waiting for -- fall through and send it immediately.
+ mBlockingResponseReceived = true;
+ }
+ else
+ {
+ // Still waiting. Queue this message and don't process it yet.
+ mMessageQueue.push(message);
+ return;
+ }
+ }
+
+ bool passMessage = true;
+
+ // FIXME: how should we handle queueing here?
+
+ {
+ std::string message_class = parsed.getClass();
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
+ {
+ passMessage = false;
+
+ std::string message_name = parsed.getName();
+ if (message_name == "load_plugin")
+ {
+ mPluginFile = parsed.getValue("file");
+ mPluginDir = parsed.getValue("dir");
+ }
+ else if (message_name == "shutdown_plugin")
+ {
+ setState(STATE_SHUTDOWNREQ);
+ }
+ else if (message_name == "shm_add")
+ {
+ std::string name = parsed.getValue("name");
+ size_t size = (size_t)parsed.getValueS32("size");
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if (iter != mSharedMemoryRegions.end())
+ {
+ // Need to remove the old region first
+ LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL;
+ }
+ else
+ {
+ // This is a new region
+ LLPluginSharedMemory *region = new LLPluginSharedMemory;
+ if (region->attach(name, size))
+ {
+ mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
+
+ std::stringstream addr;
+ addr << region->getMappedAddress();
+
+ // Send the add notification to the plugin
+ LLPluginMessage message("base", "shm_added");
+ message.setValue("name", name);
+ message.setValueS32("size", (S32)size);
+ message.setValuePointer("address", region->getMappedAddress());
+ sendMessageToPlugin(message);
+
+ // and send the response to the parent
+ message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response");
+ message.setValue("name", name);
+ sendMessageToParent(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
+ delete region;
+ }
+ }
+
+ }
+ else if (message_name == "shm_remove")
+ {
+ std::string name = parsed.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if (iter != mSharedMemoryRegions.end())
+ {
+ // forward the remove request to the plugin -- its response will trigger us to detach the segment.
+ LLPluginMessage message("base", "shm_remove");
+ message.setValue("name", name);
+ sendMessageToPlugin(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL;
+ }
+ }
+ else if (message_name == "sleep_time")
+ {
+ mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz
+ }
+ else if (message_name == "crash")
+ {
+ // Crash the plugin
+ LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL;
+ }
+ else if (message_name == "hang")
+ {
+ // Hang the plugin
+ LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL;
+ while (1)
+ {
+ // wheeeeeeeee......
+ }
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown internal message from parent: " << message_name << LL_ENDL;
+ }
+ }
+ }
+
+ if (passMessage && mInstance != NULL)
+ {
+ LLTimer elapsed;
+
+ mInstance->sendMessage(message);
+
+ mCPUElapsed += elapsed.getElapsedTimeF64();
+ }
}
/* virtual */
void LLPluginProcessChild::receivePluginMessage(const std::string &message)
{
- LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL;
-
- if (mBlockingRequest)
- {
- //
- LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL;
- }
-
- // Incoming message from the plugin instance
- bool passMessage = true;
-
- // FIXME: how should we handle queueing here?
-
- // Intercept certain base messages (responses to ones sent by this class)
- {
- // Decode this message
- LLPluginMessage parsed;
- parsed.parse(message);
-
- if (parsed.hasValue("blocking_request"))
- {
- mBlockingRequest = true;
- }
-
- std::string message_class = parsed.getClass();
- if (message_class == "base")
- {
- std::string message_name = parsed.getName();
- if (message_name == "init_response")
- {
- // The plugin has finished initializing.
- setState(STATE_RUNNING);
-
- // Don't pass this message up to the parent
- passMessage = false;
-
- LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response");
- LLSD versions = parsed.getValueLLSD("versions");
- new_message.setValueLLSD("versions", versions);
-
- if (parsed.hasValue("plugin_version"))
- {
- std::string plugin_version = parsed.getValue("plugin_version");
- new_message.setValueLLSD("plugin_version", plugin_version);
- }
-
- // Let the parent know it's loaded and initialized.
- sendMessageToParent(new_message);
- }
- else if (message_name == "goodbye")
- {
- setState(STATE_UNLOADED);
- }
- else if (message_name == "shm_remove_response")
- {
- // Don't pass this message up to the parent
- passMessage = false;
-
- std::string name = parsed.getValue("name");
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
- if (iter != mSharedMemoryRegions.end())
- {
- // detach the shared memory region
- iter->second->detach();
-
- // and remove it from our map
- mSharedMemoryRegions.erase(iter);
-
- // Finally, send the response to the parent.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response");
- message.setValue("name", name);
- sendMessageToParent(message);
- }
- else
- {
- LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL;
- }
- }
- }
- }
-
- if (passMessage)
- {
- LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;
- writeMessageRaw(message);
- }
-
- while (mBlockingRequest)
- {
- // The plugin wants to block and wait for a response to this message.
- sleep(mSleepTime); // this will pump the message pipe and process messages
-
- if (mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL))
- {
- // Response has been received, or we've hit an error state. Stop waiting.
- mBlockingRequest = false;
- mBlockingResponseReceived = false;
- }
- }
+ LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL;
+
+ if (mBlockingRequest)
+ {
+ //
+ LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL;
+ }
+
+ // Incoming message from the plugin instance
+ bool passMessage = true;
+
+ // FIXME: how should we handle queueing here?
+
+ // Intercept certain base messages (responses to ones sent by this class)
+ {
+ // Decode this message
+ LLPluginMessage parsed;
+ parsed.parse(message);
+
+ if (parsed.hasValue("blocking_request"))
+ {
+ mBlockingRequest = true;
+ }
+
+ std::string message_class = parsed.getClass();
+ if (message_class == "base")
+ {
+ std::string message_name = parsed.getName();
+ if (message_name == "init_response")
+ {
+ // The plugin has finished initializing.
+ setState(STATE_RUNNING);
+
+ // Don't pass this message up to the parent
+ passMessage = false;
+
+ LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response");
+ LLSD versions = parsed.getValueLLSD("versions");
+ new_message.setValueLLSD("versions", versions);
+
+ if (parsed.hasValue("plugin_version"))
+ {
+ std::string plugin_version = parsed.getValue("plugin_version");
+ new_message.setValueLLSD("plugin_version", plugin_version);
+ }
+
+ // Let the parent know it's loaded and initialized.
+ sendMessageToParent(new_message);
+ }
+ else if (message_name == "goodbye")
+ {
+ setState(STATE_UNLOADED);
+ }
+ else if (message_name == "shm_remove_response")
+ {
+ // Don't pass this message up to the parent
+ passMessage = false;
+
+ std::string name = parsed.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if (iter != mSharedMemoryRegions.end())
+ {
+ // detach the shared memory region
+ iter->second->detach();
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+
+ // Finally, send the response to the parent.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response");
+ message.setValue("name", name);
+ sendMessageToParent(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ if (passMessage)
+ {
+ LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;
+ writeMessageRaw(message);
+ }
+
+ while (mBlockingRequest)
+ {
+ // The plugin wants to block and wait for a response to this message.
+ sleep(mSleepTime); // this will pump the message pipe and process messages
+
+ if (mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL))
+ {
+ // Response has been received, or we've hit an error state. Stop waiting.
+ mBlockingRequest = false;
+ mBlockingResponseReceived = false;
+ }
+ }
}
void LLPluginProcessChild::setState(EState state)
{
- LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
- mState = state;
+ LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
+ mState = state;
};
void LLPluginProcessChild::deliverQueuedMessages()
{
- if (!mBlockingRequest)
- {
- while (!mMessageQueue.empty())
- {
- receiveMessageRaw(mMessageQueue.front());
- mMessageQueue.pop();
- }
- }
+ if (!mBlockingRequest)
+ {
+ while (!mMessageQueue.empty())
+ {
+ receiveMessageRaw(mMessageQueue.front());
+ mMessageQueue.pop();
+ }
+ }
}
diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h
index b916cc9528..5de0f90209 100644
--- a/indra/llplugin/llpluginprocesschild.h
+++ b/indra/llplugin/llpluginprocesschild.h
@@ -1,26 +1,26 @@
-/**
+/**
* @file llpluginprocesschild.h
- * @brief LLPluginProcessChild handles the child side of the external-process plugin API.
+ * @brief LLPluginProcessChild handles the child side of the external-process plugin API.
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -40,76 +40,76 @@ class LLPluginInstance;
class LLPluginProcessChild: public LLPluginMessagePipeOwner, public LLPluginInstanceMessageListener
{
- LOG_CLASS(LLPluginProcessChild);
+ LOG_CLASS(LLPluginProcessChild);
public:
- LLPluginProcessChild();
- ~LLPluginProcessChild();
-
- void init(U32 launcher_port);
- void idle(void);
- void sleep(F64 seconds);
- void pump();
-
- // returns true if the plugin is in the steady state (processing messages)
- bool isRunning(void);
-
- // returns true if the plugin is unloaded or we're in an unrecoverable error state.
- bool isDone(void);
-
- void killSockets(void);
-
- F64 getSleepTime(void) const { return mSleepTime; };
-
- void sendMessageToPlugin(const LLPluginMessage &message);
- void sendMessageToParent(const LLPluginMessage &message);
-
- // Inherited from LLPluginMessagePipeOwner
- /* virtual */ void receiveMessageRaw(const std::string &message);
-
- // Inherited from LLPluginInstanceMessageListener
- /* virtual */ void receivePluginMessage(const std::string &message);
-
+ LLPluginProcessChild();
+ ~LLPluginProcessChild();
+
+ void init(U32 launcher_port);
+ void idle(void);
+ void sleep(F64 seconds);
+ void pump();
+
+ // returns true if the plugin is in the steady state (processing messages)
+ bool isRunning(void);
+
+ // returns true if the plugin is unloaded or we're in an unrecoverable error state.
+ bool isDone(void);
+
+ void killSockets(void);
+
+ F64 getSleepTime(void) const { return mSleepTime; };
+
+ void sendMessageToPlugin(const LLPluginMessage &message);
+ void sendMessageToParent(const LLPluginMessage &message);
+
+ // Inherited from LLPluginMessagePipeOwner
+ /* virtual */ void receiveMessageRaw(const std::string &message);
+
+ // Inherited from LLPluginInstanceMessageListener
+ /* virtual */ void receivePluginMessage(const std::string &message);
+
private:
- enum EState
- {
- STATE_UNINITIALIZED,
- STATE_INITIALIZED, // init() has been called
- STATE_CONNECTED, // connected back to launcher
- STATE_PLUGIN_LOADING, // plugin library needs to be loaded
- STATE_PLUGIN_LOADED, // plugin library has been loaded
- STATE_PLUGIN_INITIALIZING, // plugin is processing init message
- STATE_RUNNING, // steady state (processing messages)
+ enum EState
+ {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZED, // init() has been called
+ STATE_CONNECTED, // connected back to launcher
+ STATE_PLUGIN_LOADING, // plugin library needs to be loaded
+ STATE_PLUGIN_LOADED, // plugin library has been loaded
+ STATE_PLUGIN_INITIALIZING, // plugin is processing init message
+ STATE_RUNNING, // steady state (processing messages)
STATE_SHUTDOWNREQ, // Parent has requested a shutdown.
- STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded
- STATE_UNLOADED, // plugin has been unloaded
- STATE_ERROR, // generic bailout state
- STATE_DONE // state machine will sit in this state after either error or normal termination.
- };
- void setState(EState state);
-
- EState mState;
-
- LLHost mLauncherHost;
- LLSocket::ptr_t mSocket;
-
- std::string mPluginFile;
- std::string mPluginDir;
-
- LLPluginInstance *mInstance;
-
- typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
- sharedMemoryRegionsType mSharedMemoryRegions;
-
- LLTimer mHeartbeat;
- F64 mSleepTime;
- F64 mCPUElapsed;
- bool mBlockingRequest;
- bool mBlockingResponseReceived;
- std::queue<std::string> mMessageQueue;
+ STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded
+ STATE_UNLOADED, // plugin has been unloaded
+ STATE_ERROR, // generic bailout state
+ STATE_DONE // state machine will sit in this state after either error or normal termination.
+ };
+ void setState(EState state);
+
+ EState mState;
+
+ LLHost mLauncherHost;
+ LLSocket::ptr_t mSocket;
+
+ std::string mPluginFile;
+ std::string mPluginDir;
+
+ LLPluginInstance *mInstance;
+
+ typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
+ sharedMemoryRegionsType mSharedMemoryRegions;
+
+ LLTimer mHeartbeat;
+ F64 mSleepTime;
+ F64 mCPUElapsed;
+ bool mBlockingRequest;
+ bool mBlockingResponseReceived;
+ std::queue<std::string> mMessageQueue;
LLTimer mWaitGoodbye;
- void deliverQueuedMessages();
-
+ void deliverQueuedMessages();
+
};
#endif // LL_LLPLUGINPROCESSCHILD_H
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index a28f6c648f..00abcf740f 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginprocessparent.cpp
* @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -36,10 +36,10 @@
#include "stringize.h"
#include "llapr.h"
-//virtual
+//virtual
LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
{
-
+
}
bool LLPluginProcessParent::sUseReadThread = false;
@@ -53,29 +53,29 @@ LLThread *LLPluginProcessParent::sReadThread = NULL;
class LLPluginProcessParentPollThread: public LLThread
{
public:
- LLPluginProcessParentPollThread() :
- LLThread("LLPluginProcessParentPollThread", gAPRPoolp)
- {
- }
+ LLPluginProcessParentPollThread() :
+ LLThread("LLPluginProcessParentPollThread", gAPRPoolp)
+ {
+ }
protected:
- // Inherited from LLThread
- /*virtual*/ void run(void)
- {
- while(!isQuitting() && LLPluginProcessParent::getUseReadThread())
- {
- LLPluginProcessParent::poll(0.1f);
- checkPause();
- }
-
- // Final poll to clean up the pollset, etc.
- LLPluginProcessParent::poll(0.0f);
- }
-
- // Inherited from LLThread
- /*virtual*/ bool runCondition(void)
- {
- return(LLPluginProcessParent::canPollThreadRun());
- }
+ // Inherited from LLThread
+ /*virtual*/ void run(void)
+ {
+ while(!isQuitting() && LLPluginProcessParent::getUseReadThread())
+ {
+ LLPluginProcessParent::poll(0.1f);
+ checkPause();
+ }
+
+ // Final poll to clean up the pollset, etc.
+ LLPluginProcessParent::poll(0.0f);
+ }
+
+ // Inherited from LLThread
+ /*virtual*/ bool runCondition(void)
+ {
+ return(LLPluginProcessParent::canPollThreadRun());
+ }
};
@@ -103,33 +103,33 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
mIncomingQueueMutex(),
pProcessCreationThread(NULL)
{
- if(!sInstancesMutex)
- {
- sInstancesMutex = new LLCoros::Mutex();
- }
-
- mOwner = owner;
- mBoundPort = 0;
- mState = STATE_UNINITIALIZED;
- mSleepTime = 0.0;
- mCPUUsage = 0.0;
- mDisableTimeout = false;
- mDebug = false;
- mBlocked = false;
- mPolledInput = false;
- mPollFD.client_data = NULL;
-
- mPluginLaunchTimeout = 60.0f;
- mPluginLockupTimeout = 15.0f;
-
- // Don't start the timer here -- start it when we actually launch the plugin process.
- mHeartbeat.stop();
-
+ if(!sInstancesMutex)
+ {
+ sInstancesMutex = new LLCoros::Mutex();
+ }
+
+ mOwner = owner;
+ mBoundPort = 0;
+ mState = STATE_UNINITIALIZED;
+ mSleepTime = 0.0;
+ mCPUUsage = 0.0;
+ mDisableTimeout = false;
+ mDebug = false;
+ mBlocked = false;
+ mPolledInput = false;
+ mPollFD.client_data = NULL;
+
+ mPluginLaunchTimeout = 60.0f;
+ mPluginLockupTimeout = 15.0f;
+
+ // Don't start the timer here -- start it when we actually launch the plugin process.
+ mHeartbeat.stop();
+
}
LLPluginProcessParent::~LLPluginProcessParent()
{
- LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
+ LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
if (pProcessCreationThread)
{
if (!pProcessCreationThread->isStopped())
@@ -143,20 +143,20 @@ LLPluginProcessParent::~LLPluginProcessParent()
pProcessCreationThread = NULL;
}
- // Destroy any remaining shared memory regions
- sharedMemoryRegionsType::iterator iter;
- while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end())
- {
- // destroy the shared memory region
- iter->second->destroy();
- delete iter->second;
- iter->second = NULL;
-
- // and remove it from our map
- mSharedMemoryRegions.erase(iter);
- }
-
- LLProcess::kill(mProcess);
+ // Destroy any remaining shared memory regions
+ sharedMemoryRegionsType::iterator iter;
+ while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end())
+ {
+ // destroy the shared memory region
+ iter->second->destroy();
+ delete iter->second;
+ iter->second = NULL;
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+ }
+
+ LLProcess::kill(mProcess);
if (!LLApp::isQuitting())
{ // If we are quitting, the network sockets will already have been destroyed.
killSockets();
@@ -226,7 +226,7 @@ void LLPluginProcessParent::requestShutdown()
namestream << "LLPluginProcessParentListener" << ++count;
//*HACK!*//
- // After requestShutdown has been called our previous owner will no longer call
+ // After requestShutdown has been called our previous owner will no longer call
// our idle() method. Tie into the event loop here to do that until we are good
// and finished.
LL_DEBUGS("LLPluginProcessParent") << "listening on \"mainloop\"" << LL_ENDL;
@@ -278,78 +278,78 @@ bool LLPluginProcessParent::wantsPolling() const
void LLPluginProcessParent::killSockets(void)
{
- {
- LLMutexLock lock(&mIncomingQueueMutex);
- killMessagePipe();
- }
+ {
+ LLMutexLock lock(&mIncomingQueueMutex);
+ killMessagePipe();
+ }
- mListenSocket.reset();
- mSocket.reset();
+ mListenSocket.reset();
+ mSocket.reset();
}
void LLPluginProcessParent::errorState(void)
{
- if(mState < STATE_RUNNING)
- setState(STATE_LAUNCH_FAILURE);
- else
- setState(STATE_ERROR);
+ if(mState < STATE_RUNNING)
+ setState(STATE_LAUNCH_FAILURE);
+ else
+ setState(STATE_ERROR);
}
void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{
- mProcessParams.executable = launcher_filename;
- mProcessParams.cwd = plugin_dir;
- mPluginFile = plugin_filename;
- mPluginDir = plugin_dir;
- mCPUUsage = 0.0f;
- mDebug = debug;
- setState(STATE_INITIALIZED);
+{
+ mProcessParams.executable = launcher_filename;
+ mProcessParams.cwd = plugin_dir;
+ mPluginFile = plugin_filename;
+ mPluginDir = plugin_dir;
+ mCPUUsage = 0.0f;
+ mDebug = debug;
+ setState(STATE_INITIALIZED);
}
bool LLPluginProcessParent::accept()
{
- bool result = false;
-
- apr_status_t status = APR_EGENERAL;
- apr_socket_t *new_socket = NULL;
-
- status = apr_socket_accept(
- &new_socket,
- mListenSocket->getSocket(),
- gAPRPoolp);
-
-
- if(status == APR_SUCCESS)
- {
-// LL_INFOS() << "SUCCESS" << LL_ENDL;
- // Success. Create a message pipe on the new socket
-
- // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
- apr_pool_t* new_pool = NULL;
- status = apr_pool_create(&new_pool, gAPRPoolp);
-
- mSocket = LLSocket::create(new_socket, new_pool);
- new LLPluginMessagePipe(this, mSocket);
-
- result = true;
- }
- else if(APR_STATUS_IS_EAGAIN(status))
- {
-// LL_INFOS() << "EAGAIN" << LL_ENDL;
-
- // No incoming connections. This is not an error.
- status = APR_SUCCESS;
- }
- else
- {
-// LL_INFOS() << "Error:" << LL_ENDL;
- ll_apr_warn_status(status);
-
- // Some other error.
- errorState();
- }
-
- return result;
+ bool result = false;
+
+ apr_status_t status = APR_EGENERAL;
+ apr_socket_t *new_socket = NULL;
+
+ status = apr_socket_accept(
+ &new_socket,
+ mListenSocket->getSocket(),
+ gAPRPoolp);
+
+
+ if(status == APR_SUCCESS)
+ {
+// LL_INFOS() << "SUCCESS" << LL_ENDL;
+ // Success. Create a message pipe on the new socket
+
+ // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
+ apr_pool_t* new_pool = NULL;
+ status = apr_pool_create(&new_pool, gAPRPoolp);
+
+ mSocket = LLSocket::create(new_socket, new_pool);
+ new LLPluginMessagePipe(this, mSocket);
+
+ result = true;
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+// LL_INFOS() << "EAGAIN" << LL_ENDL;
+
+ // No incoming connections. This is not an error.
+ status = APR_SUCCESS;
+ }
+ else
+ {
+// LL_INFOS() << "Error:" << LL_ENDL;
+ ll_apr_warn_status(status);
+
+ // Some other error.
+ errorState();
+ }
+
+ return result;
}
bool LLPluginProcessParent::createPluginProcess()
@@ -383,166 +383,166 @@ void LLPluginProcessParent::clearProcessCreationThread()
void LLPluginProcessParent::idle(void)
{
- bool idle_again;
+ bool idle_again;
- do
- {
- // process queued messages
+ do
+ {
+ // process queued messages
// Inside main thread, it is preferable not to block it on mutex.
- bool locked = mIncomingQueueMutex.trylock();
- while(locked && !mIncomingQueue.empty())
- {
- LLPluginMessage message = mIncomingQueue.front();
- mIncomingQueue.pop();
- mIncomingQueueMutex.unlock();
-
- receiveMessage(message);
-
- locked = mIncomingQueueMutex.trylock();
- }
+ bool locked = mIncomingQueueMutex.trylock();
+ while(locked && !mIncomingQueue.empty())
+ {
+ LLPluginMessage message = mIncomingQueue.front();
+ mIncomingQueue.pop();
+ mIncomingQueueMutex.unlock();
+
+ receiveMessage(message);
+
+ locked = mIncomingQueueMutex.trylock();
+ }
if (locked)
{
mIncomingQueueMutex.unlock();
}
-
- // Give time to network processing
- if(mMessagePipe)
- {
- // Drain any queued outgoing messages
- mMessagePipe->pumpOutput();
-
- // Only do input processing here if this instance isn't in a pollset.
- // If viewer and plugin are both shutting down, don't process further
- // input, viewer won't be able to handle it.
- if(!mPolledInput
- && !(mState >= STATE_GOODBYE && LLApp::isExiting()))
- {
- mMessagePipe->pumpInput();
- }
- }
-
- if(mState <= STATE_RUNNING)
- {
- if(APR_STATUS_IS_EOF(mSocketError))
- {
- // Plugin socket was closed. This covers both normal plugin termination and plugin crashes.
- errorState();
- }
- else if(mSocketError != APR_SUCCESS)
- {
- // The socket is in an error state -- the plugin is gone.
- LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
- errorState();
- }
- }
-
- // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
- // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
- // When in doubt, don't do it.
- idle_again = false;
- switch(mState)
- {
- case STATE_UNINITIALIZED:
- break;
-
- case STATE_INITIALIZED:
- {
-
- apr_status_t status = APR_SUCCESS;
- apr_sockaddr_t* addr = NULL;
- mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
- mBoundPort = 0;
-
- // This code is based on parts of LLSocket::create() in lliosocket.cpp.
-
- status = apr_sockaddr_info_get(
- &addr,
- "127.0.0.1",
- APR_INET,
- 0, // port 0 = ephemeral ("find me a port")
- 0,
- gAPRPoolp);
-
- if(ll_apr_warn_status(status))
- {
- killSockets();
- errorState();
- break;
- }
-
- // This allows us to reuse the address on quick down/up. This is unlikely to create problems.
- ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1));
-
- status = apr_socket_bind(mListenSocket->getSocket(), addr);
- if(ll_apr_warn_status(status))
- {
- killSockets();
- errorState();
- break;
- }
-
- // Get the actual port the socket was bound to
- {
- apr_sockaddr_t* bound_addr = NULL;
- if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
- {
- killSockets();
- errorState();
- break;
- }
- mBoundPort = bound_addr->port;
-
- if(mBoundPort == 0)
- {
- LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
-
- killSockets();
- errorState();
- break;
- }
- }
-
- LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL;
-
- // Make the listen socket non-blocking
- status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1);
- if(ll_apr_warn_status(status))
- {
- killSockets();
- errorState();
- break;
- }
-
- apr_socket_timeout_set(mListenSocket->getSocket(), 0);
- if(ll_apr_warn_status(status))
- {
- killSockets();
- errorState();
- break;
- }
-
- // If it's a stream based socket, we need to tell the OS
- // to keep a queue of incoming connections for ACCEPT.
- status = apr_socket_listen(
- mListenSocket->getSocket(),
- 10); // FIXME: Magic number for queue size
-
- if(ll_apr_warn_status(status))
- {
- killSockets();
- errorState();
- break;
- }
-
- // If we got here, we're listening.
- setState(STATE_LISTENING);
- }
- break;
-
- case STATE_LISTENING:
- {
- // Launch the plugin process.
+
+ // Give time to network processing
+ if(mMessagePipe)
+ {
+ // Drain any queued outgoing messages
+ mMessagePipe->pumpOutput();
+
+ // Only do input processing here if this instance isn't in a pollset.
+ // If viewer and plugin are both shutting down, don't process further
+ // input, viewer won't be able to handle it.
+ if(!mPolledInput
+ && !(mState >= STATE_GOODBYE && LLApp::isExiting()))
+ {
+ mMessagePipe->pumpInput();
+ }
+ }
+
+ if(mState <= STATE_RUNNING)
+ {
+ if(APR_STATUS_IS_EOF(mSocketError))
+ {
+ // Plugin socket was closed. This covers both normal plugin termination and plugin crashes.
+ errorState();
+ }
+ else if(mSocketError != APR_SUCCESS)
+ {
+ // The socket is in an error state -- the plugin is gone.
+ LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
+ errorState();
+ }
+ }
+
+ // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
+ // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
+ // When in doubt, don't do it.
+ idle_again = false;
+ switch(mState)
+ {
+ case STATE_UNINITIALIZED:
+ break;
+
+ case STATE_INITIALIZED:
+ {
+
+ apr_status_t status = APR_SUCCESS;
+ apr_sockaddr_t* addr = NULL;
+ mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
+ mBoundPort = 0;
+
+ // This code is based on parts of LLSocket::create() in lliosocket.cpp.
+
+ status = apr_sockaddr_info_get(
+ &addr,
+ "127.0.0.1",
+ APR_INET,
+ 0, // port 0 = ephemeral ("find me a port")
+ 0,
+ gAPRPoolp);
+
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // This allows us to reuse the address on quick down/up. This is unlikely to create problems.
+ ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1));
+
+ status = apr_socket_bind(mListenSocket->getSocket(), addr);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // Get the actual port the socket was bound to
+ {
+ apr_sockaddr_t* bound_addr = NULL;
+ if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+ mBoundPort = bound_addr->port;
+
+ if(mBoundPort == 0)
+ {
+ LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
+
+ killSockets();
+ errorState();
+ break;
+ }
+ }
+
+ LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL;
+
+ // Make the listen socket non-blocking
+ status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ apr_socket_timeout_set(mListenSocket->getSocket(), 0);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // If it's a stream based socket, we need to tell the OS
+ // to keep a queue of incoming connections for ACCEPT.
+ status = apr_socket_listen(
+ mListenSocket->getSocket(),
+ 10); // FIXME: Magic number for queue size
+
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // If we got here, we're listening.
+ setState(STATE_LISTENING);
+ }
+ break;
+
+ case STATE_LISTENING:
+ {
+ // Launch the plugin process.
if (mDebug && !pProcessCreationThread)
{
createPluginProcess();
@@ -565,36 +565,36 @@ void LLPluginProcessParent::idle(void)
errorState();
}
-
- if (mProcess)
- {
- if(mDebug)
- {
+
+ if (mProcess)
+ {
+ if(mDebug)
+ {
#if LL_DARWIN
- // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
-
- // The command we're constructing would look like this on the command line:
- // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
-
- LLProcess::Params params;
- params.executable = "/usr/bin/osascript";
- params.args.add("-e");
- params.args.add("tell application \"Terminal\"");
- params.args.add("-e");
- params.args.add(STRINGIZE("set win to do script \"lldb -pid "
- << mProcess->getProcessID() << "\""));
- params.args.add("-e");
- params.args.add("do script \"continue\" in win");
- params.args.add("-e");
- params.args.add("end tell");
- mDebugger = LLProcess::create(params);
+ // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
+
+ // The command we're constructing would look like this on the command line:
+ // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
+
+ LLProcess::Params params;
+ params.executable = "/usr/bin/osascript";
+ params.args.add("-e");
+ params.args.add("tell application \"Terminal\"");
+ params.args.add("-e");
+ params.args.add(STRINGIZE("set win to do script \"lldb -pid "
+ << mProcess->getProcessID() << "\""));
+ params.args.add("-e");
+ params.args.add("do script \"continue\" in win");
+ params.args.add("-e");
+ params.args.add("end tell");
+ mDebugger = LLProcess::create(params);
#endif
- }
-
- // This will allow us to time out if the process never starts.
- mHeartbeat.start();
- mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
+ }
+
+ // This will allow us to time out if the process never starts.
+ mHeartbeat.start();
+ mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
// pProcessCreationThread should have stopped by this point,
// but check just in case it paused on statistics sync
@@ -604,67 +604,67 @@ void LLPluginProcessParent::idle(void)
pProcessCreationThread = NULL;
}
- setState(STATE_LAUNCHED);
- }
- }
- break;
-
- case STATE_LAUNCHED:
- // waiting for the plugin to connect
- if(pluginLockedUpOrQuit())
- {
- errorState();
- }
- else
- {
- // Check for the incoming connection.
- if(accept())
- {
- // Stop listening on the server port
- mListenSocket.reset();
- setState(STATE_CONNECTED);
- }
- }
- break;
-
- case STATE_CONNECTED:
- // waiting for hello message from the plugin
-
- if(pluginLockedUpOrQuit())
- {
- errorState();
- }
- break;
-
- case STATE_HELLO:
- LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;
-
- // Send the message to load the plugin
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
- message.setValue("file", mPluginFile);
- message.setValue("dir", mPluginDir);
- sendMessage(message);
- }
-
- setState(STATE_LOADING);
- break;
-
- case STATE_LOADING:
- // The load_plugin_response message will kick us from here into STATE_RUNNING
- if(pluginLockedUpOrQuit())
- {
- errorState();
- }
- break;
-
- case STATE_RUNNING:
- if(pluginLockedUpOrQuit())
- {
- errorState();
- }
- break;
-
+ setState(STATE_LAUNCHED);
+ }
+ }
+ break;
+
+ case STATE_LAUNCHED:
+ // waiting for the plugin to connect
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ else
+ {
+ // Check for the incoming connection.
+ if(accept())
+ {
+ // Stop listening on the server port
+ mListenSocket.reset();
+ setState(STATE_CONNECTED);
+ }
+ }
+ break;
+
+ case STATE_CONNECTED:
+ // waiting for hello message from the plugin
+
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
+ case STATE_HELLO:
+ LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;
+
+ // Send the message to load the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
+ message.setValue("file", mPluginFile);
+ message.setValue("dir", mPluginDir);
+ sendMessage(message);
+ }
+
+ setState(STATE_LOADING);
+ break;
+
+ case STATE_LOADING:
+ // The load_plugin_response message will kick us from here into STATE_RUNNING
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
+ case STATE_RUNNING:
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
case STATE_GOODBYE:
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown_plugin");
@@ -673,292 +673,292 @@ void LLPluginProcessParent::idle(void)
setState(STATE_EXITING);
break;
- case STATE_EXITING:
- if (! LLProcess::isRunning(mProcess))
- {
- setState(STATE_CLEANUP);
- }
- else if(pluginLockedUp())
- {
- LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;
- errorState();
- }
- break;
-
- case STATE_LAUNCH_FAILURE:
- if(mOwner != NULL)
- {
- mOwner->pluginLaunchFailed();
- }
- setState(STATE_CLEANUP);
- break;
-
- case STATE_ERROR:
- if(mOwner != NULL)
- {
- mOwner->pluginDied();
- }
- setState(STATE_CLEANUP);
- break;
-
- case STATE_CLEANUP:
- LLProcess::kill(mProcess);
- killSockets();
- setState(STATE_DONE);
+ case STATE_EXITING:
+ if (! LLProcess::isRunning(mProcess))
+ {
+ setState(STATE_CLEANUP);
+ }
+ else if(pluginLockedUp())
+ {
+ LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;
+ errorState();
+ }
+ break;
+
+ case STATE_LAUNCH_FAILURE:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginLaunchFailed();
+ }
+ setState(STATE_CLEANUP);
+ break;
+
+ case STATE_ERROR:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginDied();
+ }
+ setState(STATE_CLEANUP);
+ break;
+
+ case STATE_CLEANUP:
+ LLProcess::kill(mProcess);
+ killSockets();
+ setState(STATE_DONE);
dirtyPollSet();
clearProcessCreationThread();
- break;
-
- case STATE_DONE:
- // just sit here.
- break;
- }
-
- } while (idle_again);
+ break;
+
+ case STATE_DONE:
+ // just sit here.
+ break;
+ }
+
+ } while (idle_again);
}
bool LLPluginProcessParent::isLoading(void)
{
- bool result = false;
-
- if(mState <= STATE_LOADING)
- result = true;
-
- return result;
+ bool result = false;
+
+ if(mState <= STATE_LOADING)
+ result = true;
+
+ return result;
}
bool LLPluginProcessParent::isRunning(void)
{
- bool result = false;
-
- if(mState == STATE_RUNNING)
- result = true;
-
- return result;
+ bool result = false;
+
+ if(mState == STATE_RUNNING)
+ result = true;
+
+ return result;
}
bool LLPluginProcessParent::isDone(void)
{
- bool result = false;
-
- if(mState == STATE_DONE)
- result = true;
-
- return result;
+ bool result = false;
+
+ if(mState == STATE_DONE)
+ result = true;
+
+ return result;
}
void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send)
{
- if(force_send || (sleep_time != mSleepTime))
- {
- // Cache the time locally
- mSleepTime = sleep_time;
-
- if(canSendMessage())
- {
- // and send to the plugin.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time");
- message.setValueReal("time", mSleepTime);
- sendMessage(message);
- }
- else
- {
- // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later.
- }
- }
+ if(force_send || (sleep_time != mSleepTime))
+ {
+ // Cache the time locally
+ mSleepTime = sleep_time;
+
+ if(canSendMessage())
+ {
+ // and send to the plugin.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time");
+ message.setValueReal("time", mSleepTime);
+ sendMessage(message);
+ }
+ else
+ {
+ // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later.
+ }
+ }
}
void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)
{
- if(message.hasValue("blocking_response"))
- {
- mBlocked = false;
-
- // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked.
- mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
- }
-
- std::string buffer = message.generate();
- LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;
- writeMessageRaw(buffer);
-
- // Try to send message immediately.
- if(mMessagePipe)
- {
- mMessagePipe->pumpOutput();
- }
+ if(message.hasValue("blocking_response"))
+ {
+ mBlocked = false;
+
+ // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked.
+ mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
+ }
+
+ std::string buffer = message.generate();
+ LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;
+ writeMessageRaw(buffer);
+
+ // Try to send message immediately.
+ if(mMessagePipe)
+ {
+ mMessagePipe->pumpOutput();
+ }
}
-//virtual
+//virtual
void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe)
{
- bool update_pollset = false;
-
- if(mMessagePipe)
- {
- // Unsetting an existing message pipe -- remove from the pollset
- mPollFD.client_data = NULL;
-
- // pollset needs an update
- update_pollset = true;
- }
- if(message_pipe != NULL)
- {
- // Set up the apr_pollfd_t
- mPollFD.p = gAPRPoolp;
- mPollFD.desc_type = APR_POLL_SOCKET;
- mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
- mPollFD.rtnevents = 0;
- mPollFD.desc.s = mSocket->getSocket();
- mPollFD.client_data = (void*)this;
-
- // pollset needs an update
- update_pollset = true;
- }
-
- mMessagePipe = message_pipe;
-
- if(update_pollset)
- {
- dirtyPollSet();
- }
+ bool update_pollset = false;
+
+ if(mMessagePipe)
+ {
+ // Unsetting an existing message pipe -- remove from the pollset
+ mPollFD.client_data = NULL;
+
+ // pollset needs an update
+ update_pollset = true;
+ }
+ if(message_pipe != NULL)
+ {
+ // Set up the apr_pollfd_t
+ mPollFD.p = gAPRPoolp;
+ mPollFD.desc_type = APR_POLL_SOCKET;
+ mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
+ mPollFD.rtnevents = 0;
+ mPollFD.desc.s = mSocket->getSocket();
+ mPollFD.client_data = (void*)this;
+
+ // pollset needs an update
+ update_pollset = true;
+ }
+
+ mMessagePipe = message_pipe;
+
+ if(update_pollset)
+ {
+ dirtyPollSet();
+ }
}
-//static
+//static
void LLPluginProcessParent::dirtyPollSet()
{
- sPollsetNeedsRebuild = true;
-
- if(sReadThread)
- {
- LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL;
- sReadThread->unpause();
- }
+ sPollsetNeedsRebuild = true;
+
+ if(sReadThread)
+ {
+ LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL;
+ sReadThread->unpause();
+ }
}
void LLPluginProcessParent::updatePollset()
{
- if(!sInstancesMutex)
- {
- // No instances have been created yet. There's no work to do.
- return;
- }
-
+ if(!sInstancesMutex)
+ {
+ // No instances have been created yet. There's no work to do.
+ return;
+ }
+
LLCoros::LockType lock(*sInstancesMutex);
- if(sPollSet)
- {
- LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL;
- // delete the existing pollset.
- apr_pollset_destroy(sPollSet);
- sPollSet = NULL;
- }
-
+ if(sPollSet)
+ {
+ LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL;
+ // delete the existing pollset.
+ apr_pollset_destroy(sPollSet);
+ sPollSet = NULL;
+ }
+
mapInstances_t::iterator iter;
- int count = 0;
-
- // Count the number of instances that want to be in the pollset
- for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
- {
- (*iter).second->mPolledInput = false;
+ int count = 0;
+
+ // Count the number of instances that want to be in the pollset
+ for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
+ {
+ (*iter).second->mPolledInput = false;
if ((*iter).second->wantsPolling())
- {
- // This instance has a socket that needs to be polled.
- ++count;
- }
- }
-
- if(sUseReadThread && sReadThread && !sReadThread->isQuitting())
- {
- if(!sPollSet && (count > 0))
- {
+ {
+ // This instance has a socket that needs to be polled.
+ ++count;
+ }
+ }
+
+ if(sUseReadThread && sReadThread && !sReadThread->isQuitting())
+ {
+ if(!sPollSet && (count > 0))
+ {
#ifdef APR_POLLSET_NOCOPY
- // The pollset doesn't exist yet. Create it now.
- apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY);
- if(status != APR_SUCCESS)
- {
+ // The pollset doesn't exist yet. Create it now.
+ apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY);
+ if(status != APR_SUCCESS)
+ {
#endif // APR_POLLSET_NOCOPY
- LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
- sPollSet = NULL;
+ LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
+ sPollSet = NULL;
#ifdef APR_POLLSET_NOCOPY
- }
- else
- {
- LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL;
-
- // Pollset was created, add all instances to it.
- for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
- {
+ }
+ else
+ {
+ LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL;
+
+ // Pollset was created, add all instances to it.
+ for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
+ {
if ((*iter).second->wantsPolling())
- {
- status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD));
- if(status == APR_SUCCESS)
- {
- (*iter).second->mPolledInput = true;
- }
- else
- {
- LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL;
- }
- }
- }
- }
+ {
+ status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD));
+ if(status == APR_SUCCESS)
+ {
+ (*iter).second->mPolledInput = true;
+ }
+ else
+ {
+ LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL;
+ }
+ }
+ }
+ }
#endif // APR_POLLSET_NOCOPY
- }
- }
+ }
+ }
}
void LLPluginProcessParent::setUseReadThread(bool use_read_thread)
{
- if(sUseReadThread != use_read_thread)
- {
- sUseReadThread = use_read_thread;
-
- if(sUseReadThread)
- {
- if(!sReadThread)
- {
- // start up the read thread
- LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL;
-
- // make sure the pollset gets rebuilt.
- sPollsetNeedsRebuild = true;
-
- sReadThread = new LLPluginProcessParentPollThread;
- sReadThread->start();
- }
- }
- else
- {
- if(sReadThread)
- {
- // shut down the read thread
- LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL;
- delete sReadThread;
- sReadThread = NULL;
- }
- }
-
- }
+ if(sUseReadThread != use_read_thread)
+ {
+ sUseReadThread = use_read_thread;
+
+ if(sUseReadThread)
+ {
+ if(!sReadThread)
+ {
+ // start up the read thread
+ LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL;
+
+ // make sure the pollset gets rebuilt.
+ sPollsetNeedsRebuild = true;
+
+ sReadThread = new LLPluginProcessParentPollThread;
+ sReadThread->start();
+ }
+ }
+ else
+ {
+ if(sReadThread)
+ {
+ // shut down the read thread
+ LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL;
+ delete sReadThread;
+ sReadThread = NULL;
+ }
+ }
+
+ }
}
void LLPluginProcessParent::poll(F64 timeout)
{
- if(sPollsetNeedsRebuild || !sUseReadThread)
- {
- sPollsetNeedsRebuild = false;
- updatePollset();
- }
-
- if(sPollSet)
- {
- apr_status_t status;
- apr_int32_t count;
- const apr_pollfd_t *descriptors;
- status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors);
- if(status == APR_SUCCESS)
- {
- // One or more of the descriptors signalled. Call them.
+ if(sPollsetNeedsRebuild || !sUseReadThread)
+ {
+ sPollsetNeedsRebuild = false;
+ updatePollset();
+ }
+
+ if(sPollSet)
+ {
+ apr_status_t status;
+ apr_int32_t count;
+ const apr_pollfd_t *descriptors;
+ status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors);
+ if(status == APR_SUCCESS)
+ {
+ // One or more of the descriptors signalled. Call them.
for (int i = 0; i < count; i++)
{
void *thatId = descriptors[i].client_data;
@@ -980,23 +980,23 @@ void LLPluginProcessParent::poll(F64 timeout)
that->mIncomingQueueMutex.unlock();
}
- }
- }
- else if(APR_STATUS_IS_TIMEUP(status))
- {
- // timed out with no incoming data. Just return.
- }
- else if(status == EBADF)
- {
- // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed.
- // The pollset has been or will be recreated, so just return.
- LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL;
- }
- else if(status != APR_SUCCESS)
- {
- LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
- }
- }
+ }
+ }
+ else if(APR_STATUS_IS_TIMEUP(status))
+ {
+ // timed out with no incoming data. Just return.
+ }
+ else if(status == EBADF)
+ {
+ // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed.
+ // The pollset has been or will be recreated, so just return.
+ LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL;
+ }
+ else if(status != APR_SUCCESS)
+ {
+ LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
+ }
+ }
// Remove instances in the done state from the sInstances map.
mapInstances_t::iterator itClean = sInstances.begin();
@@ -1011,293 +1011,293 @@ void LLPluginProcessParent::poll(F64 timeout)
void LLPluginProcessParent::servicePoll()
{
- bool result = true;
-
- // poll signalled on this object's socket. Try to process incoming messages.
- if(mMessagePipe)
- {
- result = mMessagePipe->pumpInput(0.0f);
- }
-
- if(!result)
- {
- // If we got a read error on input, remove this pipe from the pollset
- apr_pollset_remove(sPollSet, &mPollFD);
-
- // and tell the code not to re-add it
- mPollFD.client_data = NULL;
- }
+ bool result = true;
+
+ // poll signalled on this object's socket. Try to process incoming messages.
+ if(mMessagePipe)
+ {
+ result = mMessagePipe->pumpInput(0.0f);
+ }
+
+ if(!result)
+ {
+ // If we got a read error on input, remove this pipe from the pollset
+ apr_pollset_remove(sPollSet, &mPollFD);
+
+ // and tell the code not to re-add it
+ mPollFD.client_data = NULL;
+ }
}
void LLPluginProcessParent::receiveMessageRaw(const std::string &message)
{
- LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL;
-
- LLPluginMessage parsed;
- if(LLSDParser::PARSE_FAILURE != parsed.parse(message))
- {
- if(parsed.hasValue("blocking_request"))
- {
- mBlocked = true;
- }
-
- if(mPolledInput)
- {
- // This is being called on the polling thread -- only do minimal processing/queueing.
- receiveMessageEarly(parsed);
- }
- else
- {
- // This is not being called on the polling thread -- do full message processing at this time.
- receiveMessage(parsed);
- }
- }
+ LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL;
+
+ LLPluginMessage parsed;
+ if(LLSDParser::PARSE_FAILURE != parsed.parse(message))
+ {
+ if(parsed.hasValue("blocking_request"))
+ {
+ mBlocked = true;
+ }
+
+ if(mPolledInput)
+ {
+ // This is being called on the polling thread -- only do minimal processing/queueing.
+ receiveMessageEarly(parsed);
+ }
+ else
+ {
+ // This is not being called on the polling thread -- do full message processing at this time.
+ receiveMessage(parsed);
+ }
+ }
}
void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message)
{
- // NOTE: this function will be called from the polling thread. It will be called with mIncomingQueueMutex _already locked_.
-
- bool handled = false;
-
- std::string message_class = message.getClass();
- if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
- {
- // no internal messages need to be handled early.
- }
- else
- {
- // Call out to the owner and see if they to reply
- // TODO: Should this only happen when blocked?
- if(mOwner != NULL)
- {
- handled = mOwner->receivePluginMessageEarly(message);
- }
- }
-
- if(!handled)
- {
- // any message that wasn't handled early needs to be queued.
- mIncomingQueue.push(message);
- }
+ // NOTE: this function will be called from the polling thread. It will be called with mIncomingQueueMutex _already locked_.
+
+ bool handled = false;
+
+ std::string message_class = message.getClass();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
+ {
+ // no internal messages need to be handled early.
+ }
+ else
+ {
+ // Call out to the owner and see if they to reply
+ // TODO: Should this only happen when blocked?
+ if(mOwner != NULL)
+ {
+ handled = mOwner->receivePluginMessageEarly(message);
+ }
+ }
+
+ if(!handled)
+ {
+ // any message that wasn't handled early needs to be queued.
+ mIncomingQueue.push(message);
+ }
}
void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
{
- std::string message_class = message.getClass();
- if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
- {
- // internal messages should be handled here
- std::string message_name = message.getName();
- if(message_name == "hello")
- {
- if(mState == STATE_CONNECTED)
- {
- // Plugin host has launched. Tell it which plugin to load.
- setState(STATE_HELLO);
- }
- else
- {
- LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
- errorState();
- }
-
- }
- else if(message_name == "load_plugin_response")
- {
- if(mState == STATE_LOADING)
- {
- // Plugin has been loaded.
-
- mPluginVersionString = message.getValue("plugin_version");
- LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;
-
- // Check which message classes/versions the plugin supports.
- // TODO: check against current versions
- // TODO: kill plugin on major mismatches?
- mMessageClassVersions = message.getValueLLSD("versions");
- LLSD::map_iterator iter;
- for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++)
- {
- LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
- }
-
- // Send initial sleep time
- llassert_always(mSleepTime != 0.f);
- setSleepTime(mSleepTime, true);
-
- setState(STATE_RUNNING);
- }
- else
- {
- LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
- errorState();
- }
- }
- else if(message_name == "heartbeat")
- {
- // this resets our timer.
- mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
-
- mCPUUsage = message.getValueReal("cpu_usage");
-
- LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL;
-
- }
- else if(message_name == "shm_add_response")
- {
- // Nothing to do here.
- }
- else if(message_name == "shm_remove_response")
- {
- std::string name = message.getValue("name");
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
-
- if(iter != mSharedMemoryRegions.end())
- {
- // destroy the shared memory region
- iter->second->destroy();
- delete iter->second;
- iter->second = NULL;
-
- // and remove it from our map
- mSharedMemoryRegions.erase(iter);
- }
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL;
- }
- }
- else
- {
- if(mOwner != NULL)
- {
- mOwner->receivePluginMessage(message);
- }
- }
+ std::string message_class = message.getClass();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
+ {
+ // internal messages should be handled here
+ std::string message_name = message.getName();
+ if(message_name == "hello")
+ {
+ if(mState == STATE_CONNECTED)
+ {
+ // Plugin host has launched. Tell it which plugin to load.
+ setState(STATE_HELLO);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
+ errorState();
+ }
+
+ }
+ else if(message_name == "load_plugin_response")
+ {
+ if(mState == STATE_LOADING)
+ {
+ // Plugin has been loaded.
+
+ mPluginVersionString = message.getValue("plugin_version");
+ LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;
+
+ // Check which message classes/versions the plugin supports.
+ // TODO: check against current versions
+ // TODO: kill plugin on major mismatches?
+ mMessageClassVersions = message.getValueLLSD("versions");
+ LLSD::map_iterator iter;
+ for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++)
+ {
+ LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
+ }
+
+ // Send initial sleep time
+ llassert_always(mSleepTime != 0.f);
+ setSleepTime(mSleepTime, true);
+
+ setState(STATE_RUNNING);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
+ errorState();
+ }
+ }
+ else if(message_name == "heartbeat")
+ {
+ // this resets our timer.
+ mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
+
+ mCPUUsage = message.getValueReal("cpu_usage");
+
+ LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL;
+
+ }
+ else if(message_name == "shm_add_response")
+ {
+ // Nothing to do here.
+ }
+ else if(message_name == "shm_remove_response")
+ {
+ std::string name = message.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // destroy the shared memory region
+ iter->second->destroy();
+ delete iter->second;
+ iter->second = NULL;
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+ }
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL;
+ }
+ }
+ else
+ {
+ if(mOwner != NULL)
+ {
+ mOwner->receivePluginMessage(message);
+ }
+ }
}
std::string LLPluginProcessParent::addSharedMemory(size_t size)
{
- std::string name;
-
- LLPluginSharedMemory *region = new LLPluginSharedMemory;
-
- // This is a new region
- if(region->create(size))
- {
- name = region->getName();
-
- mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add");
- message.setValue("name", name);
- message.setValueS32("size", (S32)size);
- sendMessage(message);
- }
- else
- {
- LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
-
- // Don't leak
- delete region;
- }
-
- return name;
+ std::string name;
+
+ LLPluginSharedMemory *region = new LLPluginSharedMemory;
+
+ // This is a new region
+ if(region->create(size))
+ {
+ name = region->getName();
+
+ mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add");
+ message.setValue("name", name);
+ message.setValueS32("size", (S32)size);
+ sendMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
+
+ // Don't leak
+ delete region;
+ }
+
+ return name;
}
void LLPluginProcessParent::removeSharedMemory(const std::string &name)
{
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
-
- if(iter != mSharedMemoryRegions.end())
- {
- // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove");
- message.setValue("name", name);
- sendMessage(message);
- }
- else
- {
- LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL;
- }
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL;
+ }
}
size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name)
{
- size_t result = 0;
-
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
- if(iter != mSharedMemoryRegions.end())
- {
- result = iter->second->getSize();
- }
-
- return result;
+ size_t result = 0;
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ result = iter->second->getSize();
+ }
+
+ return result;
}
void *LLPluginProcessParent::getSharedMemoryAddress(const std::string &name)
{
- void *result = NULL;
-
- sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
- if(iter != mSharedMemoryRegions.end())
- {
- result = iter->second->getMappedAddress();
- }
-
- return result;
+ void *result = NULL;
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ result = iter->second->getMappedAddress();
+ }
+
+ return result;
}
std::string LLPluginProcessParent::getMessageClassVersion(const std::string &message_class)
{
- std::string result;
-
- if(mMessageClassVersions.has(message_class))
- {
- result = mMessageClassVersions[message_class].asString();
- }
-
- return result;
+ std::string result;
+
+ if(mMessageClassVersions.has(message_class))
+ {
+ result = mMessageClassVersions[message_class].asString();
+ }
+
+ return result;
}
std::string LLPluginProcessParent::getPluginVersion(void)
{
- return mPluginVersionString;
+ return mPluginVersionString;
}
void LLPluginProcessParent::setState(EState state)
{
- LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
- mState = state;
+ LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
+ mState = state;
};
bool LLPluginProcessParent::pluginLockedUpOrQuit()
{
- bool result = false;
-
- if (! LLProcess::isRunning(mProcess))
- {
- LL_WARNS("Plugin") << "child exited" << LL_ENDL;
- result = true;
- }
- else if(pluginLockedUp())
- {
- LL_WARNS("Plugin") << "timeout" << LL_ENDL;
- result = true;
- }
-
- return result;
+ bool result = false;
+
+ if (! LLProcess::isRunning(mProcess))
+ {
+ LL_WARNS("Plugin") << "child exited" << LL_ENDL;
+ result = true;
+ }
+ else if(pluginLockedUp())
+ {
+ LL_WARNS("Plugin") << "timeout" << LL_ENDL;
+ result = true;
+ }
+
+ return result;
}
bool LLPluginProcessParent::pluginLockedUp()
{
- if(mDisableTimeout || mDebug || mBlocked)
- {
- // Never time out a plugin process in these cases.
- return false;
- }
-
- // If the timer is running and has expired, the plugin has locked up.
- return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());
+ if(mDisableTimeout || mDebug || mBlocked)
+ {
+ // Never time out a plugin process in these cases.
+ return false;
+ }
+
+ // If the timer is running and has expired, the plugin has locked up.
+ return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());
}
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 2f9dc921ea..d1c4933d81 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginprocessparent.h
* @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -43,182 +43,182 @@
#include "llsd.h"
#include "llevents.h"
-class LLPluginProcessParentOwner : public std::enable_shared_from_this < LLPluginProcessParentOwner >
+class LLPluginProcessParentOwner : public std::enable_shared_from_this < LLPluginProcessParentOwner >
{
public:
- virtual ~LLPluginProcessParentOwner();
- virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
- virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;};
- // This will only be called when the plugin has died unexpectedly
- virtual void pluginLaunchFailed() {};
- virtual void pluginDied() {};
+ virtual ~LLPluginProcessParentOwner();
+ virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
+ virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;};
+ // This will only be called when the plugin has died unexpectedly
+ virtual void pluginLaunchFailed() {};
+ virtual void pluginDied() {};
};
class LLPluginProcessParent : public LLPluginMessagePipeOwner
{
- LOG_CLASS(LLPluginProcessParent);
+ LOG_CLASS(LLPluginProcessParent);
LLPluginProcessParent(LLPluginProcessParentOwner *owner);
public:
typedef std::shared_ptr<LLPluginProcessParent> ptr_t;
- ~LLPluginProcessParent();
-
- void init(const std::string &launcher_filename,
- const std::string &plugin_dir,
- const std::string &plugin_filename,
- bool debug);
+ ~LLPluginProcessParent();
+
+ void init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
+ const std::string &plugin_filename,
+ bool debug);
// Creates a process
// returns true if process already exists or if created,
// false if failed to create
bool createPluginProcess();
- void idle(void);
-
- // returns true if the plugin is on its way to steady state
- bool isLoading(void);
+ void idle(void);
+
+ // returns true if the plugin is on its way to steady state
+ bool isLoading(void);
+
+ // returns true if the plugin is in the steady state (processing messages)
+ bool isRunning(void);
- // returns true if the plugin is in the steady state (processing messages)
- bool isRunning(void);
+ // returns true if the process has exited or we've had a fatal error
+ bool isDone(void);
- // returns true if the process has exited or we've had a fatal error
- bool isDone(void);
-
- // returns true if the process is currently waiting on a blocking request
- bool isBlocked(void) { return mBlocked; };
-
- void killSockets(void);
-
- // Go to the proper error state
- void errorState(void);
+ // returns true if the process is currently waiting on a blocking request
+ bool isBlocked(void) { return mBlocked; };
- void setSleepTime(F64 sleep_time, bool force_send = false);
- F64 getSleepTime(void) const { return mSleepTime; };
+ void killSockets(void);
- void sendMessage(const LLPluginMessage &message);
-
- void receiveMessage(const LLPluginMessage &message);
+ // Go to the proper error state
+ void errorState(void);
+
+ void setSleepTime(F64 sleep_time, bool force_send = false);
+ F64 getSleepTime(void) const { return mSleepTime; };
+
+ void sendMessage(const LLPluginMessage &message);
+
+ void receiveMessage(const LLPluginMessage &message);
static ptr_t create(LLPluginProcessParentOwner *owner);
void requestShutdown();
- // Inherited from LLPluginMessagePipeOwner
- /*virtual*/ void receiveMessageRaw(const std::string &message);
- /*virtual*/ void receiveMessageEarly(const LLPluginMessage &message);
- /*virtual*/ void setMessagePipe(LLPluginMessagePipe *message_pipe) ;
-
- // 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.
- std::string addSharedMemory(size_t size);
- // Negotiates for the removal of a shared memory segment. It is the caller's responsibility to ensure that nothing touches the memory
- // after this has been called, since the segment will be unmapped shortly thereafter.
- void removeSharedMemory(const std::string &name);
- size_t getSharedMemorySize(const std::string &name);
- void *getSharedMemoryAddress(const std::string &name);
-
- // Returns the version string the plugin indicated for the message class, or an empty string if that class wasn't in the list.
- std::string getMessageClassVersion(const std::string &message_class);
-
- std::string getPluginVersion(void);
-
- bool getDisableTimeout() { return mDisableTimeout; };
- void setDisableTimeout(bool disable) { mDisableTimeout = disable; };
-
- void setLaunchTimeout(F32 timeout) { mPluginLaunchTimeout = timeout; };
- void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; };
-
- F64 getCPUUsage() { return mCPUUsage; };
-
- static void poll(F64 timeout);
- static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); };
- static void setUseReadThread(bool use_read_thread);
- static bool getUseReadThread() { return sUseReadThread; };
+ // Inherited from LLPluginMessagePipeOwner
+ /*virtual*/ void receiveMessageRaw(const std::string &message);
+ /*virtual*/ void receiveMessageEarly(const LLPluginMessage &message);
+ /*virtual*/ void setMessagePipe(LLPluginMessagePipe *message_pipe) ;
+
+ // 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.
+ std::string addSharedMemory(size_t size);
+ // Negotiates for the removal of a shared memory segment. It is the caller's responsibility to ensure that nothing touches the memory
+ // after this has been called, since the segment will be unmapped shortly thereafter.
+ void removeSharedMemory(const std::string &name);
+ size_t getSharedMemorySize(const std::string &name);
+ void *getSharedMemoryAddress(const std::string &name);
+
+ // Returns the version string the plugin indicated for the message class, or an empty string if that class wasn't in the list.
+ std::string getMessageClassVersion(const std::string &message_class);
+
+ std::string getPluginVersion(void);
+
+ bool getDisableTimeout() { return mDisableTimeout; };
+ void setDisableTimeout(bool disable) { mDisableTimeout = disable; };
+
+ void setLaunchTimeout(F32 timeout) { mPluginLaunchTimeout = timeout; };
+ void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; };
+
+ F64 getCPUUsage() { return mCPUUsage; };
+
+ static void poll(F64 timeout);
+ static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); };
+ static void setUseReadThread(bool use_read_thread);
+ static bool getUseReadThread() { return sUseReadThread; };
static void shutdown();
private:
typedef std::map<void *, ptr_t> mapInstances_t;
- enum EState
- {
- STATE_UNINITIALIZED,
- STATE_INITIALIZED, // init() has been called
- STATE_LISTENING, // listening for incoming connection
- STATE_LAUNCHED, // process has been launched
- STATE_CONNECTED, // process has connected
- STATE_HELLO, // first message from the plugin process has been received
- STATE_LOADING, // process has been asked to load the plugin
- STATE_RUNNING, //
+ enum EState
+ {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZED, // init() has been called
+ STATE_LISTENING, // listening for incoming connection
+ STATE_LAUNCHED, // process has been launched
+ STATE_CONNECTED, // process has connected
+ STATE_HELLO, // first message from the plugin process has been received
+ STATE_LOADING, // process has been asked to load the plugin
+ STATE_RUNNING, //
STATE_GOODBYE,
- STATE_LAUNCH_FAILURE, // Failure before plugin loaded
- STATE_ERROR, // generic bailout state
- STATE_CLEANUP, // clean everything up
- STATE_EXITING, // Tried to kill process, waiting for it to exit
- STATE_DONE //
+ STATE_LAUNCH_FAILURE, // Failure before plugin loaded
+ STATE_ERROR, // generic bailout state
+ STATE_CLEANUP, // clean everything up
+ STATE_EXITING, // Tried to kill process, waiting for it to exit
+ STATE_DONE //
- };
- EState mState;
- void setState(EState state);
+ };
+ EState mState;
+ void setState(EState state);
bool wantsPolling() const;
void removeFromProcessing();
- bool pluginLockedUp();
- bool pluginLockedUpOrQuit();
+ bool pluginLockedUp();
+ bool pluginLockedUpOrQuit();
- bool accept();
+ bool accept();
void clearProcessCreationThread();
- LLSocket::ptr_t mListenSocket;
- LLSocket::ptr_t mSocket;
- U32 mBoundPort;
-
- LLProcess::Params mProcessParams;
- LLProcessPtr mProcess;
- LLThread *pProcessCreationThread;
-
- std::string mPluginFile;
- std::string mPluginDir;
-
- LLPluginProcessParentOwner *mOwner;
-
- typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
- sharedMemoryRegionsType mSharedMemoryRegions;
-
- LLSD mMessageClassVersions;
- std::string mPluginVersionString;
-
- LLTimer mHeartbeat;
- F64 mSleepTime;
- F64 mCPUUsage;
-
- bool mDisableTimeout;
- bool mDebug;
- bool mBlocked;
- bool mPolledInput;
-
- LLProcessPtr mDebugger;
-
- F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch.
- F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
-
- static bool sUseReadThread;
- apr_pollfd_t mPollFD;
- static apr_pollset_t *sPollSet;
- static bool sPollsetNeedsRebuild;
- static LLCoros::Mutex *sInstancesMutex;
+ LLSocket::ptr_t mListenSocket;
+ LLSocket::ptr_t mSocket;
+ U32 mBoundPort;
+
+ LLProcess::Params mProcessParams;
+ LLProcessPtr mProcess;
+ LLThread *pProcessCreationThread;
+
+ std::string mPluginFile;
+ std::string mPluginDir;
+
+ LLPluginProcessParentOwner *mOwner;
+
+ typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
+ sharedMemoryRegionsType mSharedMemoryRegions;
+
+ LLSD mMessageClassVersions;
+ std::string mPluginVersionString;
+
+ LLTimer mHeartbeat;
+ F64 mSleepTime;
+ F64 mCPUUsage;
+
+ bool mDisableTimeout;
+ bool mDebug;
+ bool mBlocked;
+ bool mPolledInput;
+
+ LLProcessPtr mDebugger;
+
+ F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch.
+ F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
+
+ static bool sUseReadThread;
+ apr_pollfd_t mPollFD;
+ static apr_pollset_t *sPollSet;
+ static bool sPollsetNeedsRebuild;
+ static LLCoros::Mutex *sInstancesMutex;
static mapInstances_t sInstances;
- static void dirtyPollSet();
- static void updatePollset();
- void servicePoll();
- static LLThread *sReadThread;
+ static void dirtyPollSet();
+ static void updatePollset();
+ void servicePoll();
+ static LLThread *sReadThread;
LLTempBoundListener mPolling;
bool pollTick();
- LLMutex mIncomingQueueMutex;
- std::queue<LLPluginMessage> mIncomingQueue;
+ LLMutex mIncomingQueueMutex;
+ std::queue<LLPluginMessage> mIncomingQueue;
};
#endif // LL_LLPLUGINPROCESSPARENT_H
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp
index 3fc9cbd973..a10d251069 100644
--- a/indra/llplugin/llpluginsharedmemory.cpp
+++ b/indra/llplugin/llpluginsharedmemory.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpluginsharedmemory.cpp
* LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
*
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -31,44 +31,44 @@
#include "llpluginsharedmemory.h"
// on Mac and Linux, we use the native shm_open/mmap interface by using
-// #define USE_SHM_OPEN_SHARED_MEMORY 1
+// #define USE_SHM_OPEN_SHARED_MEMORY 1
// in the appropriate sections below.
// For Windows, use:
-// #define USE_WIN32_SHARED_MEMORY 1
+// #define USE_WIN32_SHARED_MEMORY 1
// If we ever want to fall back to the apr implementation for a platform, use:
-// #define USE_APR_SHARED_MEMORY 1
+// #define USE_APR_SHARED_MEMORY 1
#if LL_WINDOWS
-// #define USE_APR_SHARED_MEMORY 1
- #define USE_WIN32_SHARED_MEMORY 1
+// #define USE_APR_SHARED_MEMORY 1
+ #define USE_WIN32_SHARED_MEMORY 1
#elif LL_DARWIN
- #define USE_SHM_OPEN_SHARED_MEMORY 1
+ #define USE_SHM_OPEN_SHARED_MEMORY 1
#elif LL_LINUX
- #define USE_SHM_OPEN_SHARED_MEMORY 1
+ #define USE_SHM_OPEN_SHARED_MEMORY 1
#endif
// FIXME: This path thing is evil and unacceptable.
#if LL_WINDOWS
- #define APR_SHARED_MEMORY_PREFIX_STRING "C:\\LLPlugin_"
- // Apparnently using the "Global\\" prefix here only works from administrative accounts under Vista.
- // Other options I've seen referenced are "Local\\" and "Session\\".
- #define WIN32_SHARED_MEMORY_PREFIX_STRING "Local\\LL_"
+ #define APR_SHARED_MEMORY_PREFIX_STRING "C:\\LLPlugin_"
+ // Apparnently using the "Global\\" prefix here only works from administrative accounts under Vista.
+ // Other options I've seen referenced are "Local\\" and "Session\\".
+ #define WIN32_SHARED_MEMORY_PREFIX_STRING "Local\\LL_"
#else
- // mac and linux
- #define APR_SHARED_MEMORY_PREFIX_STRING "/tmp/LLPlugin_"
- #define SHM_OPEN_SHARED_MEMORY_PREFIX_STRING "/LL"
+ // mac and linux
+ #define APR_SHARED_MEMORY_PREFIX_STRING "/tmp/LLPlugin_"
+ #define SHM_OPEN_SHARED_MEMORY_PREFIX_STRING "/LL"
#endif
-#if USE_APR_SHARED_MEMORY
- #include "llapr.h"
- #include "apr_shm.h"
+#if USE_APR_SHARED_MEMORY
+ #include "llapr.h"
+ #include "apr_shm.h"
#elif USE_SHM_OPEN_SHARED_MEMORY
- #include <sys/fcntl.h>
- #include <sys/mman.h>
- #include <errno.h>
+ #include <sys/fcntl.h>
+ #include <sys/mman.h>
+ #include <errno.h>
#elif USE_WIN32_SHARED_MEMORY
#include <windows.h>
#endif // USE_APR_SHARED_MEMORY
@@ -78,17 +78,17 @@ int LLPluginSharedMemory::sSegmentNumber = 0;
std::string LLPluginSharedMemory::createName(void)
{
- std::stringstream newname;
+ std::stringstream newname;
#if LL_WINDOWS
- newname << GetCurrentProcessId();
+ newname << GetCurrentProcessId();
#else // LL_WINDOWS
- newname << getpid();
+ newname << getpid();
#endif // LL_WINDOWS
-
- newname << "_" << sSegmentNumber++;
-
- return newname.str();
+
+ newname << "_" << sSegmentNumber++;
+
+ return newname.str();
}
/**
@@ -98,15 +98,15 @@ std::string LLPluginSharedMemory::createName(void)
class LLPluginSharedMemoryPlatformImpl
{
public:
- LLPluginSharedMemoryPlatformImpl();
- ~LLPluginSharedMemoryPlatformImpl();
-
+ LLPluginSharedMemoryPlatformImpl();
+ ~LLPluginSharedMemoryPlatformImpl();
+
#if USE_APR_SHARED_MEMORY
- apr_shm_t* mAprSharedMemory;
+ apr_shm_t* mAprSharedMemory;
#elif USE_SHM_OPEN_SHARED_MEMORY
- int mSharedMemoryFD;
+ int mSharedMemoryFD;
#elif USE_WIN32_SHARED_MEMORY
- HANDLE mMapFile;
+ HANDLE mMapFile;
#endif
};
@@ -116,11 +116,11 @@ public:
*/
LLPluginSharedMemory::LLPluginSharedMemory()
{
- mSize = 0;
- mMappedAddress = NULL;
- mNeedsDestroy = false;
+ mSize = 0;
+ mMappedAddress = NULL;
+ mNeedsDestroy = false;
- mImpl = new LLPluginSharedMemoryPlatformImpl;
+ mImpl = new LLPluginSharedMemoryPlatformImpl;
}
/**
@@ -128,14 +128,14 @@ LLPluginSharedMemory::LLPluginSharedMemory()
*/
LLPluginSharedMemory::~LLPluginSharedMemory()
{
- if(mNeedsDestroy)
- destroy();
- else
- detach();
-
- unlink();
-
- delete mImpl;
+ if(mNeedsDestroy)
+ destroy();
+ else
+ detach();
+
+ unlink();
+
+ delete mImpl;
}
#if USE_APR_SHARED_MEMORY
@@ -143,106 +143,106 @@ LLPluginSharedMemory::~LLPluginSharedMemory()
LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
{
- mAprSharedMemory = NULL;
+ mAprSharedMemory = NULL;
}
LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
{
-
+
}
bool LLPluginSharedMemory::map(void)
{
- mMappedAddress = apr_shm_baseaddr_get(mImpl->mAprSharedMemory);
- if(mMappedAddress == NULL)
- {
- return false;
- }
-
- return true;
+ mMappedAddress = apr_shm_baseaddr_get(mImpl->mAprSharedMemory);
+ if(mMappedAddress == NULL)
+ {
+ return false;
+ }
+
+ return true;
}
bool LLPluginSharedMemory::unmap(void)
{
- // This is a no-op under apr.
- return true;
+ // This is a no-op under apr.
+ return true;
}
bool LLPluginSharedMemory::close(void)
{
- // This is a no-op under apr.
- return true;
+ // This is a no-op under apr.
+ return true;
}
bool LLPluginSharedMemory::unlink(void)
{
- // This is a no-op under apr.
- return true;
+ // This is a no-op under apr.
+ return true;
}
bool LLPluginSharedMemory::create(size_t size)
{
- mName = APR_SHARED_MEMORY_PREFIX_STRING;
- mName += createName();
- mSize = size;
-
- apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp );
-
- if(ll_apr_warn_status(status))
- {
- return false;
- }
+ mName = APR_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp );
+
+ if(ll_apr_warn_status(status))
+ {
+ return false;
+ }
- mNeedsDestroy = true;
-
- return map();
+ mNeedsDestroy = true;
+
+ return map();
}
bool LLPluginSharedMemory::destroy(void)
{
- if(mImpl->mAprSharedMemory)
- {
- apr_status_t status = apr_shm_destroy(mImpl->mAprSharedMemory);
- if(ll_apr_warn_status(status))
- {
- // TODO: Is this a fatal error? I think not...
- }
- mImpl->mAprSharedMemory = NULL;
- }
-
- return true;
+ if(mImpl->mAprSharedMemory)
+ {
+ apr_status_t status = apr_shm_destroy(mImpl->mAprSharedMemory);
+ if(ll_apr_warn_status(status))
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+ mImpl->mAprSharedMemory = NULL;
+ }
+
+ return true;
}
bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
{
- mName = name;
- mSize = size;
-
- apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp );
-
- if(ll_apr_warn_status(status))
- {
- return false;
- }
+ mName = name;
+ mSize = size;
+
+ apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp );
- return map();
+ if(ll_apr_warn_status(status))
+ {
+ return false;
+ }
+
+ return map();
}
bool LLPluginSharedMemory::detach(void)
{
- if(mImpl->mAprSharedMemory)
- {
- apr_status_t status = apr_shm_detach(mImpl->mAprSharedMemory);
- if(ll_apr_warn_status(status))
- {
- // TODO: Is this a fatal error? I think not...
- }
- mImpl->mAprSharedMemory = NULL;
- }
-
- return true;
+ if(mImpl->mAprSharedMemory)
+ {
+ apr_status_t status = apr_shm_detach(mImpl->mAprSharedMemory);
+ if(ll_apr_warn_status(status))
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+ mImpl->mAprSharedMemory = NULL;
+ }
+
+ return true;
}
@@ -251,7 +251,7 @@ bool LLPluginSharedMemory::detach(void)
LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
{
- mSharedMemoryFD = -1;
+ mSharedMemoryFD = -1;
}
LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
@@ -260,119 +260,119 @@ LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
bool LLPluginSharedMemory::map(void)
{
- mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0);
- if(mMappedAddress == NULL)
- {
- return false;
- }
-
- LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+ mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0);
+ if(mMappedAddress == NULL)
+ {
+ return false;
+ }
- return true;
+ LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+
+ return true;
}
bool LLPluginSharedMemory::unmap(void)
{
- if(mMappedAddress != NULL)
- {
- LL_DEBUGS("Plugin") << "calling munmap(" << mMappedAddress << ", " << mSize << ")" << LL_ENDL;
- if(::munmap(mMappedAddress, mSize) == -1)
- {
- // TODO: Is this a fatal error? I think not...
- }
-
- mMappedAddress = NULL;
- }
+ if(mMappedAddress != NULL)
+ {
+ LL_DEBUGS("Plugin") << "calling munmap(" << mMappedAddress << ", " << mSize << ")" << LL_ENDL;
+ if(::munmap(mMappedAddress, mSize) == -1)
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+
+ mMappedAddress = NULL;
+ }
- return true;
+ return true;
}
bool LLPluginSharedMemory::close(void)
{
- if(mImpl->mSharedMemoryFD != -1)
- {
- LL_DEBUGS("Plugin") << "calling close(" << mImpl->mSharedMemoryFD << ")" << LL_ENDL;
- if(::close(mImpl->mSharedMemoryFD) == -1)
- {
- // TODO: Is this a fatal error? I think not...
- }
-
- mImpl->mSharedMemoryFD = -1;
- }
- return true;
+ if(mImpl->mSharedMemoryFD != -1)
+ {
+ LL_DEBUGS("Plugin") << "calling close(" << mImpl->mSharedMemoryFD << ")" << LL_ENDL;
+ if(::close(mImpl->mSharedMemoryFD) == -1)
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+
+ mImpl->mSharedMemoryFD = -1;
+ }
+ return true;
}
bool LLPluginSharedMemory::unlink(void)
{
- if(!mName.empty())
- {
- if(::shm_unlink(mName.c_str()) == -1)
- {
- return false;
- }
- }
-
- return true;
+ if(!mName.empty())
+ {
+ if(::shm_unlink(mName.c_str()) == -1)
+ {
+ return false;
+ }
+ }
+
+ return true;
}
bool LLPluginSharedMemory::create(size_t size)
{
- mName = SHM_OPEN_SHARED_MEMORY_PREFIX_STRING;
- mName += createName();
- mSize = size;
-
- // Preemptive unlink, just in case something didn't get cleaned up.
- unlink();
-
- mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
- if(mImpl->mSharedMemoryFD == -1)
- {
- return false;
- }
-
- mNeedsDestroy = true;
-
- if(::ftruncate(mImpl->mSharedMemoryFD, mSize) == -1)
- {
- return false;
- }
-
-
- return map();
+ mName = SHM_OPEN_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ // Preemptive unlink, just in case something didn't get cleaned up.
+ unlink();
+
+ mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+ if(mImpl->mSharedMemoryFD == -1)
+ {
+ return false;
+ }
+
+ mNeedsDestroy = true;
+
+ if(::ftruncate(mImpl->mSharedMemoryFD, mSize) == -1)
+ {
+ return false;
+ }
+
+
+ return map();
}
bool LLPluginSharedMemory::destroy(void)
{
- unmap();
- close();
-
- return true;
+ unmap();
+ close();
+
+ return true;
}
bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
{
- mName = name;
- mSize = size;
+ mName = name;
+ mSize = size;
+
+ mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
+ if(mImpl->mSharedMemoryFD == -1)
+ {
+ return false;
+ }
+
+ // unlink here so the segment will be cleaned up automatically after the last close.
+ unlink();
- mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
- if(mImpl->mSharedMemoryFD == -1)
- {
- return false;
- }
-
- // unlink here so the segment will be cleaned up automatically after the last close.
- unlink();
-
- return map();
+ return map();
}
bool LLPluginSharedMemory::detach(void)
{
- unmap();
- close();
- return true;
+ unmap();
+ close();
+ return true;
}
#elif USE_WIN32_SHARED_MEMORY
@@ -382,119 +382,119 @@ bool LLPluginSharedMemory::detach(void)
LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
{
- mMapFile = NULL;
+ mMapFile = NULL;
}
LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
{
-
+
}
bool LLPluginSharedMemory::map(void)
{
- mMappedAddress = MapViewOfFile(
- mImpl->mMapFile, // handle to map object
- FILE_MAP_ALL_ACCESS, // read/write permission
- 0,
- 0,
- mSize);
-
- if(mMappedAddress == NULL)
- {
- LL_WARNS("Plugin") << "MapViewOfFile failed: " << GetLastError() << LL_ENDL;
- return false;
- }
-
- LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+ mMappedAddress = MapViewOfFile(
+ mImpl->mMapFile, // handle to map object
+ FILE_MAP_ALL_ACCESS, // read/write permission
+ 0,
+ 0,
+ mSize);
+
+ if(mMappedAddress == NULL)
+ {
+ LL_WARNS("Plugin") << "MapViewOfFile failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
- return true;
+ LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+
+ return true;
}
bool LLPluginSharedMemory::unmap(void)
{
- if(mMappedAddress != NULL)
- {
- UnmapViewOfFile(mMappedAddress);
- mMappedAddress = NULL;
- }
+ if(mMappedAddress != NULL)
+ {
+ UnmapViewOfFile(mMappedAddress);
+ mMappedAddress = NULL;
+ }
- return true;
+ return true;
}
bool LLPluginSharedMemory::close(void)
{
- if(mImpl->mMapFile != NULL)
- {
- CloseHandle(mImpl->mMapFile);
- mImpl->mMapFile = NULL;
- }
-
- return true;
+ if(mImpl->mMapFile != NULL)
+ {
+ CloseHandle(mImpl->mMapFile);
+ mImpl->mMapFile = NULL;
+ }
+
+ return true;
}
bool LLPluginSharedMemory::unlink(void)
{
- // This is a no-op on Windows.
- return true;
+ // This is a no-op on Windows.
+ return true;
}
bool LLPluginSharedMemory::create(size_t size)
{
- mName = WIN32_SHARED_MEMORY_PREFIX_STRING;
- mName += createName();
- mSize = size;
+ mName = WIN32_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ mImpl->mMapFile = CreateFileMappingA(
+ INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max. object size
+ mSize, // buffer size
+ mName.c_str()); // name of mapping object
- mImpl->mMapFile = CreateFileMappingA(
- INVALID_HANDLE_VALUE, // use paging file
- NULL, // default security
- PAGE_READWRITE, // read/write access
- 0, // max. object size
- mSize, // buffer size
- mName.c_str()); // name of mapping object
+ if(mImpl->mMapFile == NULL)
+ {
+ LL_WARNS("Plugin") << "CreateFileMapping failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
- if(mImpl->mMapFile == NULL)
- {
- LL_WARNS("Plugin") << "CreateFileMapping failed: " << GetLastError() << LL_ENDL;
- return false;
- }
+ mNeedsDestroy = true;
- mNeedsDestroy = true;
-
- return map();
+ return map();
}
bool LLPluginSharedMemory::destroy(void)
{
- unmap();
- close();
- return true;
+ unmap();
+ close();
+ return true;
}
bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
{
- mName = name;
- mSize = size;
+ mName = name;
+ mSize = size;
+
+ mImpl->mMapFile = OpenFileMappingA(
+ FILE_MAP_ALL_ACCESS, // read/write access
+ false, // do not inherit the name
+ mName.c_str()); // name of mapping object
+
+ if(mImpl->mMapFile == NULL)
+ {
+ LL_WARNS("Plugin") << "OpenFileMapping failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
- mImpl->mMapFile = OpenFileMappingA(
- FILE_MAP_ALL_ACCESS, // read/write access
- false, // do not inherit the name
- mName.c_str()); // name of mapping object
-
- if(mImpl->mMapFile == NULL)
- {
- LL_WARNS("Plugin") << "OpenFileMapping failed: " << GetLastError() << LL_ENDL;
- return false;
- }
-
- return map();
+ return map();
}
bool LLPluginSharedMemory::detach(void)
{
- unmap();
- close();
- return true;
+ unmap();
+ close();
+ return true;
}
diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h
index c6cd49cabb..a0aa885a58 100644
--- a/indra/llplugin/llpluginsharedmemory.h
+++ b/indra/llplugin/llpluginsharedmemory.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpluginsharedmemory.h
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
@@ -36,15 +36,15 @@ class LLPluginSharedMemoryPlatformImpl;
*/
class LLPluginSharedMemory
{
- LOG_CLASS(LLPluginSharedMemory);
+ LOG_CLASS(LLPluginSharedMemory);
public:
- LLPluginSharedMemory();
- ~LLPluginSharedMemory();
-
- // Parent will use create/destroy, child will use attach/detach.
- // Message transactions will ensure child attaches after parent creates and detaches before parent destroys.
-
- /**
+ LLPluginSharedMemory();
+ ~LLPluginSharedMemory();
+
+ // Parent will use create/destroy, child will use attach/detach.
+ // Message transactions will ensure child attaches after parent creates and detaches before parent destroys.
+
+ /**
* Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent.
* Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
*
@@ -52,16 +52,16 @@ public:
*
* @return False for failure, true for success.
*/
- bool create(size_t size);
- /**
+ bool create(size_t size);
+ /**
* Destroys a shared memory segment. Used by parent.
* Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
*
* @return True. TODO:DOC - always returns true. Is this the intended behavior?
*/
- bool destroy(void);
-
- /**
+ bool destroy(void);
+
+ /**
* Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()?
*
* @param[in] name Name to attach to memory segment
@@ -69,55 +69,55 @@ public:
*
* @return False on failure, true otherwise.
*/
- bool attach(const std::string &name, size_t size);
- /**
+ bool attach(const std::string &name, size_t size);
+ /**
* Detaches shared memory segment.
*
* @return False on failure, true otherwise.
*/
- bool detach(void);
+ bool detach(void);
- /**
+ /**
* Checks if shared memory is mapped to a non-null address.
*
* @return True if memory address is non-null, false otherwise.
*/
- bool isMapped(void) const { return (mMappedAddress != NULL); };
- /**
+ bool isMapped(void) const { return (mMappedAddress != NULL); };
+ /**
* Get pointer to shared memory.
*
* @return Pointer to shared memory.
*/
- void *getMappedAddress(void) const { return mMappedAddress; };
- /**
+ void *getMappedAddress(void) const { return mMappedAddress; };
+ /**
* Get size of shared memory.
*
* @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit?
*/
- size_t getSize(void) const { return mSize; };
- /**
+ size_t getSize(void) const { return mSize; };
+ /**
* Get name of shared memory.
*
* @return Name of shared memory.
*/
- std::string getName() const { return mName; };
-
+ std::string getName() const { return mName; };
+
private:
- bool map(void);
- bool unmap(void);
- bool close(void);
- bool unlink(void);
-
- std::string mName;
- size_t mSize;
- void *mMappedAddress;
- bool mNeedsDestroy;
-
- LLPluginSharedMemoryPlatformImpl *mImpl;
-
- static int sSegmentNumber;
- static std::string createName();
-
+ bool map(void);
+ bool unmap(void);
+ bool close(void);
+ bool unlink(void);
+
+ std::string mName;
+ size_t mSize;
+ void *mMappedAddress;
+ bool mNeedsDestroy;
+
+ LLPluginSharedMemoryPlatformImpl *mImpl;
+
+ static int sSegmentNumber;
+ static std::string createName();
+
};
diff --git a/indra/llplugin/slplugin/slplugin-objc.h b/indra/llplugin/slplugin/slplugin-objc.h
index af0ebe1af2..b2e5c16ff0 100644
--- a/indra/llplugin/slplugin/slplugin-objc.h
+++ b/indra/llplugin/slplugin/slplugin-objc.h
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
@@ -37,7 +37,7 @@ class NSWindow;
class LLCocoaPlugin
{
-public:
+public:
LLCocoaPlugin();
void setupCocoa();
void createAutoReleasePool();
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index bf5e223181..81a27cf2e5 100644
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
@@ -43,87 +43,87 @@ using namespace std;
#if LL_DARWIN
- #include "slplugin-objc.h"
+ #include "slplugin-objc.h"
#endif
#if LL_DARWIN || LL_LINUX
- #include <signal.h>
+ #include <signal.h>
#endif
/*
- On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly or LSUIElement flag in the Info.plist.
+ On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly or LSUIElement flag in the Info.plist.
+
+ Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags:
- Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags:
+ -sectcreate __TEXT __info_plist /path/to/slplugin_info.plist
- -sectcreate __TEXT __info_plist /path/to/slplugin_info.plist
+ which means adding this to the gcc flags:
- which means adding this to the gcc flags:
+ -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist
- -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist
-
- Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity.
+ Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity.
*/
#if LL_DARWIN || LL_LINUX
// Signal handlers to make crashes not show an OS dialog...
static void crash_handler(int sig)
{
- // Just exit cleanly.
- // TODO: add our own crash reporting
- _exit(1);
+ // Just exit cleanly.
+ // TODO: add our own crash reporting
+ _exit(1);
}
#endif
#if LL_WINDOWS
#include <windows.h>
////////////////////////////////////////////////////////////////////////////////
-// Our exception handler - will probably just exit and the host application
-// will miss the heartbeat and log the error in the usual fashion.
+// Our exception handler - will probably just exit and the host application
+// will miss the heartbeat and log the error in the usual fashion.
LONG WINAPI myWin32ExceptionHandler( struct _EXCEPTION_POINTERS* exception_infop )
{
- //std::cerr << "This plugin (" << __FILE__ << ") - ";
- //std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl;
+ //std::cerr << "This plugin (" << __FILE__ << ") - ";
+ //std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl;
- // TODO: replace exception handler before we exit?
- return EXCEPTION_EXECUTE_HANDLER;
+ // TODO: replace exception handler before we exit?
+ return EXCEPTION_EXECUTE_HANDLER;
}
////////////////////////////////////////////////////////////////////////////////
-// Hook our exception handler and replace the system one
+// Hook our exception handler and replace the system one
void initExceptionHandler()
{
- LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
+ LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
- // save old exception handler in case we need to restore it at the end
- prev_filter = SetUnhandledExceptionFilter( myWin32ExceptionHandler );
+ // save old exception handler in case we need to restore it at the end
+ prev_filter = SetUnhandledExceptionFilter( myWin32ExceptionHandler );
}
bool checkExceptionHandler()
{
- bool ok = true;
- LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
- prev_filter = SetUnhandledExceptionFilter(myWin32ExceptionHandler);
-
- if (prev_filter != myWin32ExceptionHandler)
- {
- LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with " << prev_filter << "!" << LL_ENDL;
- ok = false;
- }
-
- if (prev_filter == nullptr)
- {
- ok = false;
- if (nullptr == myWin32ExceptionHandler)
- {
- LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL;
- }
- else
- {
- LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with NULL!" << LL_ENDL;
- }
- }
-
- return ok;
+ bool ok = true;
+ LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
+ prev_filter = SetUnhandledExceptionFilter(myWin32ExceptionHandler);
+
+ if (prev_filter != myWin32ExceptionHandler)
+ {
+ LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with " << prev_filter << "!" << LL_ENDL;
+ ok = false;
+ }
+
+ if (prev_filter == nullptr)
+ {
+ ok = false;
+ if (nullptr == myWin32ExceptionHandler)
+ {
+ LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with NULL!" << LL_ENDL;
+ }
+ }
+
+ return ok;
}
#endif
@@ -137,132 +137,132 @@ int main(int argc, char **argv)
#endif
{
- ll_init_apr();
+ ll_init_apr();
- // Set up llerror logging
- {
- LLError::initForApplication(".",".");
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
-// LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
-// LLError::logToFile("slplugin.log");
- }
+ // Set up llerror logging
+ {
+ LLError::initForApplication(".",".");
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+// LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
+// LLError::logToFile("slplugin.log");
+ }
#if LL_WINDOWS
- if( strlen( lpCmdLine ) == 0 )
- {
- LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL;
- };
-
- U32 port = 0;
- if(!LLStringUtil::convertToU32(lpCmdLine, port))
- {
- LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
- };
-
- // Insert our exception handler into the system so this plugin doesn't
- // display a crash message if something bad happens. The host app will
- // see the missing heartbeat and log appropriately.
- initExceptionHandler();
+ if( strlen( lpCmdLine ) == 0 )
+ {
+ LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL;
+ };
+
+ U32 port = 0;
+ if(!LLStringUtil::convertToU32(lpCmdLine, port))
+ {
+ LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
+ };
+
+ // Insert our exception handler into the system so this plugin doesn't
+ // display a crash message if something bad happens. The host app will
+ // see the missing heartbeat and log appropriately.
+ initExceptionHandler();
#elif LL_DARWIN || LL_LINUX
- if(argc < 2)
- {
- LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL;
- }
-
- U32 port = 0;
- if(!LLStringUtil::convertToU32(argv[1], port))
- {
- LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
- }
-
- // Catch signals that most kinds of crashes will generate, and exit cleanly so the system crash dialog isn't shown.
- signal(SIGILL, &crash_handler); // illegal instruction
- signal(SIGFPE, &crash_handler); // floating-point exception
- signal(SIGBUS, &crash_handler); // bus error
- signal(SIGSEGV, &crash_handler); // segmentation violation
- signal(SIGSYS, &crash_handler); // non-existent system call invoked
+ if(argc < 2)
+ {
+ LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL;
+ }
+
+ U32 port = 0;
+ if(!LLStringUtil::convertToU32(argv[1], port))
+ {
+ LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
+ }
+
+ // Catch signals that most kinds of crashes will generate, and exit cleanly so the system crash dialog isn't shown.
+ signal(SIGILL, &crash_handler); // illegal instruction
+ signal(SIGFPE, &crash_handler); // floating-point exception
+ signal(SIGBUS, &crash_handler); // bus error
+ signal(SIGSEGV, &crash_handler); // segmentation violation
+ signal(SIGSYS, &crash_handler); // non-existent system call invoked
#endif
# if LL_DARWIN
- signal(SIGEMT, &crash_handler); // emulate instruction executed
+ signal(SIGEMT, &crash_handler); // emulate instruction executed
LLCocoaPlugin cocoa_interface;
- cocoa_interface.setupCocoa();
- cocoa_interface.createAutoReleasePool();
+ cocoa_interface.setupCocoa();
+ cocoa_interface.createAutoReleasePool();
#endif //LL_DARWIN
- LLPluginProcessChild *plugin = new LLPluginProcessChild();
+ LLPluginProcessChild *plugin = new LLPluginProcessChild();
- plugin->init(port);
+ plugin->init(port);
#if LL_DARWIN
cocoa_interface.deleteAutoReleasePool();
#endif
- LLTimer timer;
- timer.start();
+ LLTimer timer;
+ timer.start();
#if LL_WINDOWS
- checkExceptionHandler();
+ checkExceptionHandler();
#endif
#if LL_DARWIN
-
- // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground.
- // Use this to track the current frontmost window and bring this process to the front if it changes.
+
+ // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground.
+ // Use this to track the current frontmost window and bring this process to the front if it changes.
// cocoa_interface.mEventTarget = GetEventDispatcherTarget();
#endif
- while(!plugin->isDone())
- {
+ while(!plugin->isDone())
+ {
#if LL_DARWIN
- cocoa_interface.createAutoReleasePool();
+ cocoa_interface.createAutoReleasePool();
#endif
- timer.reset();
- plugin->idle();
+ timer.reset();
+ plugin->idle();
#if LL_DARWIN
- {
- cocoa_interface.processEvents();
+ {
+ cocoa_interface.processEvents();
}
#endif
- F64 elapsed = timer.getElapsedTimeF64();
- F64 remaining = plugin->getSleepTime() - elapsed;
-
- if(remaining <= 0.0)
- {
- // We've already used our full allotment.
-// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, not sleeping" << LL_ENDL;
-
- // Still need to service the network...
- plugin->pump();
- }
- else
- {
-
-// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL;
-// timer.reset();
-
- // This also services the network as needed.
- plugin->sleep(remaining);
-
-// LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL;
- }
-
-
+ F64 elapsed = timer.getElapsedTimeF64();
+ F64 remaining = plugin->getSleepTime() - elapsed;
+
+ if(remaining <= 0.0)
+ {
+ // We've already used our full allotment.
+// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, not sleeping" << LL_ENDL;
+
+ // Still need to service the network...
+ plugin->pump();
+ }
+ else
+ {
+
+// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL;
+// timer.reset();
+
+ // This also services the network as needed.
+ plugin->sleep(remaining);
+
+// LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL;
+ }
+
+
#if LL_WINDOWS
- // More agressive checking of interfering exception handlers.
- // Doesn't appear to be required so far - even for plugins
- // that do crash with a single call to the intercept
- // exception handler such as QuickTime.
- //checkExceptionHandler();
+ // More agressive checking of interfering exception handlers.
+ // Doesn't appear to be required so far - even for plugins
+ // that do crash with a single call to the intercept
+ // exception handler such as QuickTime.
+ //checkExceptionHandler();
#endif
#if LL_DARWIN
- cocoa_interface.deleteAutoReleasePool();
+ cocoa_interface.deleteAutoReleasePool();
#endif
- }
- delete plugin;
+ }
+ delete plugin;
- ll_cleanup_apr();
+ ll_cleanup_apr();
- return 0;
+ return 0;
}