vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Analog_Output.C
Go to the documentation of this file.
1 #include "vrpn_Analog_Output.h"
2 #include <stdio.h>
3 
5  : vrpn_BaseClass(name, c)
6  , o_num_channel(0)
7 {
8  int i;
9 
10  // Call the base class' init routine
12 
13  // Set the time to 0 just to have something there.
14  o_timestamp.tv_usec = o_timestamp.tv_sec = 0;
15  // Initialize the values in the channels,
16  // gets rid of uninitialized memory read error in Purify
17  // and makes sure any initial value change gets reported.
18  for (i = 0; i < vrpn_CHANNEL_MAX; i++) {
19  o_channel[i] = 0;
20  }
21 }
22 
24 {
26  "vrpn_Analog_Output Change_request");
28  "vrpn_Analog_Output Change_Channels_request");
30  "vrpn_Analog_Output Num_Channels_report");
33  if ((request_m_id == -1) || (request_channels_m_id == -1) ||
34  (report_num_channels_m_id == -1) || (got_connection_m_id == -1)) {
35  return -1;
36  }
37  else {
38  return 0;
39  }
40 }
41 
43 {
44  printf("Analog_Output Report: ");
45  for (vrpn_int32 i = 0; i < o_num_channel; i++) {
46  // printf("Channel[%d]= %f\t", i, o_channel[i]);
47  printf("%f\t", o_channel[i]);
48  }
49  printf("\n");
50 }
51 
53  vrpn_Connection* c,
54  vrpn_int32 numChannels)
55  : vrpn_Analog_Output(name, c)
56 {
57  this->setNumChannels(numChannels);
58 
59  // Check if we have a connection
60  if (d_connection == NULL) {
61  fprintf(stderr, "vrpn_Analog_Output: Can't get connection!\n");
62  }
63 
64  // Register a handler for the request channel change message
66  d_sender_id)) {
67  fprintf(stderr, "vrpn_Analog_Output_Server: can't register change "
68  "channel request handler\n");
69  d_connection = NULL;
70  }
71 
72  // Register a handler for the request channels change message
75  d_sender_id)) {
76  fprintf(stderr, "vrpn_Analog_Output_Server: can't register change "
77  "channels request handler\n");
78  d_connection = NULL;
79  }
80 
81  // Register a handler for vrpn_got_connection, so we can tell the
82  // client how many channels are active
84  this)) {
85  fprintf(stderr, "vrpn_Analog_Output_Server: can't register new "
86  "connection handler\n");
87  d_connection = NULL;
88  }
89 }
90 
91 // virtual
93 
94 vrpn_int32 vrpn_Analog_Output_Server::setNumChannels(vrpn_int32 sizeRequested)
95 {
96  if (sizeRequested < 0) sizeRequested = 0;
97  if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
98 
99  o_num_channel = sizeRequested;
100 
101  return o_num_channel;
102 }
103 
104 /* static */
107 {
108  const char* bufptr = p.buffer;
109  vrpn_int32 chan_num;
110  vrpn_int32 pad;
111  vrpn_float64 value;
113 
114  // Read the parameters from the buffer
115  vrpn_unbuffer(&bufptr, &chan_num);
116  vrpn_unbuffer(&bufptr, &pad);
117  vrpn_unbuffer(&bufptr, &value);
118 
119  // Set the appropriate value, if the channel number is in the
120  // range of the ones we have.
121  if ((chan_num < 0) || (chan_num >= me->o_num_channel)) {
122  fprintf(stderr, "vrpn_Analog_Output_Server::handle_request_message(): "
123  "Index out of bounds\n");
124  char msg[1024];
125  sprintf(msg, "Error: (handle_request_message): channel %d is not "
126  "active. Squelching.",
127  chan_num);
129  return 0;
130  }
131  me->o_channel[chan_num] = value;
132 
133  return 0;
134 }
135 
136 /* static */
138  void* userdata, vrpn_HANDLERPARAM p)
139 {
140  int i;
141  const char* bufptr = p.buffer;
142  vrpn_int32 num;
143  vrpn_int32 pad;
145 
146  // Read the values from the buffer
147  vrpn_unbuffer(&bufptr, &num);
148  vrpn_unbuffer(&bufptr, &pad);
149  if (num > me->o_num_channel) {
150  char msg[1024];
151  sprintf(msg, "Error: (handle_request_channels_message): channels "
152  "above %d not active; "
153  "bad request up to channel %d. Squelching.",
154  me->o_num_channel, num);
156  num = me->o_num_channel;
157  }
158  if (num < 0) {
159  char msg[1024];
160  sprintf(msg, "Error: (handle_request_channels_message): invalid "
161  "channel %d. Squelching.",
162  num);
164  return 0;
165  }
166  for (i = 0; i < num; i++) {
167  vrpn_unbuffer(&bufptr, &(me->o_channel[i]));
168  }
169 
170  return 0;
171 }
172 
173 /* static */
176 {
178  if (me->report_num_channels() == false) {
179  fprintf(stderr, "Error: failed sending active channels to client.\n");
180  }
181  return 0;
182 }
183 
185  vrpn_uint32 class_of_service)
186 {
187  char msgbuf[sizeof(vrpn_int32)];
188  vrpn_int32 len = sizeof(vrpn_int32);
189  ;
190 
191  encode_num_channels_to(msgbuf, this->o_num_channel);
193  if (d_connection &&
195  d_sender_id, msgbuf, class_of_service)) {
196  fprintf(stderr, "vrpn_Analog_Output_Server (report_num_channels): "
197  "cannot write message: tossing\n");
198  return false;
199  }
200  return true;
201 }
202 
204  vrpn_int32 num)
205 {
206  // Message includes: int32 number of active channels
207  int buflen = sizeof(vrpn_int32);
208 
209  vrpn_buffer(&buf, &buflen, num);
210  return sizeof(vrpn_int32);
211 }
212 
214  const char* name, vrpn_Connection* c, vrpn_int32 numChannels)
215  : vrpn_Analog_Output_Server(name, c, numChannels)
216 {
217  // Register a handler for the request channel change message. This will go
218  // in the list AFTER the one for the base class, so the values will already
219  // have been filled in. So we just need to call the user-level callbacks
220  // and pass them a pointer to the data values.
222  d_sender_id)) {
223  fprintf(stderr, "vrpn_Analog_Output_Callback_Server: can't register "
224  "change channel request handler\n");
225  d_connection = NULL;
226  }
227 
228  // Register a handler for the request channels change message. This will go
229  // in the list AFTER the one for the base class, so the values will already
230  // have been filled in. So we just need to call the user-level callbacks
231  // and pass them a pointer to the data values.
234  fprintf(stderr, "vrpn_Analog_Output_Callback_Server: can't register "
235  "change channels request handler\n");
236  d_connection = NULL;
237  }
238 }
239 
240 // virtual
242 
243 /* static */
244 // This is inserted into the list AFTER the
246  void* userdata, vrpn_HANDLERPARAM p)
247 {
250  vrpn_ANALOGOUTPUTCB callback_data;
251 
252  callback_data.msg_time = p.msg_time;
253  callback_data.num_channel = me->getNumChannels();
254  callback_data.channel = me->o_channels();
255  me->d_callback_list.call_handlers(callback_data);
256 
257  return 0;
258 }
259 
261  vrpn_Connection* c)
262  : vrpn_Analog_Output(name, c)
263 {
264  vrpn_int32 i;
265 
267  for (i = 0; i < vrpn_CHANNEL_MAX; i++) {
268  o_channel[i] = 0;
269  }
271 
272  // Register a handler for the report number of active channels message
275  d_sender_id)) {
276  fprintf(stderr, "vrpn_Analog_Output_Remote: can't register active "
277  "channel report handler\n");
278  d_connection = NULL;
279  }
280 }
281 
282 // virtual
284 
286 {
287  if (d_connection) {
289  client_mainloop();
290  }
291 }
292 
293 /* static */
296 {
297  const char* bufptr = p.buffer;
298  vrpn_int32 num;
300 
301  // Read the parameters from the buffer
302  vrpn_unbuffer(&bufptr, &num);
303 
304  if (num >= 0 && num <= vrpn_CHANNEL_MAX) {
305  me->o_num_channel = num;
306  }
307  else {
308  fprintf(
309  stderr,
310  "vrpn_Analog_Output_Remote::handle_report_num_channels_message: "
311  "Someone sent us a bogus number of channels: %d.\n",
312  num);
313  }
314  return 0;
315 }
316 
318  unsigned int chan, vrpn_float64 val, vrpn_uint32 class_of_service)
319 {
320  // msgbuf must be float64-aligned!
321  vrpn_float64 fbuf[2];
322  char* msgbuf = (char*)fbuf;
323 
324  vrpn_int32 len;
325 
327  len = encode_change_to(msgbuf, chan, val);
328  if (d_connection &&
330  msgbuf, class_of_service)) {
331  fprintf(stderr,
332  "vrpn_Analog_Output_Remote: cannot write message: tossing\n");
333  return false;
334  }
335 
336  return true;
337 }
338 
340  int num, vrpn_float64* vals, vrpn_uint32 class_of_service)
341 {
342  if (num < 0 || num > vrpn_CHANNEL_MAX) {
343  fprintf(stderr, "vrpn_Analog_Output_Remote: cannot change channels: "
344  "number of channels out of range\n");
345  return false;
346  }
347 
348  vrpn_float64 fbuf[1 + vrpn_CHANNEL_MAX];
349  char* msgbuf = (char*)fbuf;
350  vrpn_int32 len;
351 
353  len = encode_change_channels_to(msgbuf, num, vals);
354  if (d_connection &&
356  d_sender_id, msgbuf, class_of_service)) {
357  fprintf(stderr,
358  "vrpn_Analog_Output_Remote: cannot write message: tossing\n");
359  return false;
360  }
361  return true;
362 }
363 
365  vrpn_int32 chan,
366  vrpn_float64 val)
367 {
368  // Message includes: int32 channel_number, int32 padding, float64
369  // request_value
370  // Byte order of each needs to be reversed to match network standard
371 
372  vrpn_int32 pad = 0;
373  int buflen = 2 * sizeof(vrpn_int32) + sizeof(vrpn_float64);
374 
375  vrpn_buffer(&buf, &buflen, chan);
376  vrpn_buffer(&buf, &buflen, pad);
377  vrpn_buffer(&buf, &buflen, val);
378 
379  return 2 * sizeof(vrpn_int32) + sizeof(vrpn_float64);
380 }
381 
382 vrpn_int32
384  vrpn_float64* vals)
385 {
386  int i;
387  vrpn_int32 pad = 0;
388  int buflen = 2 * sizeof(vrpn_int32) + num * sizeof(vrpn_float64);
389 
390  vrpn_buffer(&buf, &buflen, num);
391  vrpn_buffer(&buf, &buflen, pad);
392  for (i = 0; i < num; i++) {
393  vrpn_buffer(&buf, &buflen, vals[i]);
394  }
395 
396  return 2 * sizeof(vrpn_int32) + num * sizeof(vrpn_float64);
397 }
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
vrpn_Analog_Output_Server(const char *name, vrpn_Connection *c, vrpn_int32 numChannels=vrpn_CHANNEL_MAX)
struct timeval msg_time
struct timeval o_timestamp
virtual bool request_change_channels(int num, vrpn_float64 *vals, vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
vrpn_int32 request_channels_m_id
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail...
static int VRPN_CALLBACK handle_report_num_channels(void *userdata, vrpn_HANDLERPARAM p)
vrpn_int32 setNumChannels(vrpn_int32 sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
void client_mainloop(void)
Handles functions that all clients should provide in their mainloop() (warning of no server...
virtual ~vrpn_Analog_Output_Server(void)
const char * buffer
vrpn_float64 o_channel[vrpn_CHANNEL_MAX]
static int VRPN_CALLBACK handle_got_connection(void *userdata, vrpn_HANDLERPARAM p)
Used to notify us when a new connection is requested, so that we can let the client know how many cha...
vrpn_Analog_Output_Remote(const char *name, vrpn_Connection *c=NULL)
virtual vrpn_int32 encode_change_channels_to(char *buf, vrpn_int32 num, vrpn_float64 *vals)
vrpn_Callback_List< vrpn_ANALOGOUTPUTCB > d_callback_list
List of user-level routines that need to be called back to let them know that the values have changed...
virtual bool report_num_channels(vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
Generic connection class not specific to the transport mechanism.
const vrpn_float64 * o_channels(void) const
Exposes an array of values for the user to read from.
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
virtual int init(void)
Initialize things that the constructor can&#39;t. Returns 0 on success, -1 on failure.
vrpn_int32 getNumChannels() const
virtual ~vrpn_Analog_Output_Remote(void)
static int VRPN_CALLBACK handle_request_channels_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to change a number of channels Derived class must either install handlers for t...
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
const vrpn_float64 * channel
vrpn_Connection * d_connection
Connection that this object talks to.
This structure is what is passed to a vrpn_Connection message callback.
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
vrpn_int32 got_connection_m_id
vrpn_int32 report_num_channels_m_id
const char * vrpn_got_connection
virtual bool request_change_channel_value(unsigned int chan, vrpn_float64 val, vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
virtual vrpn_int32 encode_num_channels_to(char *buf, vrpn_int32 num)
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message...
Definition: vrpn_Shared.C:241
#define vrpn_CHANNEL_MAX
Definition: vrpn_Analog.h:16
static int VRPN_CALLBACK handle_change_message(void *userdata, vrpn_HANDLERPARAM p)
Handles BOTH types of changes messages, and will be called after the vrpn_Analog_Output_Server class ...
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
static int VRPN_CALLBACK handle_request_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to change one of the values by setting the channel to that value. Derived class must either install handlers for this routine or else make its own routines to handle the request message.
vrpn_int32 d_sender_id
Sender ID registered with the connection.
vrpn_Analog_Output_Callback_Server(const char *name, vrpn_Connection *c, vrpn_int32 numChannels=vrpn_CHANNEL_MAX)
virtual vrpn_int32 encode_change_to(char *buf, vrpn_int32 chan, vrpn_float64 val)
vrpn_Analog_Output(const char *name, vrpn_Connection *c=NULL)
virtual vrpn_int32 register_message_type(const char *name)
void call_handlers(const CALLBACK_STRUCT &info)
This will pass the referenced parameter as a const to all the callbacks.