Update of /cvsroot/playerstage/code/player/libplayercore
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18140/libplayercore

Modified Files:
        Makefile.am driver.cc driver.h player.h playercore.h 
Added Files:
        property.cpp property.h 
Log Message:
applied patch 1709455 from geoff biggs adding support for generic properties to 
interfaces


Index: player.h
===================================================================
RCS file: /cvsroot/playerstage/code/player/libplayercore/player.h,v
retrieving revision 1.128
retrieving revision 1.129
diff -C2 -d -r1.128 -r1.129
*** player.h    14 Mar 2007 16:41:51 -0000      1.128
--- player.h    29 Apr 2007 07:18:43 -0000      1.129
***************
*** 444,447 ****
--- 444,497 ----
  } player_capabilities_req_t;
  
+ 
+ /**
+ @ingroup message_basics
+ @defgroup propbags Property Bags
+ Querying driver properties
+ 
+ */
+ 
+ #define PLAYER_GET_INTPROP_REQ 254
+ #define PLAYER_SET_INTPROP_REQ 253
+ #define PLAYER_GET_DBLPROP_REQ 252
+ #define PLAYER_SET_DBLPROP_REQ 251
+ #define PLAYER_GET_STRPROP_REQ 250
+ #define PLAYER_SET_STRPROP_REQ 249
+ 
+ /** @brief Request to get an integer property */
+ typedef struct player_intprop_req
+ {
+       /** The property key's length */
+       uint32_t key_count;
+       /** The property key */
+       char *key;
+       /** The property value */
+       int32_t value;
+ } player_intprop_req_t;
+ 
+ /** @brief Request to get a double property */
+ typedef struct player_dblprop_req
+ {
+       /** The property key's length */
+       uint32_t key_count;
+       /** The property key */
+       char *key;
+       /** The property value */
+       double value;
+ } player_dblprop_req_t;
+ 
+ /** @brief Request to get a string property */
+ typedef struct player_strprop_req
+ {
+       /** The property key's length */
+       uint32_t key_count;
+       /** The property key */
+       char *key;
+       /** The property's length */
+       uint32_t value_count;
+       /** The property value */
+       char *value;
+ } player_strprop_req_t;
+ 
  // 
/////////////////////////////////////////////////////////////////////////////
  //

--- NEW FILE: property.h ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000
 *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef __PROPERTY_H
#define __PROPERTY_H

class ConfigFile;

// Property base class
class Property
{
        public:
                Property (void);
                Property (const char *newKey);
                virtual ~Property (void);

                // Accessor functions
                virtual const char* GetKey (void) const         { return key; }
                virtual void SetKey (const char *newKey);
                virtual void GetValueToMessage (void *data) const = 0;
                virtual void SetValueFromMessage (const void *data) = 0;

                // Config file read method
                virtual bool ReadConfig (ConfigFile *cf, int section) = 0;

        protected:
                char *key;                      // Key for this property
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// Integer property class
class IntProperty : public Property
{
        public:
                IntProperty (const char *newKey, int newValue);

                int GetValue (void) const                       { return value; 
}
                void SetValue (int newValue)            { value = newValue; }
                void GetValueToMessage (void *data) const;
                void SetValueFromMessage (const void *data);

                // Config file read method
                virtual bool ReadConfig (ConfigFile *cf, int section);

                // Operators
                operator int (void)                             { return value; 
}
                const IntProperty& operator= (const IntProperty &rhs);
                int operator= (int rhs)                         { value = rhs; 
return value; }

        private:
                int value;
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// Double property class
class DoubleProperty : public Property
{
        public:
                DoubleProperty (const char *newKey, double newValue);

                double GetValue (void) const            { return value; }
                void SetValue (double newValue)         { value = newValue; }
                void GetValueToMessage (void *data) const;
                void SetValueFromMessage (const void *data);

                // Config file read method
                virtual bool ReadConfig (ConfigFile *cf, int section);

                // Operators
                operator double (void)                          { return value; 
}
                const DoubleProperty& operator= (const DoubleProperty &rhs);
                double operator= (double rhs)           { value = rhs; return 
value; }

