Linden Lab Official:Hello World plugin: basic plugin code

From Second Life Wiki
Jump to: navigation, search


<cpp>

  1. include "linden_common.h"
  1. include "llgl.h"
  2. include "llplugininstance.h"
  3. include "llpluginmessage.h"
  4. include "llpluginmessageclasses.h"
  5. include "media_plugin_base.h"
  1. 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>