Linden Lab Official:Hello World plugin: basic plugin code
<cpp>
- include "linden_common.h"
- include "llgl.h"
- include "llplugininstance.h"
- include "llpluginmessage.h"
- include "llpluginmessageclasses.h"
- include "media_plugin_base.h"
- include <time.h>
//////////////////////////////////////////////////////////////////////////////// // class MediaPluginHelloworld :
public MediaPluginBase
{
public:
MediaPluginHelloworld( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
~MediaPluginHelloworld();
/*virtual*/ void receiveMessage( const char* message_string );
private:
bool init();
void update( double milliseconds );
void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
int getSurfaceSize() const;
void randomizeDirection();
bool mFirstTime;
time_t mLastUpdateTime;
enum Constants { ENumObjects = 10 };
unsigned char* mBackgroundPixels;
bool mMouseButtonDown;
bool mStopAction;
int squareR;
int squareG;
int squareB;
int squareWidth;
int squareHeight;
int squareXpos;
int squareYpos;
int squareXinc;
int squareYinc;
};
//////////////////////////////////////////////////////////////////////////////// // MediaPluginHelloworld::MediaPluginHelloworld( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) :
MediaPluginBase( host_send_func, host_user_data )
{
mFirstTime = true; mWidth = 1024; // needs to be non-zero if no later resize message is sent mHeight = 1024; // needs to be non-zero if no later resize message is sent mDepth = 4; mPixels = 0; mMouseButtonDown = false; mStopAction = false; mLastUpdateTime = 0;
}
//////////////////////////////////////////////////////////////////////////////// // MediaPluginHelloworld::~MediaPluginHelloworld() { }
//////////////////////////////////////////////////////////////////////////////// // void MediaPluginHelloworld::receiveMessage( const char* message_string ) { // std::cout << "entered MediaPluginHelloworld::receiveMessage()" << std::endl;
LLPluginMessage message_in;
if ( message_in.parse( message_string ) >= 0 )
{
std::string message_class = message_in.getClass();
std::string message_name = message_in.getName();
if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE )
{
if ( message_name == "init" )
{
LLPluginMessage message( "base", "init_response" );
LLSD versions = LLSD::emptyMap();
versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
message.setValueLLSD( "versions", versions );
std::string plugin_version = "Hello World media plugin, Hello World Version 1.0.0.0";
message.setValue( "plugin_version", plugin_version );
sendMessage( message );
// Plugin gets to decide the texture parameters to use.
message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
message.setValueS32( "default_width", mWidth ); // width in pixels
message.setValueS32( "default_height", mHeight ); // height in pixels
message.setValueS32( "depth", mDepth ); // pixel size in bytes
message.setValueU32( "internalformat", GL_RGBA );
message.setValueU32( "format", GL_RGBA );
message.setValueU32( "type", GL_UNSIGNED_BYTE );
message.setValueBoolean( "coords_opengl", false );
sendMessage( message );
}
else
if ( message_name == "idle" )
{
// no response is necessary here.
double time = message_in.getValueReal( "time" );
std::cout << "MediaPluginHelloworld::receiveMessage(): idle"<<std::endl;
// Convert time to milliseconds for update()
update( time );
}
else
if ( message_name == "cleanup" )
{
// clean up here
}
else
if ( message_name == "shm_added" )
{
SharedSegmentInfo info;
info.mAddress = message_in.getValuePointer( "address" );
info.mSize = ( size_t )message_in.getValueS32( "size" );
std::string name = message_in.getValue( "name" );
mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) );
}
else
if ( message_name == "shm_remove" )
{
std::string name = message_in.getValue( "name" );
SharedSegmentMap::iterator iter = mSharedSegments.find( name );
if( iter != mSharedSegments.end() )
{
if ( mPixels == iter->second.mAddress )
{
// This is the currently active pixel buffer.
// Make sure we stop drawing to it.
mPixels = NULL;
mTextureSegmentName.clear();
};
mSharedSegments.erase( iter );
}
else
{
//std::cerr << "MediaPluginHelloworld::receiveMessage: unknown shared memory region!" << std::endl;
};
// Send the response so it can be cleaned up.
LLPluginMessage message( "base", "shm_remove_response" );
message.setValue( "name", name );
sendMessage( message );
}
else
{
//std::cerr << "MediaPluginHelloworld::receiveMessage: unknown base message: " << message_name << std::endl;
};
}
else
if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
{
if ( message_name == "size_change" )
{
std::string name = message_in.getValue( "name" );
S32 width = message_in.getValueS32( "width" );
S32 height = message_in.getValueS32( "height" );
S32 texture_width = message_in.getValueS32( "texture_width" );
S32 texture_height = message_in.getValueS32( "texture_height" );
if ( ! name.empty() )
{
// Find the shared memory region with this name
SharedSegmentMap::iterator iter = mSharedSegments.find( name );
if ( iter != mSharedSegments.end() )
{
mPixels = ( unsigned char* )iter->second.mAddress;
mWidth = width;
mHeight = height;
mTextureWidth = texture_width;
mTextureHeight = texture_height;
init();
};
};
LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" );
message.setValue( "name", name );
message.setValueS32( "width", width );
message.setValueS32( "height", height );
message.setValueS32( "texture_width", texture_width );
message.setValueS32( "texture_height", texture_height );
sendMessage( message );
}
else
if ( message_name == "load_uri" )
{
std::string uri = message_in.getValue( "uri" );
if ( ! uri.empty() )
{
};
}
else
if ( message_name == "mouse_event" )
{
std::string event = message_in.getValue( "event" );
S32 button = message_in.getValueS32( "button" );
// left mouse button
if ( button == 0 )
{
int mouse_x = message_in.getValueS32( "x" );
int mouse_y = message_in.getValueS32( "y" );
std::string modifiers = message_in.getValue( "modifiers" );
if ( event == "move" )
{
if ( mMouseButtonDown ) write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 );
}
else
if ( event == "down" )
{
mMouseButtonDown = true;
}
else
if ( event == "up" )
{
mMouseButtonDown = false;
}
else
if ( event == "double_click" )
{
};
};
}
else
if ( message_name == "key_event" )
{
std::string event = message_in.getValue( "event" );
S32 key = message_in.getValueS32( "key" );
std::string modifiers = message_in.getValue( "modifiers" );
if ( event == "down" )
{
if ( key == ' ')
{
mLastUpdateTime = 0;
update( 0.0f );
};
};
}
else
{
//std::cerr << "MediaPluginHelloworld::receiveMessage: unknown media message: " << message_string << std::endl;
};
}
else
if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER )
{
if ( message_name == "browse_reload" )
{
mLastUpdateTime = 0;
mFirstTime = true;
mStopAction = false;
update( 0.0f );
}
else
if ( message_name == "browse_stop" )
{
for( int n = 0; n < ENumObjects; ++n )
squareXinc = squareYinc = 0;
mStopAction = true;
update( 0.0f );
}
else
{
//std::cerr << "MediaPluginHelloworld::receiveMessage: unknown media_browser message: " << message_string << std::endl;
};
}
else
{
//std::cerr << "MediaPluginHelloworld::receiveMessage: unknown message class: " << message_class << std::endl;
};
};
}
//////////////////////////////////////////////////////////////////////////////// // int MediaPluginHelloworld::getSurfaceSize() const {
return mWidth * mHeight * mDepth;
}
//////////////////////////////////////////////////////////////////////////////// // void MediaPluginHelloworld::randomizeDirection() {
// Sset an X and Y direction, disallow 0 (no direction).
do
{
squareXinc = rand() % 5 - 2;
}
while (squareXinc == 0);
do
{
squareYinc = rand() % 7 - 3;
}
while (squareYinc == 0);
} //////////////////////////////////////////////////////////////////////////////// // void MediaPluginHelloworld::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) {
// make sure we don't write outside the buffer
if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
return;
if ( mBackgroundPixels != NULL )
{
unsigned char *pixel = mBackgroundPixels;
pixel += y * mWidth * mDepth;
pixel += ( x * mDepth );
pixel[ 0 ] = b;
pixel[ 1 ] = g;
pixel[ 2 ] = r;
setDirty( x, y, x + 1, y + 1 );
};
}
//////////////////////////////////////////////////////////////////////////////// // void MediaPluginHelloworld::update( double milliseconds ) {
if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
return;
if ( mPixels == 0 )
return;
// TODO
};
//////////////////////////////////////////////////////////////////////////////// // bool MediaPluginHelloworld::init() {
LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); message.setValue( "name", "Hello World Plugin" ); sendMessage( message ); return true;
};
//////////////////////////////////////////////////////////////////////////////// // int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func,
void* host_user_data,
LLPluginInstance::sendMessageFunction *plugin_send_func,
void **plugin_user_data )
{
MediaPluginHelloworld* self = new MediaPluginHelloworld( host_send_func, host_user_data ); *plugin_send_func = MediaPluginHelloworld::staticReceiveMessage; *plugin_user_data = ( void* )self; return 0;
}
</cpp>