        private:
                double value;
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class StringProperty : public Property
{
        public:
                StringProperty (const char *newKey, const char *newValue);
                ~StringProperty (void);

                const char* GetValue (void) const       { return value; }
                void SetValue (const char *newValue);
                void GetValueToMessage (void *data) const;
                void SetValueFromMessage (const void *data);

                // Config file read method
                virtual bool ReadConfig (ConfigFile *cf, int section);

                // Operators
                operator const char* (void)                             { 
return value; }
                const StringProperty& operator= (const StringProperty &rhs);
                const char* operator= (const char* rhs);

        private:
                char *value;
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

typedef struct PropertyNode
{
        char *key;
        Property *property;
        struct PropertyNode *next;
} PropertyNode;

// Property bag class: stores registered properties
class PropertyBag
{
        public:
                PropertyBag (void);
                ~PropertyBag (void);

                bool AddProperty (const char *key, Property *property);
                Property* GetProperty (const char *key);

        private:
                PropertyNode *firstProperty;
};

#endif // __PROPERTY_H

Index: driver.h
===================================================================
RCS file: /cvsroot/playerstage/code/player/libplayercore/driver.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** driver.h    6 May 2006 11:17:04 -0000       1.18
--- driver.h    29 Apr 2007 07:18:43 -0000      1.19
***************
*** 1,7 ****
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000  
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *                      
   *
   *  This program is free software; you can redistribute it and/or modify
--- 1,7 ----
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *
   *
   *  This program is free software; you can redistribute it and/or modify
***************
*** 23,27 ****
  /*
   * $Id$
!  *  
   *  The virtual class from which all driver classes inherit.  this
   *  defines the API that all drivers must implement.
--- 23,27 ----
  /*
   * $Id$
!  *
   *  The virtual class from which all driver classes inherit.  this
   *  defines the API that all drivers must implement.
***************
*** 36,45 ****
  #include <libplayercore/message.h>
  #include <libplayercore/player.h>
  
! /** 
  @brief capabilities request handler macro
  
! This macro tests the current message to see if its a capabilities 
! request and creates an ACK message if it is and matches the defined 
  capability.
  
--- 36,49 ----
  #include <libplayercore/message.h>
  #include <libplayercore/player.h>
+ #include <libplayercore/property.h>
  
! #include <map>
! using namespace std;
! 
! /**
  @brief capabilities request handler macro
  
! This macro tests the current message to see if its a capabilities
! request and creates an ACK message if it is and matches the defined
  capability.
  
***************
*** 61,70 ****
        return 0; \
      } \
!   } 
  
  
  // Forward declarations
  class ConfigFile;
- class Driver;
  
  /**
--- 65,73 ----
        return 0; \
      } \
!   }
  
  
  // Forward declarations
  class ConfigFile;
  
  /**
***************
*** 87,94 ****
      int error;
  
    protected:
  
      /* @brief Start the driver thread
!     
      This method is usually called from the overloaded Setup() method to
      create the driver thread.  This will call Main(). */
--- 90,99 ----
      int error;
  
+     PropertyBag propertyBag;
+ 
    protected:
  
      /* @brief Start the driver thread
! 
      This method is usually called from the overloaded Setup() method to
      create the driver thread.  This will call Main(). */
***************
*** 96,100 ****
  
      /** @brief Cancel (and wait for termination) of the driver thread
!     
      This method is usually called from the overloaded Shutdown() method
      to terminate the driver thread. */
--- 101,105 ----
  
      /** @brief Cancel (and wait for termination) of the driver thread
! 
      This method is usually called from the overloaded Shutdown() method
      to terminate the driver thread. */
***************
*** 110,119 ****
  
      /** @brief Add an interface.
!     
      @param addr Player device address.
!     
      @returns 0 on success, non-zero otherwise. */
      int AddInterface(player_devaddr_t addr);
!     
      /** @brief Set/reset error code */
      void SetError(int code) {this->error = code;}
--- 115,124 ----
  
      /** @brief Add an interface.
! 
      @param addr Player device address.
! 
      @returns 0 on success, non-zero otherwise. */
      int AddInterface(player_devaddr_t addr);
! 
      /** @brief Set/reset error code */
      void SetError(int code) {this->error = code;}
***************
*** 125,132 ****
      one message is already waiting. */
      void Wait() { this->InQueue->Wait(); }
!     
    public:
!     /** @brief The driver's thread. 
!     
      The driver's thread, when managed by StartThread() and
      StopThread(). */
--- 130,137 ----
      one message is already waiting. */
      void Wait() { this->InQueue->Wait(); }
! 
    public:
!     /** @brief The driver's thread.
! 
      The driver's thread, when managed by StartThread() and
      StopThread(). */
***************
*** 138,142 ****
  
      /** @brief Last requester's queue.
!     
      Pointer to a queue to which this driver owes a reply.  Used mainly
      by non-threaded drivers to cache the return address for requests
--- 143,147 ----
  
      /** @brief Last requester's queue.
! 
      Pointer to a queue to which this driver owes a reply.  Used mainly
      by non-threaded drivers to cache the return address for requests
***************
*** 145,151 ****
  
      /** @brief Publish a message via one of this driver's interfaces.
!     
      This form of Publish will assemble the message header for you.
!     
      @param addr The origin address
      @param queue If non-NULL, the target queue; if NULL,
--- 150,156 ----
  
      /** @brief Publish a message via one of this driver's interfaces.
! 
      This form of Publish will assemble the message header for you.
! 
      @param addr The origin address
      @param queue If non-NULL, the target queue; if NULL,
***************
*** 157,170 ****
      @param timestamp Timestamp for the message body (if NULL, then the
      current time will be filled in) */
!     void Publish(player_devaddr_t addr, 
!                  MessageQueue* queue, 
!                  uint8_t type, 
                   uint8_t subtype,
!                  void* src=NULL, 
                   size_t len=0,
                   double* timestamp=NULL);
  
      /** @brief Publish a message via one of this driver's interfaces.
!     
      Use this form of Publish if you already have the message header
      assembled.
--- 162,175 ----
      @param timestamp Timestamp for the message body (if NULL, then the
      current time will be filled in) */
!     void Publish(player_devaddr_t addr,
!                  MessageQueue* queue,
!                  uint8_t type,
                   uint8_t subtype,
!                  void* src=NULL,
                   size_t len=0,
                   double* timestamp=NULL);
  
      /** @brief Publish a message via one of this driver's interfaces.
! 
      Use this form of Publish if you already have the message header
      assembled.
***************
*** 173,177 ****
      @param hdr The message header
      @param src The message body */
!     void Publish(MessageQueue* queue, 
                   player_msghdr_t* hdr,
                   void* src);
--- 178,182 ----
      @param hdr The message header
      @param src The message body */
!     void Publish(MessageQueue* queue,
                   player_msghdr_t* hdr,
                   void* src);
***************
*** 180,184 ****
      /** @brief Default device address (single-interface drivers) */
      player_devaddr_t device_addr;
!         
      /** @brief Number of subscriptions to this driver. */
      int subscriptions;
--- 185,189 ----
      /** @brief Default device address (single-interface drivers) */
      player_devaddr_t device_addr;
! 
      /** @brief Number of subscriptions to this driver. */
      int subscriptions;
***************
*** 189,193 ****
  
      /** @brief Always on flag.
!     
      If true, driver should be "always on", i.e., player will
      "subscribe" at startup, before any clients subscribe. The
--- 194,198 ----
  
      /** @brief Always on flag.
! 
      If true, driver should be "always on", i.e., player will
      "subscribe" at startup, before any clients subscribe. The
***************
*** 201,205 ****
  
      /** @brief Constructor for single-interface drivers.
!     
      @param cf Current configuration file
      @param section Current section in configuration file
--- 206,210 ----
  
      /** @brief Constructor for single-interface drivers.
! 
      @param cf Current configuration file
      @param section Current section in configuration file
***************
*** 207,218 ****
      @param queue_maxlen How long can the incoming queue grow?
      @param interf Player interface code; e.g., PLAYER_POSITION_CODE */
!     Driver(ConfigFile *cf, 
!            int section, 
!            bool overwrite_cmds, 
!            size_t queue_maxlen, 
             int interf);
  
      /** @brief Constructor for multiple-interface drivers.
!     
      Use AddInterface() to specify individual interfaces.
      @param cf Current configuration file
--- 212,223 ----
      @param queue_maxlen How long can the incoming queue grow?
      @param interf Player interface code; e.g., PLAYER_POSITION_CODE */
!     Driver(ConfigFile *cf,
!            int section,
!            bool overwrite_cmds,
!            size_t queue_maxlen,
             int interf);
  
      /** @brief Constructor for multiple-interface drivers.
! 
      Use AddInterface() to specify individual interfaces.
      @param cf Current configuration file
***************
*** 220,226 ****
      @param overwrite_cmds Do new commands overwrite old ones?
      @param queue_maxlen How long can the incoming queue grow? */
!     Driver(ConfigFile *cf, 
             int section,
!            bool overwrite_cmds = true, 
             size_t queue_maxlen = PLAYER_MSGQUEUE_DEFAULT_MAXLEN);
  
--- 225,231 ----
      @param overwrite_cmds Do new commands overwrite old ones?
      @param queue_maxlen How long can the incoming queue grow? */
!     Driver(ConfigFile *cf,
             int section,
!            bool overwrite_cmds = true,
             size_t queue_maxlen = PLAYER_MSGQUEUE_DEFAULT_MAXLEN);
  
***************
*** 231,241 ****
      check whether anything went wrong. */
      int GetError() { return(this->error); }
!     
      /** @brief Subscribe to this driver.
  
      The Subscribe() and Unsubscribe() methods are used to control
      subscriptions to the driver; a driver MAY override them, but
!     usually won't.  
!     
      @param addr Address of the device to subscribe to (the driver may
      have more than one interface).
--- 236,246 ----
      check whether anything went wrong. */
      int GetError() { return(this->error); }
! 
      /** @brief Subscribe to this driver.
  
      The Subscribe() and Unsubscribe() methods are used to control
      subscriptions to the driver; a driver MAY override them, but
!     usually won't.
! 
      @param addr Address of the device to subscribe to (the driver may
      have more than one interface).
***************
*** 244,252 ****
  
      /** @brief Unsubscribe from this driver.
!  
      The Subscribe() and Unsubscribe() methods are used to control
      subscriptions to the driver; a driver MAY override them, but
!     usually won't.  
!     
      @param addr Address of the device to unsubscribe from (the driver may
      have more than one interface).
--- 249,257 ----
  
      /** @brief Unsubscribe from this driver.
! 
      The Subscribe() and Unsubscribe() methods are used to control
      subscriptions to the driver; a driver MAY override them, but
!     usually won't.
! 
      @param addr Address of the device to unsubscribe from (the driver may
      have more than one interface).
***************
*** 255,275 ****
  
      /** @brief Initialize the driver.
!     
      This function is called with the first client subscribes; it MUST
      be implemented by the driver.
!     
      @returns Returns 0 on success. */
      virtual int Setup() = 0;
  
      /** @brief Finalize the driver.
!     
      This function is called with the last client unsubscribes; it MUST
      be implemented by the driver.
!     
      @returns Returns 0 on success. */
      virtual int Shutdown() = 0;
  
      /** @brief Main method for driver thread.
!     
      drivers have their own thread of execution, created using
      StartThread(); this is the entry point for the driver thread,
--- 260,280 ----
  
      /** @brief Initialize the driver.
! 
      This function is called with the first client subscribes; it MUST
      be implemented by the driver.
! 
      @returns Returns 0 on success. */
      virtual int Setup() = 0;
  
      /** @brief Finalize the driver.
! 
      This function is called with the last client unsubscribes; it MUST
      be implemented by the driver.
! 
      @returns Returns 0 on success. */
      virtual int Shutdown() = 0;
  
      /** @brief Main method for driver thread.
! 
      drivers have their own thread of execution, created using
      StartThread(); this is the entry point for the driver thread,
***************
*** 278,282 ****
  
      /** @brief Cleanup method for driver thread (called when main exits)
!     
      Overload this method and to do additional cleanup when the
      driver thread exits. */
--- 283,287 ----
  
      /** @brief Cleanup method for driver thread (called when main exits)
! 
      Overload this method and to do additional cleanup when the
      driver thread exits. */
***************
*** 284,288 ****
  
      /** @brief Process pending messages.
!     
      Call this to automatically process messages using registered handler,
      Driver::ProcessMessage.
--- 289,293 ----
  
      /** @brief Process pending messages.
! 
      Call this to automatically process messages using registered handler,
      Driver::ProcessMessage.
***************
*** 297,319 ****
        */
      void ProcessMessages(void);
!       
      /** @brief Message handler.
!     
      This function is called once for each message in the incoming queue.
      Reimplement it to provide message handling.
      Return 0 if you handled the message and -1 otherwise
!     
      @param resp_queue The queue to which any response should go.
      @param hdr The message header
      @param data The message body */
!     virtual int ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr, 
                                 void * data);
  
