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