vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Imager_Stream_Buffer.h
Go to the documentation of this file.
1 #ifndef VRPN_IMAGER_STREAM_BUFFER_H
2 #define VRPN_IMAGER_STREAM_BUFFER_H
3 #include <string.h> // for NULL, strcpy, strlen
4 
6 #include "vrpn_Configure.h" // for VRPN_CALLBACK, VRPN_API
7 #include "vrpn_Connection.h" // for vrpn_Connection (ptr only), etc
8 #include "vrpn_Imager.h"
9 #include "vrpn_Shared.h" // for vrpn_Semaphore, etc
10 #include "vrpn_Types.h" // for vrpn_int32, vrpn_uint16
11 
12 // This is a fairly complicated class that implements a multi-threaded
13 // full-rate logger and partial-rate forwarder for a vrpn_Imager_Server
14 // object. It is intended to allow previewing of microscopy experiments
15 // at a subset of the camera's video rate while logging the video at
16 // full rate, possibly on a remote computer and possibly on the original
17 // video server computer. Its architecture is described in the "Full-rate
18 // logging" section of the vrpn_Imager.html document in the VRPN web
19 // page.
20 
21 //-------------------------------------------------------------------
22 // This is a helper class for the vrpn_Imager_Stream_Shared_State class
23 // below. It keeps a linked list of vrpn_HANDLERPARAM types and the
24 // buffers to which they point. The buffers need to be allocated by
25 // the one who inserts to this list and deleted by the one who pulls
26 // elements from this list.
27 
29 public:
31  {
32  d_first = d_last = NULL;
33  d_count = 0;
34  };
36  {
37  while (d_first != NULL) {
38  struct d_ELEMENT *next = d_first->next;
39  delete d_first;
40  d_first = next;
41  }
42  }
43 
44  // Give the length of the list.
45  unsigned size(void) const { return d_count; }
46 
47  // Insert an element into the list. Return false if fails.
49  {
50  struct d_ELEMENT *el = new struct d_ELEMENT;
51  if (el == NULL) {
52  return false;
53  }
54  el->p = p;
55  el->next = NULL;
56  if (d_last != NULL) {
57  d_last->next = el;
58  }
59  d_last = el;
60  if (d_first == NULL) {
61  d_first = el;
62  }
63  d_count++;
64  return true;
65  }
66 
67  // Remove an element from the list. Return false if fails.
69  {
70  if (p == NULL) {
71  return false;
72  }
73  if (size() == 0) {
74  return false;
75  }
76 
77  *p = d_first->p;
78  if (d_last == d_first) {
79  d_last = NULL;
80  }
81  struct d_ELEMENT *temp = d_first;
82  d_first = d_first->next;
83  delete temp;
84 
85  d_count--;
86  return true;
87  }
88 
89 protected:
90  struct d_ELEMENT {
92  struct d_ELEMENT *next;
93  };
94  struct d_ELEMENT *d_first, *d_last;
95  unsigned d_count;
96 };
97 
98 //-------------------------------------------------------------------
99 // This is the data structure that is shared between the initial
100 // thread (which listens for client connections) and the non-blocking logging
101 // thread that sometimes exists to listen to the vrpn_Imager_Server.
102 // All of its methods must be thread-safe, so it creates a semaphore
103 // for access and uses it in all of the non-atomic methods.
104 // Note that some of the things in here are pointers to objects that
105 // are in the parent class, and they are here just to provide the
106 // semaphore protection. The parent class should only access these
107 // things through this shared state object.
108 
110 public:
112 
113  // Reset the shared state to what it should be at
114  // the time the logging thread is started.
115  void init(void)
116  {
117  d_time_to_exit = false;
118  d_description_updated = false;
119  d_nRows = d_nCols = d_nDepth = d_nChannels = 0;
120  d_new_log_request = false;
121  d_request_lil = NULL;
122  d_request_lol = NULL;
123  d_request_ril = NULL;
124  d_request_rol = NULL;
125  d_new_log_result = false;
126  d_result_lil = NULL;
127  d_result_lol = NULL;
128  d_result_ril = NULL;
129  d_result_rol = NULL;
130  d_new_throttle_request = false;
131  d_throttle_count = -1;
132  d_frames_in_queue = 0;
133  }
134 
135  // Accessors for the "time to exit" flag; set by the initial thread and
136  // read by the logging thread.
137  bool time_to_exit(void)
138  {
139  d_sem.p();
140  bool ret = d_time_to_exit;
141  d_sem.v();
142  return ret;
143  }
144  void time_to_exit(bool do_exit)
145  {
146  d_sem.p();
147  d_time_to_exit = do_exit;
148  d_sem.v();
149  }
150 
151  // Accessors for the parameters stored based on the
152  // imager server's reports. Returns false if nothing has
153  // been set since the last time it was read, true (and fills in
154  // the values) if it has. Channel buffer must be delete [] by
155  // the one calling this function iff the function returns true.
156  bool get_imager_description(vrpn_int32 &nRows, vrpn_int32 &nCols,
157  vrpn_int32 &nDepth, vrpn_int32 &nChannels,
158  const char **channelBuffer)
159  {
160  d_sem.p();
161  bool ret = d_description_updated;
162  if (d_description_updated) {
163  nRows = d_nRows;
164  nCols = d_nCols;
165  nDepth = d_nDepth;
166  nChannels = d_nChannels;
167  *channelBuffer = d_channel_buffer;
168  }
169  d_description_updated = false;
170  d_sem.v();
171  return ret;
172  }
173  bool set_imager_description(vrpn_int32 nRows, vrpn_int32 nCols,
174  vrpn_int32 nDepth, vrpn_int32 nChannels,
175  const char *channelBuffer)
176  {
177  d_sem.p();
178  d_nRows = nRows;
179  d_nCols = nCols;
180  d_nDepth = nDepth;
181  d_nChannels = nChannels;
182  d_channel_buffer = channelBuffer;
183  d_description_updated = true;
184  d_sem.v();
185  return true;
186  }
187 
188  // Accessors for the initial thread to pass new logfile names down to the
189  // logging thread, which will cause it to initiate a changeover of logging
190  // connections. Space for the return strings will be allocated in these
191  // functions
192  // and must be deleted by the logging thread ONLY IF the get function fills
193  // the
194  // values in (it returns true if it does).
195  // NOTE: this is used to query BOTH the presence of new logfile names
196  // AS WELL AS the names themselves. this function will only return values
197  // if new logfile names have been requested since the last time this
198  // function was called.
199  bool get_logfile_request(char **lil, char **lol, char **ril, char **rol)
200  {
201  d_sem.p();
202  bool ret = d_new_log_request;
203  if (d_new_log_request) {
204  // Allocate space to return the names in the handles passed in.
205  // Copy the values from our local storage to the return values.
206  if ((*lil = new char[strlen(d_request_lil) + 1]) != NULL) {
207  strcpy(*lil, d_request_lil);
208  }
209  if ((*lol = new char[strlen(d_request_lol) + 1]) != NULL) {
210  strcpy(*lol, d_request_lol);
211  }
212  if ((*ril = new char[strlen(d_request_ril) + 1]) != NULL) {
213  strcpy(*ril, d_request_ril);
214  }
215  if ((*rol = new char[strlen(d_request_rol) + 1]) != NULL) {
216  strcpy(*rol, d_request_rol);
217  }
218 
219  // Delete and NULL the local storage pointers.
220  delete[] d_request_lil;
221  d_request_lil = NULL;
222  delete[] d_request_lol;
223  d_request_lol = NULL;
224  delete[] d_request_ril;
225  d_request_ril = NULL;
226  delete[] d_request_rol;
227  d_request_rol = NULL;
228  }
229  d_new_log_request = false;
230  d_sem.v();
231  return ret;
232  }
233 
234  void set_logfile_request(const char *lil, const char *lol, const char *ril,
235  const char *rol)
236  {
237  d_sem.p();
238 
239  // delete file names, in case the logging thread hasn't had a chance to
240  // honor the request yet.
241  if (d_request_lil) {
242  delete[] d_request_lil;
243  d_request_lil = NULL;
244  }
245  if (d_request_lol) {
246  delete[] d_request_lol;
247  d_request_lol = NULL;
248  }
249  if (d_request_ril) {
250  delete[] d_request_ril;
251  d_request_ril = NULL;
252  }
253  if (d_request_rol) {
254  delete[] d_request_rol;
255  d_request_rol = NULL;
256  }
257 
258  // Allocate space for each string and then copy into it.
259  if (lil != NULL) {
260  if ((d_request_lil = new char[strlen(lil) + 1]) != NULL) {
261  strcpy(d_request_lil, lil);
262  }
263  }
264  if (lol != NULL) {
265  if ((d_request_lol = new char[strlen(lol) + 1]) != NULL) {
266  strcpy(d_request_lol, lol);
267  }
268  }
269  if (ril != NULL) {
270  if ((d_request_ril = new char[strlen(ril) + 1]) != NULL) {
271  strcpy(d_request_ril, ril);
272  }
273  }
274  if (rol != NULL) {
275  if ((d_request_rol = new char[strlen(rol) + 1]) != NULL) {
276  strcpy(d_request_rol, rol);
277  }
278  }
279 
280  d_new_log_request = true;
281  d_sem.v();
282  }
283 
284  // Accessors for the logfile thread to pass new logfile names back up to the
285  // initial thread, reporting a changeover of logging connections.
286  // Space for the return strings will be allocated in these functions
287  // and must be deleted by the initial thread ONLY IF the get function fills
288  // the
289  // values in (it returns true if it does).
290  // NOTE: this function is intended to query BOTH the logfile names AS WELL
291  // AS
292  // the change in logging status. it ONLY returns filenames if logging has
293  // changed since the last time this function was called).
294  bool get_logfile_result(char **lil, char **lol, char **ril, char **rol)
295  {
296  d_sem.p();
297  bool ret = d_new_log_result;
298  if (d_new_log_result) {
299  // Allocate space to return the names in the handles passed in.
300  // Copy the values from our local storage to the return values.
301  if (d_result_lil == NULL)
302  *lil = NULL;
303  else {
304  if ((*lil = new char[strlen(d_result_lil) + 1]) != NULL) {
305  strcpy(*lil, d_result_lil);
306  }
307  }
308  if (d_result_lol == NULL)
309  *lol = NULL;
310  else {
311  if ((*lol = new char[strlen(d_result_lol) + 1]) != NULL) {
312  strcpy(*lol, d_result_lol);
313  }
314  }
315  if (d_result_ril == NULL)
316  *ril = NULL;
317  else {
318  if ((*ril = new char[strlen(d_result_ril) + 1]) != NULL) {
319  strcpy(*ril, d_result_ril);
320  }
321  }
322  if (d_result_rol == NULL)
323  *rol = NULL;
324  else {
325  if ((*rol = new char[strlen(d_result_rol) + 1]) != NULL) {
326  strcpy(*rol, d_result_rol);
327  }
328  }
329 
330  // do not Delete and NULL the local storage pointers.
331  // someone may request the filenames later.
332  }
333  d_new_log_result = false;
334  d_sem.v();
335  return ret;
336  }
337 
338  void set_logfile_result(const char *lil, const char *lol, const char *ril,
339  const char *rol)
340  {
341  d_sem.p();
342 
343  if (d_result_lil) delete[] d_result_lil;
344  d_result_lil = NULL;
345  if (d_result_lol) delete[] d_result_lol;
346  d_result_lol = NULL;
347  if (d_result_ril) delete[] d_result_ril;
348  d_result_ril = NULL;
349  if (d_result_rol) delete[] d_result_rol;
350  d_result_rol = NULL;
351 
352  // Allocate space for each string and then copy into it.
353  if (lil != NULL) {
354  if ((d_result_lil = new char[strlen(lil) + 1]) != NULL) {
355  strcpy(d_result_lil, lil);
356  }
357  }
358  if (lol != NULL) {
359  if ((d_result_lol = new char[strlen(lol) + 1]) != NULL) {
360  strcpy(d_result_lol, lol);
361  }
362  }
363  if (ril != NULL) {
364  if ((d_result_ril = new char[strlen(ril) + 1]) != NULL) {
365  strcpy(d_result_ril, ril);
366  }
367  }
368  if (rol != NULL) {
369  if ((d_result_rol = new char[strlen(rol) + 1]) != NULL) {
370  strcpy(d_result_rol, rol);
371  }
372  }
373 
374  d_new_log_result = true;
375  d_sem.v();
376  }
377 
378  // fills in the arguments with the logfile names currently in use
379  // for a particular log, the value will be NULL if that log is not being
380  // collected.
381  // NOTE: this function allocates memory for each string returned. IT IS
382  // THE
383  // RESPONSIBILITY OF THE CALLING FUNCTION TO FREE THIS MEMORY.
384  void get_logfile_names(char **local_in, char **local_out, char **remote_in,
385  char **remote_out)
386  {
387  d_sem.p();
388  if (d_result_lil == NULL)
389  *local_in = NULL;
390  else {
391  *local_in = new char[strlen(d_result_lil) + 1];
392  strcpy(*local_in, d_result_lil);
393  }
394  if (d_result_lol == NULL)
395  *local_out = NULL;
396  else {
397  *local_out = new char[strlen(d_result_lol) + 1];
398  strcpy(*local_out, d_result_lol);
399  }
400  if (d_result_ril == NULL)
401  *remote_in = NULL;
402  else {
403  *remote_in = new char[strlen(d_result_ril) + 1];
404  strcpy(*remote_in, d_result_ril);
405  }
406  if (d_result_rol == NULL)
407  *remote_out = NULL;
408  else {
409  *remote_out = new char[strlen(d_result_rol) + 1];
410  strcpy(*remote_out, d_result_rol);
411  }
412  d_sem.v();
413  }
414 
415  // Accessors for the initial thread to pass new throttle values down to the
416  // logging thread, which will cause it to throttle as needed.
417  bool get_throttle_request(vrpn_int32 *throttle_count)
418  {
419  d_sem.p();
420  bool ret = d_new_throttle_request;
421  if (d_new_throttle_request) {
422  *throttle_count = d_throttle_count;
423  }
424  d_new_throttle_request = false;
425  d_sem.v();
426  return ret;
427  }
428  void set_throttle_request(vrpn_int32 throttle_count)
429  {
430  d_sem.p();
431  d_throttle_count = throttle_count;
432  d_new_throttle_request = true;
433  d_sem.v();
434  }
435 
436  // Accessors for the logging thread to increment and read the number of
437  // frames in the queue and for the initial thread to decrement them. The
438  // increment/decrement is done when a begin_frame message is found. The
439  // increment/decrement routines return the new value.
440  vrpn_int32 get_frames_in_queue(void)
441  {
442  d_sem.p();
443  vrpn_int32 ret = d_frames_in_queue;
444  d_sem.v();
445  return ret;
446  }
447  vrpn_int32 increment_frames_in_queue(void)
448  {
449  d_sem.p();
450  d_frames_in_queue++;
451  vrpn_int32 ret = d_frames_in_queue;
452  d_sem.v();
453  return ret;
454  }
455  vrpn_int32 decrement_frames_in_queue(void)
456  {
457  d_sem.p();
458  d_frames_in_queue--;
459  vrpn_int32 ret = d_frames_in_queue;
460  d_sem.v();
461  return ret;
462  }
463 
464  // Accessors for the logging thread to add messages to the queue
465  // and for the initial thread to retrieve and count them.
467  {
468  d_sem.p();
469  vrpn_int32 ret = d_logger_to_client_messages.size();
470  d_sem.v();
471  return ret;
472  }
474  {
475  d_sem.p();
476  bool ret = d_logger_to_client_messages.insert_back(p);
477  d_sem.v();
478  return ret;
479  }
481  {
482  d_sem.p();
483  bool ret = d_logger_to_client_messages.retrieve_front(p);
484  d_sem.v();
485  return ret;
486  }
487 
488 protected:
489  vrpn_Semaphore d_sem; // Semaphore to control access to data items.
490 
491  // Is it time for the logging thread to exit?
493 
494  // Stored copies of the value in the vrpn_Imager_Remote and a flag telling
495  // whether they have changed since last read.
496  bool d_description_updated; // Do we have a new description from imager
497  // server?
498  vrpn_int32 d_nRows;
499  vrpn_int32 d_nCols;
500  vrpn_int32 d_nDepth;
501  vrpn_int32 d_nChannels;
502  const char *d_channel_buffer; //< Allocated by sender, freed by receiver
503 
504  // Names of the log files passed from the initial thread to the logging
505  // thread and a flag telling whether they have been changed since last
506  // read.
512 
513  // Names of the log files passed from the logging thread to the initial
514  // thread and a flag telling whether they have been changed since last
515  // read. NOTE: we maintain a copy of the log file names here, instead
516  // of using the accessor of vrpn_Connection to query the names. Only
517  // the logging thread is supposed to have access to the logging connection,
518  // but the logging thread is banned from calling methods on the client
519  // connection.
525 
526  // New throttle request passed on by the client-handling thread
528  vrpn_int32 d_throttle_count;
529 
530  // Records the number of frames in the queue. This is incremented
531  // by the non-blocking thread and decremented by the initial thread
532  // as the begin_frame() messages are queued and dequeued.
533  vrpn_int32 d_frames_in_queue;
534 
535  // List of messages passing from the logging thread to the initial
536  // thread.
538 };
539 
540 //-------------------------------------------------------------------
541 // This class is a vrpn_Imager_Server; it has one or two instances of
542 // vrpn_Imager_Clients to talk to the server it is forwarding packets
543 // to. It does not use their callback parsers, but rather hooks its own
544 // callbacks directly to the connection object for the server it is
545 // buffering.
546 
548  public vrpn_Imager_Server {
549 public:
550  // Name of this object (the server side of the vrpn_Imager that is
551  // buffered and the vrpn_Auxiliary_Logger that the client will connect to).
552  // (Optional, can be NULL) pointer to the server connection on which to
553  // communicate.
554  // Name of the vrpn_Imager_Server to connect to (packets from this server
555  // will
556  // be forwarded to the main connection, and logging will occur on the
557  // connection
558  // to this imager_server). This server may be local or remote; if local,
559  // include "@localhost" in the name because new connections will be made to
560  // it.
561  vrpn_Imager_Stream_Buffer(const char *name, const char *imager_server_name,
562  vrpn_Connection *c);
563 
564  // Get rid of any logging thread and then clean up.
565  virtual ~vrpn_Imager_Stream_Buffer();
566 
567  // Required for servers.
568  virtual void mainloop(void);
569 
570 protected:
571  // Handle a logging-request message. The request contains four file
572  // names, two for local (to the Auxiliary server itself) and two for
573  // remote (the far side of its connection to the server). It must
574  // also respond to the client with a message saying what logging has
575  // been set up (using the send_logging_response function). Logging is
576  // turned off on a particular file by sending an empty-string name ("").
577  // The in/out local/remote are with respect to the connection that the
578  // logging is to occur on, which is to the imager server whose name is
579  // passed in to the constructor, not the connection that the client has
580  // sent the request on.
581  // Make sure to send a response saying what you did.
582  virtual void handle_request_logging(const char *local_in_logfile_name,
583  const char *local_out_logfile_name,
584  const char *remote_in_logfile_name,
585  const char *remote_out_logfile_name);
586 
587  // Static portion of handling (unpacking) the request_logging message. It
588  // then calls the non-static virtual method above.
589  static int VRPN_CALLBACK
591 
592  virtual void handle_request_logging_status();
593 
594  // Handle dropped last connection on our primary connection by shutting down
595  // the
596  // connection to the imager server. The static method in the base class
597  // looks up this
598  // pointer and calls the virtual method.
599  virtual void handle_dropped_last_connection(void);
600 
601  // Handles a throttle request by passing it on down to the non-blocking
602  // thread to deal with.
603  static int VRPN_CALLBACK
604  static_handle_throttle_message(void *userdata, vrpn_HANDLERPARAM p);
605 
606  // Handle got first connection request by (having the second thread) create
607  // a connection to the server and waiting until we get a description message
608  // from the imager server we're listening to. Timeout after a while if the
609  // connection cannot be made or the server does not respond.
610  virtual void handle_got_first_connection(void);
611  vrpn_int32 got_first_connection_m_id; // ID of message that we got the first
612  // connection
613  static int VRPN_CALLBACK
614  static_handle_got_first_connection(void *userdata, vrpn_HANDLERPARAM p);
615 
616  // State shared between the initial thread and the logging thread.
618 
619  //----------------------------------------------------------------------
620  // The section below includes methods and member variables that should
621  // only be used by the logging thread. They are not protected by
622  // semaphores and so should not be accessed except within the
623  // logging_thread_func().
624 
625  // This class spawns a new thread to handle uninterrupted communication
626  // and logging with the vrpn_Imager_Server that we are forwarding messages
627  // for. This is created in the constructor and shut down (hopefully gently)
628  // in the destructor. There are a number of semaphores that are used by
629  // the initial thread and the logging thread to communicate.
631 
632  // The function that is called to become the logging thread. It is passed
633  // a pointer to "this" so that it can acces the object that created it.
634  // Note that it must use semaphores to get at the data that will be shared
635  // between the main thread and itself. The static function basically just
636  // pulls the "this" pointer out and then calls the non-static function.
637  static void static_logging_thread_func(vrpn_ThreadData &threadData);
638  void logging_thread_func(void);
639 
640  // Stop the logging thread function, cleanly if possible. Returns true if
641  // the function stopped cleanly, false if it had to be killed.
642  bool stop_logging_thread(void);
643 
644  // Name of the vrpn_Imager_Server object we are to connect to and
645  // log/pass messages from.
647 
648  // Are we ready to drop the old connection (new one has received its
649  // descriptor message)?
651 
652  // The connection that is used to talk to the client.
655  open_new_log_connection(const char *local_in_logfile_name,
656  const char *local_out_logfile_name,
657  const char *remote_in_logfile_name,
658  const char *remote_out_logfile_name);
659 
660  // These will create/destroy the d_imager_remote and other callback handlers
661  // needed to provide the handling of messages from the logging connection
662  // passed in; they are used by the initial-connection code and by the
663  // code that handles handing off from an old connection to a new connection
664  // when a new logging message is received.
665  bool setup_handlers_for_logging_connection(vrpn_Connection *c);
666  bool teardown_handlers_for_logging_connection(vrpn_Connection *c);
667 
668  // This is yet another "create me some logs" function; it handles the
669  // hand-off from one log file to another within the logging thread.
670  // It is called by the main logging thread function when a request comes in
671  // from the initial thread to perform logging.
672  bool make_new_logging_connection(const char *local_in_logfile_name,
673  const char *local_out_logfile_name,
674  const char *remote_in_logfile_name,
675  const char *remote_out_logfile_name);
676 
677  // The imager remote to listen to the vrpn_Imager_Server, along
678  // with the callback functions that support its operation. The
679  // generic VRPN callback handler that receives all messages from
680  // the imager server and either queues them or handles them, there
681  // is a static version that just gets a this pointer and calls the
682  // non-static function.
684  static void VRPN_CALLBACK
685  handle_image_description(void *pvISB, const struct timeval msg_time);
686  static int VRPN_CALLBACK
687  static_handle_server_messages(void *pvISB, vrpn_HANDLERPARAM p);
688  int handle_server_messages(const vrpn_HANDLERPARAM &p);
689 
690  // Types of messages we expect to be coming from the server.
691  vrpn_int32 d_server_description_m_id; //< ID of the message type describing
692  // the range and channels
693  vrpn_int32 d_server_begin_frame_m_id; //< ID of the message type describing
694  // the start of a region
695  vrpn_int32 d_server_end_frame_m_id; //< ID of the message type describing
696  // the start of a region
697  vrpn_int32 d_server_discarded_frames_m_id; //< ID of the message type
698  // describing the discarding of
699  // one or more regions
700  vrpn_int32 d_server_regionu8_m_id; //< ID of the message type describing a
701  // region with 8-bit unsigned entries
702  vrpn_int32 d_server_regionu12in16_m_id; //< ID of the message type
703  // describing a region with 12-bit
704  // unsigned entries packed in 16 bits
705  vrpn_int32 d_server_regionu16_m_id; //< ID of the message type describing a
706  // region with 16-bit unsigned entries
707  vrpn_int32 d_server_regionf32_m_id; //< ID of the message type describing a
708  // region with 32-bit float entries
709  vrpn_int32 d_server_text_m_id; //< ID of the system text message
710  vrpn_int32 d_server_ping_m_id; //< ID of the system ping message
711  vrpn_int32 d_server_pong_m_id; //< ID of the system pong message
712 
713  // Transcode the sender and type fields from the logging server connection
714  // to
715  // the initial client connection and pack the resulting message into the
716  // queue
717  // from the logging thread to the initial thread. The data buffer is
718  // copied;
719  // this space is allocated by the logging thread and must be freed by the
720  // initial thread.
721  // Returns true on success and false on failure. The sender is set to the
722  // d_sender_id of our server object.
723  bool transcode_and_send(const vrpn_HANDLERPARAM &p);
724 
725  // Transcode the type from the logging thread's connection type to
726  // the initial thread's connection type. Return -1 if we don't
727  // recognize the type.
728  vrpn_int32 transcode_type(vrpn_int32 type);
729 
730  // Handling throttling on the non-blocking thread. This is a shadow
731  // copy of the structures in the vrpn_Image_Server base class; we cannot
732  // use those directly because they will be adjusted by their own callbacks
733  // in the initial thread.
736 };
737 
738 //-----------------------------------------------------------
739 // Client code should connect to the server twice, once as
740 // a vrpn_Imager_Server and once as a vrpn_Auxiliary_Logger_Server.
741 // There is not a special remote class for this.
742 
743 #endif
bool set_imager_description(vrpn_int32 nRows, vrpn_int32 nCols, vrpn_int32 nDepth, vrpn_int32 nChannels, const char *channelBuffer)
bool insert_back(const vrpn_HANDLERPARAM &p)
virtual void handle_request_logging_status()=0
bool get_logfile_result(char **lil, char **lol, char **ril, char **rol)
void set_logfile_result(const char *lil, const char *lol, const char *ril, const char *rol)
bool get_logfile_request(char **lil, char **lol, char **ril, char **rol)
virtual void handle_request_logging(const char *local_in_logfile_name, const char *local_out_logfile_name, const char *remote_in_logfile_name, const char *remote_out_logfile_name)=0
This is the class users deal with: it tells the format and the region data when it arrives.
Definition: vrpn_Imager.h:623
Generic connection class not specific to the transport mechanism.
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
bool get_imager_description(vrpn_int32 &nRows, vrpn_int32 &nCols, vrpn_int32 &nDepth, vrpn_int32 &nChannels, const char **channelBuffer)
vrpn_Imager_Stream_Shared_State d_shared_state
#define VRPN_CALLBACK
#define VRPN_API
unsigned size(void) const
struct d_ELEMENT * d_last
void set_logfile_request(const char *lil, const char *lol, const char *ril, const char *rol)
bool retrieve_logger_to_client_message(vrpn_HANDLERPARAM *p)
This structure is what is passed to a vrpn_Connection message callback.
bool retrieve_front(vrpn_HANDLERPARAM *p)
static int VRPN_CALLBACK static_handle_request_logging(void *userdata, vrpn_HANDLERPARAM p)
bool insert_logger_to_client_message(const vrpn_HANDLERPARAM &p)
virtual void handle_dropped_last_connection(void)
void get_logfile_names(char **local_in, char **local_out, char **remote_in, char **remote_out)
void set_throttle_request(vrpn_int32 throttle_count)
bool get_throttle_request(vrpn_int32 *throttle_count)