      /** @brief Update non-threaded drivers. */
!     virtual void Update() 
      {
        if(!this->driverthread)
          this->ProcessMessages();
      }
  };
  
--- 302,344 ----
        */
      void ProcessMessages(void);
! 
      /** @brief Message handler.
! 
      This function is called once for each message in the incoming queue.
      Reimplement it to provide message handling.
      Return 0 if you handled the message and -1 otherwise
! 
      @param resp_queue The queue to which any response should go.
      @param hdr The message header
      @param data The message body */
!     virtual int ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr,
                                 void * data);
  
      /** @brief Update non-threaded drivers. */
!     virtual void Update()
      {
        if(!this->driverthread)
          this->ProcessMessages();
      }
+ 
+     /** @brief Internal message handler.
+ 
+     This function handles messages internal to the driver's operation.
+ 
+     @param resp_queue The queue to which any response should go.
+     @param hdr The message header
+     @param data The message body */
+     virtual int ProcessInternalMessages(MessageQueue* resp_queue,
+                                         player_msghdr * hdr,
+                                         void * data);
+ 
+     /** @brief Property registration.
+ 
+     @param key Property key
+     @param property Pointer to a Property object - must exist for as long as 
the property bag does
+     @param cf Configuration file
+     @param section Configuration file section that may define the property 
value
+     @return True if the property was registered, false otherwise */
+     virtual bool RegisterProperty(char *key, Property *prop, ConfigFile* cf, 
int section);
  };
  

