Linden Lab Official:Hello World plugin: basic plugin code

From Second Life Wiki
Revision as of 14:32, 4 May 2011 by Rand Linden (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Ll color vert 100.gif
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.


<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>