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>