Index: driver.cc
===================================================================
RCS file: /cvsroot/playerstage/code/player/libplayercore/driver.cc,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -d -r1.26 -r1.27
*** driver.cc   7 Feb 2007 20:19:52 -0000       1.26
--- driver.cc   29 Apr 2007 07:18:43 -0000      1.27
***************
*** 1,7 ****
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000  
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *                      
   *
   *  This program is free software; you can redistribute it and/or modify
--- 1,7 ----
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *
   *
   *  This program is free software; you can redistribute it and/or modify
***************
*** 23,27 ****
  /*
   * $Id$
!  *  
   *  the base class from which all device classes inherit.  here
   *  we implement some generic methods that most devices will not need
--- 23,27 ----
  /*
   * $Id$
!  *
   *  the base class from which all device classes inherit.  here
   *  we implement some generic methods that most devices will not need
***************
*** 47,62 ****
  #include <libplayercore/configfile.h>
  #include <libplayercore/globals.h>
  
  // Default constructor for single-interface drivers.  Specify the
  // interface code and buffer sizes.
! Driver::Driver(ConfigFile *cf, int section, 
!                bool overwrite_cmds, size_t queue_maxlen, 
                 int interf)
  {
    this->error = 0;
    this->driverthread = 0;
!   
    // Look for our default device id
!   if(cf->ReadDeviceAddr(&this->device_addr, section, "provides", 
                          interf, -1, NULL) != 0)
    {
--- 47,64 ----
  #include <libplayercore/configfile.h>
  #include <libplayercore/globals.h>
+ #include <libplayercore/property.h>
+ #include <libplayercore/interface_util.h>
  
  // Default constructor for single-interface drivers.  Specify the
  // interface code and buffer sizes.
! Driver::Driver(ConfigFile *cf, int section,
!                bool overwrite_cmds, size_t queue_maxlen,
                 int interf)
  {
    this->error = 0;
    this->driverthread = 0;
! 
    // Look for our default device id
!   if(cf->ReadDeviceAddr(&this->device_addr, section, "provides",
                          interf, -1, NULL) != 0)
    {
***************
*** 64,68 ****
      return;
    }
!   
    this->subscriptions = 0;
    this->entries = 0;
--- 66,70 ----
      return;
    }
! 
    this->subscriptions = 0;
    this->entries = 0;
***************
*** 73,80 ****
    assert(InQueue);
  
!   // Create an interface 
    if(this->AddInterface(this->device_addr) != 0)
    {
!     this->SetError(-1);    
      return;
    }
--- 75,82 ----
    assert(InQueue);
  
!   // Create an interface
    if(this->AddInterface(this->device_addr) != 0)
    {
!     this->SetError(-1);
      return;
    }
***************
*** 82,86 ****
    pthread_mutex_init(&this->accessMutex,NULL);
  }
!     
  // this is the other constructor, used by multi-interface drivers.
  Driver::Driver(ConfigFile *cf, int section,
--- 84,88 ----
    pthread_mutex_init(&this->accessMutex,NULL);
  }
! 
  // this is the other constructor, used by multi-interface drivers.
  Driver::Driver(ConfigFile *cf, int section,
***************
*** 89,95 ****
    this->error = 0;
    this->driverthread = 0;
!   
    this->device_addr.interf = UINT_MAX;
!   
    this->subscriptions = 0;
    this->alwayson = false;
--- 91,97 ----
    this->error = 0;
    this->driverthread = 0;
! 
    this->device_addr.interf = UINT_MAX;
! 
    this->subscriptions = 0;
    this->alwayson = false;
***************
*** 109,113 ****
  
  // Add an interface
! int 
  Driver::AddInterface(player_devaddr_t addr)
  {
--- 111,115 ----
  
  // Add an interface
! int
  Driver::AddInterface(player_devaddr_t addr)
  {
***************
*** 122,126 ****
  
  void
! Driver::Publish(MessageQueue* queue, 
                  player_msghdr_t* hdr,
                  void* src)
--- 124,128 ----
  
  void
! Driver::Publish(MessageQueue* queue,
                  player_msghdr_t* hdr,
                  void* src)
***************
*** 172,180 ****
  
  void
! Driver::Publish(player_devaddr_t addr, 
!                 MessageQueue* queue, 
!                 uint8_t type, 
                  uint8_t subtype,
!                 void* src, 
                  size_t len,
                  double* timestamp)
--- 174,182 ----
  
  void
! Driver::Publish(player_devaddr_t addr,
!                 MessageQueue* queue,
!                 uint8_t type,
                  uint8_t subtype,
!                 void* src,
                  size_t len,
                  double* timestamp)
***************
*** 208,228 ****
    pthread_mutex_unlock(&accessMutex);
  }
!     
  int Driver::Subscribe(player_devaddr_t addr)
  {
    int setupResult;
  
!   if(subscriptions == 0) 
    {
      setupResult = Setup();
!     if (setupResult == 0 ) 
!       subscriptions++; 
    }
!   else 
    {
      subscriptions++;
      setupResult = 0;
    }
!   
    return(setupResult);
  }
--- 210,230 ----
    pthread_mutex_unlock(&accessMutex);
  }
! 
  int Driver::Subscribe(player_devaddr_t addr)
  {
    int setupResult;
  
!   if(subscriptions == 0)
    {
      setupResult = Setup();
!     if (setupResult == 0 )
!       subscriptions++;
    }
!   else
    {
      subscriptions++;
      setupResult = 0;
    }
! 
    return(setupResult);
  }
***************
*** 232,253 ****
    int shutdownResult;
  
!   if(subscriptions == 0) 
      shutdownResult = -1;
!   else if ( subscriptions == 1) 
    {
      shutdownResult = Shutdown();
      subscriptions--;
    }
!   else 
    {
      subscriptions--;
      shutdownResult = 0;
    }
!   
    return( shutdownResult );
  }
  
  /* start a thread that will invoke Main() */
