Actually flush messages before terminating a plugin (upon the shutdown message) and flush messages in the file- and dirpicker before opening the blocking dialog. Flush debug messages too (deeper into the code, just prior to the actual blocking call). Also, fix the context folder map to be a thread-safe singleton and *attempt* to add support for default folders to windows and Mac. The latter might even not compile yet and definitely have to be tested (and fixed): Opening a DirPicker in preferences --> Network and Set the directory location of the cache. It should open a Dialog window where you are already in the folder that is the current cache directory setting (you can click Cancel after verifying that this worked). And, start to upload an image, select a file is some directory (other than what it starts in). You can omit the actual upload by clicking cancel in the preview. Then upload again and now it should start in the same folder as that you were just in. Possibly you need to first open a file picker elsewhere with a different context though, or windows might choose to open in the last folder anyway while the code doesn't really work. Uploading a sound before the second texture upload should do the trick.
191 lines
6.8 KiB
C++
Executable File
191 lines
6.8 KiB
C++
Executable File
/**
|
|
* @file basic_plugin_base.cpp
|
|
* @brief Basic plugin base class for Basic API plugin system
|
|
*
|
|
* All plugins should be a subclass of BasicPluginBase.
|
|
*
|
|
* @cond
|
|
* $LicenseInfo:firstyear=2010&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2010, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlife.com/developers/opensource/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlife.com/developers/opensource/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*
|
|
* @endcond
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
#include "basic_plugin_base.h"
|
|
|
|
|
|
// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
|
|
|
|
// Used for logging.
|
|
BasicPluginBase* BasicPluginBase::sPluginBase;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// Basic plugin constructor.
|
|
///
|
|
/// @param[in] send_message_function Function for sending messages from plugin to plugin loader shell
|
|
/// @param[in] plugin_instance Message data for messages from plugin to plugin loader shell
|
|
BasicPluginBase::BasicPluginBase(LLPluginInstance::sendMessageFunction send_message_function, LLPluginInstance* plugin_instance) :
|
|
mPluginInstance(plugin_instance), mSendMessageFunction(send_message_function), mDeleteMe(false)
|
|
{
|
|
llassert(!sPluginBase);
|
|
sPluginBase = this;
|
|
}
|
|
|
|
/**
|
|
* Receive message from plugin loader shell.
|
|
*
|
|
* @param[in] message_string Message string
|
|
* @param[in] user_data Message data
|
|
*
|
|
*/
|
|
void BasicPluginBase::staticReceiveMessage(char const* message_string, BasicPluginBase** self_ptr)
|
|
{
|
|
BasicPluginBase* self = *self_ptr;
|
|
if(self != NULL)
|
|
{
|
|
self->receiveMessage(message_string);
|
|
|
|
// If the plugin has processed the delete message, delete it.
|
|
if(self->mDeleteMe)
|
|
{
|
|
delete self;
|
|
*self_ptr = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is the SLPlugin process.
|
|
// This is the loaded DSO.
|
|
//
|
|
// Call this function to send 'message' to the viewer.
|
|
// Note: mSendMessageFunction points to LLPluginInstance::staticReceiveMessage, so indirectly this
|
|
// just calls LLPluginInstance::receiveMessage (mPluginInstance->receiveMessage) where
|
|
// mPluginInstance is the LLPluginInstance created in LLPluginProcessChild::idle during
|
|
// state STATE_PLUGIN_LOADING. That function then immediately calls mOwner->receivePluginMessage
|
|
// which is implemented as LLPluginProcessChild::receivePluginMessage, the same
|
|
// LLPluginProcessChild object that created the LLPluginInstance.
|
|
/**
|
|
* Send message to plugin loader shell.
|
|
*
|
|
* @param[in] message Message data being sent to plugin loader shell
|
|
*
|
|
*/
|
|
void BasicPluginBase::sendMessage(const LLPluginMessage &message)
|
|
{
|
|
std::string output = message.generate();
|
|
PLS_DEBUGS << "BasicPluginBase::sendMessage: Sending: " << output << PLS_ENDL;
|
|
mSendMessageFunction(output.c_str(), &mPluginInstance);
|
|
}
|
|
|
|
/**
|
|
* Send debug log message to plugin loader shell.
|
|
*
|
|
* @param[in] message Log message being sent to plugin loader shell
|
|
* @param[in] level Log message level, enum of LLPluginMessage::LLPLUGIN_LOG_LEVEL
|
|
*
|
|
*/
|
|
void BasicPluginBase::sendLogMessage(std::string const& message, LLPluginMessage::LLPLUGIN_LOG_LEVEL level)
|
|
{
|
|
LLPluginMessage logmessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "log_message");
|
|
logmessage.setValue("message", message);
|
|
logmessage.setValueS32("log_level",level);
|
|
mSendMessageFunction(logmessage.generate().c_str(), &mPluginInstance);
|
|
// Theoretically we should flush here (that's what PLS_ENDL means), but we don't because
|
|
// that interfers with how the code would act without debug messages. Instead, the developer
|
|
// is responsible to call flushMessages themselves at the appropriate places.
|
|
}
|
|
|
|
/**
|
|
* Flush all messages to the viewer.
|
|
*
|
|
* This blocks if necessary, up till 10 seconds, before it gives up.
|
|
*/
|
|
void BasicPluginBase::flushMessages(void)
|
|
{
|
|
LLPluginMessage logmessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "flush");
|
|
mSendMessageFunction(logmessage.generate().c_str(), &mPluginInstance);
|
|
}
|
|
|
|
/**
|
|
* Send shutdown message to the plugin loader shell.
|
|
*
|
|
* This will cause the SLPlugin process that loaded this DSO to be terminated.
|
|
*/
|
|
void BasicPluginBase::sendShutdownMessage(void)
|
|
{
|
|
// Do a double flush. First flush all messages so far, then send the shutdown message,
|
|
// which also will try to flush itself before terminating the process.
|
|
flushMessages();
|
|
LLPluginMessage shutdownmessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown");
|
|
sendMessage(shutdownmessage);
|
|
}
|
|
|
|
#if LL_WINDOWS
|
|
# define LLSYMEXPORT __declspec(dllexport)
|
|
#elif LL_LINUX
|
|
# define LLSYMEXPORT __attribute__ ((visibility("default")))
|
|
#else
|
|
# define LLSYMEXPORT /**/
|
|
#endif
|
|
|
|
extern "C"
|
|
{
|
|
LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction send_message_function,
|
|
LLPluginInstance* plugin_instance,
|
|
LLPluginInstance::receiveMessageFunction* receive_message_function,
|
|
BasicPluginBase** plugin_object);
|
|
}
|
|
|
|
/**
|
|
* Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check!
|
|
*
|
|
* @param[in] send_message_function Function for sending messages from plugin to viewer
|
|
* @param[in] plugin_instance Message data for messages from plugin to plugin loader shell
|
|
* @param[out] receive_message_function Function for receiving message from viewer to plugin
|
|
* @param[out] plugin_object Pointer to plugin instance
|
|
*
|
|
* @return int, where 0=success
|
|
*
|
|
*/
|
|
LLSYMEXPORT int
|
|
LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction send_message_function,
|
|
LLPluginInstance* plugin_instance,
|
|
LLPluginInstance::receiveMessageFunction* receive_message_function,
|
|
BasicPluginBase** plugin_object)
|
|
{
|
|
*receive_message_function = BasicPluginBase::staticReceiveMessage;
|
|
return create_plugin(send_message_function, plugin_instance, plugin_object);
|
|
}
|
|
|
|
#ifdef WIN32
|
|
int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params )
|
|
{
|
|
return 1;
|
|
}
|
|
#endif
|