Linden Lab Official:Hello World plugin: basic plugin code
From Second Life Wiki
Second Life Wiki > Hello World plugin: basic plugin code
Official Linden Lab® Information: You may access and link to this page, but you may not copy, distribute, modify, adapt, or translate any content on this page. This content is subject to the Terms of Service and is not available under the Creative Commons or any other license.
Have a suggestion to improve this page? Contact us. |
Unofficial APIs
#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; }