! void 
  Driver::StartThread(void)
  {
--- 234,255 ----
    int shutdownResult;
  
!   if(subscriptions == 0)
      shutdownResult = -1;
!   else if ( subscriptions == 1)
    {
      shutdownResult = Shutdown();
      subscriptions--;
    }
!   else
    {
      subscriptions--;
      shutdownResult = 0;
    }
! 
    return( shutdownResult );
  }
  
  /* start a thread that will invoke Main() */
! void
  Driver::StartThread(void)
  {
***************
*** 256,260 ****
  
  /* cancel (and wait for termination) of the thread */
! void 
  Driver::StopThread(void)
  {
--- 258,262 ----
  
  /* cancel (and wait for termination) of the thread */
! void
  Driver::StopThread(void)
  {
***************
*** 270,274 ****
  
  /* Dummy main (just calls real main) */
! void* 
  Driver::DummyMain(void *devicep)
  {
--- 272,276 ----
  
  /* Dummy main (just calls real main) */
! void*
  Driver::DummyMain(void *devicep)
  {
***************
*** 281,285 ****
    // Run the uninstall cleanup function
    pthread_cleanup_pop(1);
!   
    return NULL;
  }
--- 283,287 ----
    // Run the uninstall cleanup function
    pthread_cleanup_pop(1);
! 
    return NULL;
  }
***************
*** 294,298 ****
  
  void
! Driver::Main() 
  {
    PLAYER_ERROR("You have called StartThread(), "
--- 296,300 ----
  
  void
! Driver::Main()
  {
    PLAYER_ERROR("You have called StartThread(), "
***************
*** 301,310 ****
  
  void
! Driver::MainQuit() 
  {
  }
  
  // Default message handler
! int Driver::ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr, 
                             void * data)
  {
--- 303,312 ----
  
  void
! Driver::MainQuit()
  {
  }
  
  // Default message handler
! int Driver::ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr,
                             void * data)
  {
***************
*** 338,353 ****
      }
  
      int ret = this->ProcessMessage(msg->Queue, hdr, data);
      if(ret < 0)
      {
        PLAYER_WARN7("Unhandled message for driver "
!                    "device=%d:%d:%d:%d type=%d subtype=%d len=%d\n",
                     hdr->addr.host, hdr->addr.robot,
!                    hdr->addr.interf, hdr->addr.index, 
!                    hdr->type, hdr->subtype, hdr->size);
  
        // If it was a request, reply with an empty NACK
        if(hdr->type == PLAYER_MSGTYPE_REQ)
!         this->Publish(hdr->addr, msg->Queue, PLAYER_MSGTYPE_RESP_NACK, 
                        hdr->subtype, NULL, 0, NULL);
      }
--- 340,359 ----
      }
  
+     // First check if it's an internal message
+     if (ProcessInternalMessages(msg->Queue, hdr, data) == 0)
+       continue;
+ 
      int ret = this->ProcessMessage(msg->Queue, hdr, data);
      if(ret < 0)
      {
        PLAYER_WARN7("Unhandled message for driver "
!                    "device=%d:%d:%s:%d type=%s subtype=%d len=%d\n",
                     hdr->addr.host, hdr->addr.robot,
!                    interf_to_str(hdr->addr.interf), hdr->addr.index,
!                    msgtype_to_str(hdr->type), hdr->subtype, hdr->size);
  
        // If it was a request, reply with an empty NACK
        if(hdr->type == PLAYER_MSGTYPE_REQ)
!         this->Publish(hdr->addr, msg->Queue, PLAYER_MSGTYPE_RESP_NACK,
                        hdr->subtype, NULL, 0, NULL);
      }
***************
*** 358,359 ****
--- 364,438 ----
  }
  
+ int Driver::ProcessInternalMessages(MessageQueue* resp_queue,
+                                     player_msghdr * hdr, void * data)
+ {
+   Property *property = NULL;
+ 
+   if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_GET_INTPROP_REQ, 
device_addr))
+   {
+     player_intprop_req_t req = *reinterpret_cast<player_intprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->GetValueToMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_INTPROP_REQ, reinterpret_cast<void*> (&req), 
sizeof(player_intprop_req_t), NULL);
+     return 0;
+   }
+   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_INTPROP_REQ, device_addr))
+   {
+     player_intprop_req_t req = *reinterpret_cast<player_intprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->SetValueFromMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_INTPROP_REQ, NULL, 0, NULL);
+     return 0;
+   }
+   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_DBLPROP_REQ, device_addr))
+   {
+     player_dblprop_req_t req = *reinterpret_cast<player_dblprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->GetValueToMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_DBLPROP_REQ, reinterpret_cast<void*> (&req), 
sizeof(player_dblprop_req_t), NULL);
+     return 0;
+   }
+   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_DBLPROP_REQ, device_addr))
+   {
+     player_dblprop_req_t req = *reinterpret_cast<player_dblprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->SetValueFromMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_DBLPROP_REQ, NULL, 0, NULL);
+     return 0;
+   }
+   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_GET_STRPROP_REQ, device_addr))
+   {
+     player_strprop_req_t req = *reinterpret_cast<player_strprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->GetValueToMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_GET_STRPROP_REQ, reinterpret_cast<void*> (&req), 
sizeof(player_strprop_req_t), NULL);
+     return 0;
+   }
+   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_STRPROP_REQ, device_addr))
+   {
+     player_strprop_req_t req = *reinterpret_cast<player_strprop_req_t*> 
(data);
+     if ((property = propertyBag.GetProperty (req.key)) == NULL)
+       return -1;
+     property->SetValueFromMessage (reinterpret_cast<void*> (&req));
+     Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, 
PLAYER_SET_STRPROP_REQ, NULL, 0, NULL);
+     return 0;
+   }
+ 
+   return -1;
+ }
+ 
+ bool Driver::RegisterProperty(char *key, Property *prop, ConfigFile* cf, int 
section)
+ {
+   if (!propertyBag.AddProperty (key, prop))
+     return false;
+ 
+   if (cf != NULL)
+     prop->ReadConfig (cf, section);
+ 
+   return true;
+ }

Index: playercore.h
===================================================================
RCS file: /cvsroot/playerstage/code/player/libplayercore/playercore.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** playercore.h        15 Nov 2005 00:03:00 -0000      1.4
--- playercore.h        29 Apr 2007 07:18:43 -0000      1.5
***************
*** 1,7 ****
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000  
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *                      
   *
   *  This program is free software; you can redistribute it and/or modify
--- 1,7 ----
  /*
   *  Player - One Hell of a Robot Server
!  *  Copyright (C) 2000
   *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
!  *
   *
   *  This program is free software; you can redistribute it and/or modify
***************
*** 41,44 ****
--- 41,45 ----
  #include <libplayercore/wallclocktime.h>
  #include <libplayercore/addr_util.h>
+ #include <libplayercore/property.h>
  
  #endif

--- NEW FILE: property.cpp ---
/*
 *  Player - One Hell of a Robot Server
 *  Copyright (C) 2000
 *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "property.h"
#include <libplayercore/playercommon.h>
#include <libplayercore/player.h>
#include <libplayercore/configfile.h>
#include <libplayercore/error.h>

#include <stdlib.h>
#include <string.h>

Property::Property (void)
        : key (NULL)
{
}

Property::Property (const char *newKey)
{
        if ((key = strdup (newKey)) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property key 
%s", newKey);
                key = NULL;
        }
}

Property::~Property (void)
{
        if (key != NULL)
                free (key);
}

void Property::SetKey (const char *newKey)
{
        if (key != NULL)
                free (key);

        if ((key = strdup (newKey)) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property key 
%s", newKey);
                key = NULL;
        }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

IntProperty::IntProperty (const char *newKey, int newValue)
        : Property (newKey), value (newValue)
{
}

void IntProperty::GetValueToMessage (void *data) const
{
        reinterpret_cast<player_intprop_req_t*> (data)->value = value;
}

void IntProperty::SetValueFromMessage (const void *data)
{
        value = reinterpret_cast<const player_intprop_req_t*> (data)->value;
}

bool IntProperty::ReadConfig (ConfigFile *cf, int section)
{
        // Read an integer from the config file section, using the current prop 
value as the default
        value = cf->ReadInt (section, key, value);

        return true;
}

const IntProperty& IntProperty::operator= (const IntProperty &rhs)
{
        value = rhs.GetValue ();
        return *this;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

DoubleProperty::DoubleProperty (const char *newKey, double newValue)
        : Property (newKey), value (newValue)
{
}

void DoubleProperty::GetValueToMessage (void *data) const
{
        reinterpret_cast<player_dblprop_req_t*> (data)->value = value;
}

void DoubleProperty::SetValueFromMessage (const void *data)
{
        value = reinterpret_cast<const player_dblprop_req_t*> (data)->value;
}

bool DoubleProperty::ReadConfig (ConfigFile *cf, int section)
{
        // Read a double from the config file section, using the current prop 
value as the default
        value = cf->ReadFloat (section, key, value);

        return true;
}

const DoubleProperty& DoubleProperty::operator= (const DoubleProperty &rhs)
{
        value = rhs.GetValue ();
        return *this;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

StringProperty::StringProperty (const char *newKey, const char *newValue)
        : Property (newKey)
{
        if (newValue != NULL)
        {
                if ((value = strdup (newValue)) == NULL)
                {
                        PLAYER_ERROR1 ("Failed to allocate memory to store 
property value %s", newValue);
                        value = NULL;
                }
        }
        else
                value = NULL;
}

StringProperty::~StringProperty (void)
{
        if (value != NULL)
                free (value);
}

void StringProperty::SetValue (const char *newValue)
{
        if (value != NULL)
                free (value);

        if (newValue != NULL)
        {
                if ((value = strdup (newValue)) == NULL)
                {
                        PLAYER_ERROR1 ("Failed to allocate memory to store 
property value %s", newValue);
                        value = NULL;
                }
        }
        else
                value = NULL;
}

void StringProperty::GetValueToMessage (void *data) const
{
        player_strprop_req_t *req = reinterpret_cast<player_strprop_req_t*> 
(data);

        if (value == NULL)
                req->value = NULL;
        else if ((req->value = strdup (value)) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property 
value %s", value);
                req->value = NULL;
                req->value_count = 0;
        }
        req->value_count = strlen (req->value) + 1;     // +1 to make sure the 
NULL byte is copied by pack/unpack functions
}

void StringProperty::SetValueFromMessage (const void *data)
{
        const player_strprop_req_t *req = reinterpret_cast<const 
player_strprop_req_t*> (data);
        if (value != NULL)
                free (value);
        if ((value = strdup (req->value)) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property 
value %s", req->value);
                value = NULL;
        }
}

bool StringProperty::ReadConfig (ConfigFile *cf, int section)
{
        const char *temp = cf->ReadString (section, key, NULL);
        if (temp != NULL)
        {
                if (value != NULL)
                        free (value);

                if ((value = strdup (temp)) == NULL)
                {
                        PLAYER_ERROR1 ("Failed to allocate memory to store 
property value %s", temp);
                        value = NULL;
                        return false;
                }
        }

        return true;
}

const StringProperty& StringProperty::operator= (const StringProperty &rhs)
{
        if (value != NULL)
                free (value);

        if (rhs.GetValue () == NULL)
                value = NULL;
        else if ((value = strdup (rhs.GetValue ())) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property 
value %s", rhs.GetValue ());
                value = NULL;
        }
        return *this;
}

const char* StringProperty::operator= (const char* rhs)
{
        if (value != NULL)
                free (value);

        if (rhs == NULL)
                value = NULL;
        else if ((value = strdup (rhs)) == NULL)
        {
                PLAYER_ERROR1 ("Failed to allocate memory to store property 
value %s", rhs);
                value = NULL;
        }
        return *this;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

PropertyBag::PropertyBag (void)
        : firstProperty (NULL)
{
}

PropertyBag::~PropertyBag (void)
{
        if (firstProperty != NULL)
        {
                // Trash the linked list
                PropertyNode *currentProp = firstProperty;
                while (firstProperty != NULL)
                {
                        firstProperty = currentProp->next;
                        if (currentProp->key != NULL)
                                free (currentProp->key);
                        delete currentProp;
                        currentProp = firstProperty;
                }
        }
}

bool PropertyBag::AddProperty (const char *key, Property *property)
{
        if (firstProperty == NULL)
        {
                if ((firstProperty = new PropertyNode) == NULL)
                {
                        PLAYER_ERROR ("Failed to allocate memory for property 
node");
                        return false;
                }
                if ((firstProperty->key = strdup (key)) == NULL)
                {
                        PLAYER_ERROR1 ("Failed to allocate memory for property 
key: %s", key);
                        delete firstProperty;
                        firstProperty = NULL;
                        return false;
                }
                firstProperty->property = property;
                firstProperty->next = NULL;
        }
        else
        {
                // Walk to the end of the list, checking for an existing 
property as we go
                PropertyNode *lastProperty = firstProperty;
                while (lastProperty != NULL)
                {
                        if (strcmp (lastProperty->key, key) == 0)
                        {
                                PLAYER_ERROR1 ("Property already registered: 
%s", key);
                                return false;
                        }
                        if (lastProperty->next == NULL)
                        {
                                // This is the end of the list, break before we 
lose the pointer
                                // Note that the while loop doesn't do this 
check because then
                                // it wouldn't check the last item on the list 
to see if it's the
                                // same key as the one being registered
                                break;
                        }
                        lastProperty = lastProperty->next;
                }

                // Add the new property at this position (which should be the 
end of the list)
                if ((lastProperty->next = new PropertyNode) == NULL)
                {
                        PLAYER_ERROR ("Failed to allocate memory for property 
node");
                        return false;
                }
                if ((lastProperty->next->key = strdup (key)) == NULL)
                {
                        PLAYER_ERROR1 ("Failed to allocate memory for property 
key: %s", key);
                        delete lastProperty->next;
                        lastProperty->next = NULL;
                        return false;
                }
                lastProperty = lastProperty->next;
                lastProperty->property = property;
                lastProperty->next = NULL;
        }

        return true;
}

Property* PropertyBag::GetProperty (const char *key)
{
        PropertyNode *currentProp = firstProperty;

        while (currentProp != NULL)
        {
                if (strcmp (currentProp->key, key) == 0)
                        return currentProp->property;
                currentProp = currentProp->next;
        }
        // Property wasn't found
        PLAYER_ERROR1 ("Property not registered: %s", key);
        return NULL;
}

Index: Makefile.am
===================================================================
RCS file: /cvsroot/playerstage/code/player/libplayercore/Makefile.am,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** Makefile.am 14 Mar 2007 16:41:51 -0000      1.17
--- Makefile.am 29 Apr 2007 07:18:43 -0000      1.18
***************
*** 22,26 ****
                            plugins.cc plugins.h \
                            globals.cc globals.h \
!                           addr_util.c addr_util.h
  libplayercore_la_LDFLAGS = $(PLAYER_VERSION_INFO) -rpath $(libdir) 
$(top_builddir)/libplayercore/libplayererror.la 
$(top_builddir)/libplayercore/libplayerutils.la
  libplayercore_la_DEPENDENCIES = 
$(top_builddir)/libplayercore/libplayererror.la 
$(top_builddir)/libplayercore/libplayerutils.la
--- 22,27 ----
                            plugins.cc plugins.h \
                            globals.cc globals.h \
!                           addr_util.c addr_util.h \
!                           property.cpp property.h
  libplayercore_la_LDFLAGS = $(PLAYER_VERSION_INFO) -rpath $(libdir) 
$(top_builddir)/libplayercore/libplayererror.la 
$(top_builddir)/libplayercore/libplayerutils.la
  libplayercore_la_DEPENDENCIES = 
$(top_builddir)/libplayercore/libplayererror.la 
$(top_builddir)/libplayercore/libplayerutils.la
***************
*** 49,52 ****
                        wallclocktime.h \
                        error.h \
!                       addr_util.h
  
--- 50,54 ----
                        wallclocktime.h \
                        error.h \
!                       addr_util.h \
!                       property.h
  


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to