vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Imager.C
Go to the documentation of this file.
1 #include <stdio.h> // for fprintf, stderr, printf
2 #include <string.h> // for memcpy, NULL, strncpy
3 
4 #include "vrpn_Imager.h"
5 
7  : vrpn_BaseClass(name, c)
8  , d_nRows(0)
9  , d_nCols(0)
10  , d_nDepth(0)
11  , d_nChannels(0)
12 {
14 }
15 
17 {
19  d_connection->register_message_type("vrpn_Imager Description");
21  d_connection->register_message_type("vrpn_Imager Begin_Frame");
23  d_connection->register_message_type("vrpn_Imager End_Frame");
25  d_connection->register_message_type("vrpn_Imager Discarded_Frames");
27  d_connection->register_message_type("vrpn_Imager Throttle_Frames");
29  d_connection->register_message_type("vrpn_Imager Regionu8");
31  d_connection->register_message_type("vrpn_Imager Regionu16");
33  d_connection->register_message_type("vrpn_Imager Regionu12in16");
35  d_connection->register_message_type("vrpn_Imager Regionf32");
36  if ((d_description_m_id == -1) || (d_regionu8_m_id == -1) ||
37  (d_regionu16_m_id == -1) || (d_regionf32_m_id == -1) ||
38  (d_begin_frame_m_id == -1) || (d_end_frame_m_id == -1) ||
40  return -1;
41  }
42  else {
43  return 0;
44  }
45 }
46 
48  vrpn_int32 nCols, vrpn_int32 nRows,
49  vrpn_int32 nDepth)
50  : vrpn_Imager(name, c)
51  , d_description_sent(false)
52  , d_frames_to_send(-1)
53  , d_dropped_due_to_throttle(0)
54 {
55  d_nRows = nRows;
56  d_nCols = nCols;
57  d_nDepth = nDepth;
58 
59  // Set up callback handler for ping message from client so that it
60  // sends the description. This will make sure that the other side has
61  // heard the descrption before it hears a region message. Also set this up
62  // to fire on the "new connection" system message.
63 
65  d_sender_id);
69 
70  // Set up a handler for the throttle message, which sets how many more
71  // frames to send before dropping them. Also set up a handler for the
72  // last-connection-dropped message, which will cause throttling to go
73  // back to -1.
79 }
80 
81 int vrpn_Imager_Server::add_channel(const char *name, const char *units,
82  vrpn_float32 minVal, vrpn_float32 maxVal,
83  vrpn_float32 scale, vrpn_float32 offset)
84 {
85  if (static_cast<unsigned>(d_nChannels) >= vrpn_IMAGER_MAX_CHANNELS) {
86  return -1;
87  }
88  strncpy(d_channels[d_nChannels].name, name, sizeof(cName));
89  strncpy(d_channels[d_nChannels].units, units, sizeof(cName));
90  d_channels[d_nChannels].minVal = minVal;
91  d_channels[d_nChannels].maxVal = maxVal;
92  if (scale == 0) {
93  fprintf(
94  stderr,
95  "vrpn_Imager_Server::add_channel(): Scale was zero, set to 1\n");
96  scale = 1;
97  }
98  d_channels[d_nChannels].scale = scale;
99  d_channels[d_nChannels].offset = offset;
100  d_nChannels++;
101 
102  // We haven't sent a proper description now
103  d_description_sent = false;
104  return d_nChannels - 1;
105 }
106 
108  const vrpn_uint16 cMin, const vrpn_uint16 cMax, const vrpn_uint16 rMin,
109  const vrpn_uint16 rMax, const vrpn_uint16 dMin, const vrpn_uint16 dMax,
110  const struct timeval *time)
111 {
112  // msgbuf must be float64-aligned! It is the buffer to send to the client
113  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
114  char *msgbuf = (char *)fbuf;
115  int buflen = sizeof(fbuf);
116  struct timeval timestamp;
117 
118  // If we are throttling frames and the frame count has gone to zero,
119  // then increment the number of frames missed and return failure to
120  // send.
121  if (d_frames_to_send == 0) {
123  return false;
124  }
125 
126  // If we missed some frames due to throttling, say so.
127  if (d_dropped_due_to_throttle > 0) {
130  }
131 
132  // If we are throttling, then decrement the number of frames
133  // left to send.
134  if (d_frames_to_send > 0) {
136  }
137 
138  // Make sure the region request has indices all within the image size.
139  if ((rMax >= d_nRows) || (rMin > rMax)) {
140  fprintf(stderr, "vrpn_Imager_Server::send_begin_frame(): Invalid row "
141  "range (%d..%d)\n",
142  rMin, rMax);
143  return false;
144  }
145  if ((cMax >= d_nCols) || (cMin > cMax)) {
146  fprintf(stderr, "vrpn_Imager_Server::send_begin_frame(): Invalid "
147  "column range (%d..%d)\n",
148  cMin, cMax);
149  return false;
150  }
151  if ((dMax >= d_nDepth) || (dMin > dMax)) {
152  fprintf(stderr, "vrpn_Imager_Server::send_begin_frame(): Invalid depth "
153  "range (%d..%d)\n",
154  dMin, dMax);
155  return false;
156  }
157 
158  // If the user didn't specify a time, assume they want "now" and look it up.
159  if (time != NULL) {
160  timestamp = *time;
161  }
162  else {
163  vrpn_gettimeofday(&timestamp, NULL);
164  }
165 
166  // Tell what the borders of the region are.
167  if (vrpn_buffer(&msgbuf, &buflen, dMin) ||
168  vrpn_buffer(&msgbuf, &buflen, dMax) ||
169  vrpn_buffer(&msgbuf, &buflen, rMin) ||
170  vrpn_buffer(&msgbuf, &buflen, rMax) ||
171  vrpn_buffer(&msgbuf, &buflen, cMin) ||
172  vrpn_buffer(&msgbuf, &buflen, cMax)) {
173  return false;
174  }
175 
176  // Pack the message
177  vrpn_int32 len = sizeof(fbuf) - buflen;
178  if (d_connection &&
180  d_sender_id, (char *)(void *)fbuf,
182  fprintf(stderr, "vrpn_Imager_Server::send_begin_frame(): cannot write "
183  "message: tossing\n");
184  return false;
185  }
186 
187  return true;
188 }
189 
191  const vrpn_uint16 cMin, const vrpn_uint16 cMax, const vrpn_uint16 rMin,
192  const vrpn_uint16 rMax, const vrpn_uint16 dMin, const vrpn_uint16 dMax,
193  const struct timeval *time)
194 {
195  // msgbuf must be float64-aligned! It is the buffer to send to the client
196  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
197  char *msgbuf = (char *)fbuf;
198  int buflen = sizeof(fbuf);
199  struct timeval timestamp;
200 
201  // If we are discarding frames, return failure to send.
202  if (d_dropped_due_to_throttle > 0) {
203  return false;
204  }
205 
206  // Make sure the region request has indices all within the image size.
207  if ((rMax >= d_nRows) || (rMin > rMax)) {
208  fprintf(stderr, "vrpn_Imager_Server::send_end_frame(): Invalid row "
209  "range (%d..%d)\n",
210  rMin, rMax);
211  return false;
212  }
213  if ((cMax >= d_nCols) || (cMin > cMax)) {
214  fprintf(stderr, "vrpn_Imager_Server::send_end_frame(): Invalid column "
215  "range (%d..%d)\n",
216  cMin, cMax);
217  return false;
218  }
219  if ((dMax >= d_nDepth) || (dMin > dMax)) {
220  fprintf(stderr, "vrpn_Imager_Server::send_end_frame(): Invalid depth "
221  "range (%d..%d)\n",
222  dMin, dMax);
223  return false;
224  }
225 
226  // If the user didn't specify a time, assume they want "now" and look it up.
227  if (time != NULL) {
228  timestamp = *time;
229  }
230  else {
231  vrpn_gettimeofday(&timestamp, NULL);
232  }
233 
234  // Tell what the borders of the region are.
235  if (vrpn_buffer(&msgbuf, &buflen, dMin) ||
236  vrpn_buffer(&msgbuf, &buflen, dMax) ||
237  vrpn_buffer(&msgbuf, &buflen, rMin) ||
238  vrpn_buffer(&msgbuf, &buflen, rMax) ||
239  vrpn_buffer(&msgbuf, &buflen, cMin) ||
240  vrpn_buffer(&msgbuf, &buflen, cMax)) {
241  return false;
242  }
243 
244  // Pack the message
245  vrpn_int32 len = sizeof(fbuf) - buflen;
246  if (d_connection &&
247  d_connection->pack_message(len, timestamp, d_end_frame_m_id,
248  d_sender_id, (char *)(void *)fbuf,
250  fprintf(stderr, "vrpn_Imager_Server::send_end_frame(): cannot write "
251  "message: tossing\n");
252  return false;
253  }
254 
255  return true;
256 }
257 
258 bool vrpn_Imager_Server::send_discarded_frames(const vrpn_uint16 count,
259  const struct timeval *time)
260 {
261  // msgbuf must be float64-aligned! It is the buffer to send to the client
262  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
263  char *msgbuf = (char *)fbuf;
264  int buflen = sizeof(fbuf);
265  struct timeval timestamp;
266 
267  // If the user didn't specify a time, assume they want "now" and look it up.
268  if (time != NULL) {
269  timestamp = *time;
270  }
271  else {
272  vrpn_gettimeofday(&timestamp, NULL);
273  }
274 
275  // Tell how many frames were skipped.
276  if (vrpn_buffer(&msgbuf, &buflen, count)) {
277  return false;
278  }
279 
280  // Pack the message
281  vrpn_int32 len = sizeof(fbuf) - buflen;
282  if (d_connection &&
284  d_sender_id, (char *)(void *)fbuf,
286  fprintf(stderr, "vrpn_Imager_Server::send_discarded_frames(): cannot "
287  "write message: tossing\n");
288  return false;
289  }
290 
291  return true;
292 }
293 
294 // XXX Re-cast the memcpy loop in terms of offsets (the same way the per-element
295 // loop is done) and share base calculation between the two; move the if
296 // statement
297 // into the inner loop, doing it memcpy or step-at-a-time.
298 
321  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
322  vrpn_uint16 rMax, const vrpn_uint8 *data, vrpn_uint32 colStride,
323  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
324  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
325  const struct timeval *time)
326 {
327  // msgbuf must be float64-aligned! It is the buffer to send to the client;
328  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
329  char *msgbuf = reinterpret_cast<char *>(fbuf);
330  int buflen = sizeof(fbuf);
331  struct timeval timestamp;
332 
333  // If we are discarding frames, return failure to send.
334  if (d_dropped_due_to_throttle > 0) {
335  return false;
336  }
337 
338  // Make sure the region request has a valid channel, has indices all
339  // within the image size, and is not too large to fit into the data
340  // array (which is sized the way it is to make sure it can be sent in
341  // one VRPN reliable message).
342  if ((chanIndex < 0) || (chanIndex >= d_nChannels)) {
343  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
344  "Invalid channel index (%d)\n",
345  chanIndex);
346  return false;
347  }
348  if ((dMax >= d_nDepth) || (dMin > dMax)) {
349  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
350  "Invalid depth range (%d..%d)\n",
351  dMin, dMax);
352  return false;
353  }
354  if ((rMax >= d_nRows) || (rMin > rMax)) {
355  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
356  "Invalid row range (%d..%d)\n",
357  rMin, rMax);
358  return false;
359  }
360  if ((cMax >= d_nCols) || (cMin > cMax)) {
361  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
362  "Invalid column range (%d..%d)\n",
363  cMin, cMax);
364  return false;
365  }
366  if (static_cast<unsigned>((rMax - rMin + 1) * (cMax - cMin + 1) *
367  (dMax - dMin + 1)) > vrpn_IMAGER_MAX_REGIONu8) {
368  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
369  "Region too large (%d,%d,%d to %d,%d,%d)\n",
370  cMin, rMin, dMin, cMax, rMax, dMax);
371  return false;
372  }
373  if (invert_rows && (nRows < rMax)) {
374  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
375  "nRows must not be less than rMax\n");
376  return false;
377  }
378 
379  // Make sure we've sent the description before we send any regions
380  if (!d_description_sent) {
382  d_description_sent = true;
383  }
384 
385  // If the user didn't specify a time, assume they want "now" and look it up.
386  if (time != NULL) {
387  timestamp = *time;
388  }
389  else {
390  vrpn_gettimeofday(&timestamp, NULL);
391  }
392 
393  // Check the compression status and prepare to do compression if it is
394  // called for.
395  if (d_channels[chanIndex].d_compression != vrpn_Imager_Channel::NONE) {
396  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
397  "Compression not implemented\n");
398  return false;
399  }
400 
401  // Tell which channel this region is for, and what the borders of the
402  // region are.
403  if (vrpn_buffer(&msgbuf, &buflen, chanIndex) ||
404  vrpn_buffer(&msgbuf, &buflen, dMin) ||
405  vrpn_buffer(&msgbuf, &buflen, dMax) ||
406  vrpn_buffer(&msgbuf, &buflen, rMin) ||
407  vrpn_buffer(&msgbuf, &buflen, rMax) ||
408  vrpn_buffer(&msgbuf, &buflen, cMin) ||
409  vrpn_buffer(&msgbuf, &buflen, cMax) ||
410  vrpn_buffer(&msgbuf, &buflen, vrpn_IMAGER_VALTYPE_UINT8)) {
411  return false;
412  }
413 
414  // Insert the data into the buffer, copying it as efficiently as possible
415  // from the caller's buffer into the buffer we are going to send. Note that
416  // the send buffer is going to be little-endian. The code looks a little
417  // complicated because it short-circuits the copying for the case where the
418  // column stride is one element long (using memcpy() on each row) but has to
419  // copy one element at a time otherwise.
420  // There is also the matter if deciding whether to invert the image in y,
421  // which complicates the index calculation and the calculation of the
422  // strides.
423  int cols = cMax - cMin + 1;
424  int linelen = cols * sizeof(data[0]);
425  if (colStride == 1) {
426  for (unsigned d = dMin; d <= dMax; d++) {
427  for (unsigned r = rMin; r <= rMax; r++) {
428  unsigned rActual;
429  if (invert_rows) {
430  rActual = (nRows - 1) - r;
431  }
432  else {
433  rActual = r;
434  }
435  if (buflen < linelen) {
436  return false;
437  }
438  memcpy(msgbuf,
439  &data[d * depthStride + rActual * rowStride + cMin],
440  linelen);
441  msgbuf += linelen;
442  buflen -= linelen;
443  }
444  }
445  }
446  else {
447  if (buflen < (int)((dMax - dMin + 1) * (rMax - rMin + 1) *
448  (cMax - cMin + 1) * sizeof(data[0]))) {
449  return false;
450  }
451  long rowStep = rowStride;
452  if (invert_rows) {
453  rowStep *= -1;
454  }
455  for (unsigned d = dMin; d <= dMax; d++) {
456  // XXX Turn the depth calculation into start and += like the others
457  const vrpn_uint8 *rowStart =
458  &data[d * depthStride + rMin * rowStride + cMin];
459  if (invert_rows) {
460  rowStart = &data[d * depthStride +
461  (nRows - 1 - rMin) * rowStride + cMin];
462  }
463  const vrpn_uint8 *copyFrom = rowStart;
464  for (unsigned r = rMin; r <= rMax; r++) {
465  for (unsigned c = cMin; c <= cMax; c++) {
466  *reinterpret_cast<vrpn_uint8 *>(msgbuf) =
467  *copyFrom; //< Copy the current element
468  msgbuf++; //< Skip to the next buffer location
469  copyFrom +=
470  colStride; //< Skip appropriate number of elements
471  }
472  rowStart += rowStep; //< Skip to the start of the next row
473  copyFrom = rowStart;
474  }
475  }
476  buflen -= (rMax - rMin + 1) * (cMax - cMin + 1) * sizeof(data[0]);
477  }
478 
479  // No need to swap endian-ness on single-byte elements.
480 
481  // Pack the message
482  vrpn_int32 len = sizeof(fbuf) - buflen;
483  if (d_connection &&
485  (char *)(void *)fbuf,
487  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
488  "cannot write message: tossing\n");
489  return false;
490  }
491 
492  return true;
493 }
494 
517  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
518  vrpn_uint16 rMax, const vrpn_uint16 *data, vrpn_uint32 colStride,
519  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
520  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
521  const struct timeval *time)
522 {
523  // msgbuf must be float64-aligned! It is the buffer to send to the client
524  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
525  char *msgbuf = (char *)fbuf;
526  int buflen = sizeof(fbuf);
527  struct timeval timestamp;
528 
529  // If we are discarding frames, return failure to send.
530  if (d_dropped_due_to_throttle > 0) {
531  return false;
532  }
533 
534  // Make sure the region request has a valid channel, has indices all
535  // within the image size, and is not too large to fit into the data
536  // array (which is sized the way it is to make sure it can be sent in
537  // one VRPN reliable message).
538  if ((chanIndex < 0) || (chanIndex >= d_nChannels)) {
539  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
540  "Invalid channel index (%d)\n",
541  chanIndex);
542  return false;
543  }
544  if ((dMax >= d_nDepth) || (dMin > dMax)) {
545  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
546  "Invalid depth range (%d..%d)\n",
547  dMin, dMax);
548  return false;
549  }
550  if ((rMax >= d_nRows) || (rMin > rMax)) {
551  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
552  "Invalid row range (%d..%d)\n",
553  rMin, rMax);
554  return false;
555  }
556  if ((cMax >= d_nCols) || (cMin > cMax)) {
557  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
558  "Invalid column range (%d..%d)\n",
559  cMin, cMax);
560  return false;
561  }
562  if (static_cast<unsigned>((rMax - rMin + 1) * (cMax - cMin + 1) *
563  (dMax - dMin + 1)) > vrpn_IMAGER_MAX_REGIONu16) {
564  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
565  "Region too large (%d,%d,%d to %d,%d,%d)\n",
566  cMin, rMin, dMin, cMax, rMax, dMax);
567  return false;
568  }
569  if (invert_rows && (nRows < rMax)) {
570  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
571  "nRows must not be less than rMax\n");
572  return false;
573  }
574 
575  // Make sure we've sent the description before we send any regions
576  if (!d_description_sent) {
578  d_description_sent = true;
579  }
580 
581  // If the user didn't specify a time, assume they want "now" and look it up.
582  if (time != NULL) {
583  timestamp = *time;
584  }
585  else {
586  vrpn_gettimeofday(&timestamp, NULL);
587  }
588 
589  // Check the compression status and prepare to do compression if it is
590  // called for.
591  if (d_channels[chanIndex].d_compression != vrpn_Imager_Channel::NONE) {
592  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
593  "Compression not implemented\n");
594  return false;
595  }
596 
597  // Tell which channel this region is for, and what the borders of the
598  // region are.
599  if (vrpn_buffer(&msgbuf, &buflen, chanIndex) ||
600  vrpn_buffer(&msgbuf, &buflen, dMin) ||
601  vrpn_buffer(&msgbuf, &buflen, dMax) ||
602  vrpn_buffer(&msgbuf, &buflen, rMin) ||
603  vrpn_buffer(&msgbuf, &buflen, rMax) ||
604  vrpn_buffer(&msgbuf, &buflen, cMin) ||
605  vrpn_buffer(&msgbuf, &buflen, cMax) ||
606  vrpn_buffer(&msgbuf, &buflen, vrpn_IMAGER_VALTYPE_UINT16)) {
607  return false;
608  }
609 
610  // Insert the data into the buffer, copying it as efficiently as possible
611  // from the caller's buffer into the buffer we are going to send. Note that
612  // the send buffer is going to be little-endian. The code looks a little
613  // complicated because it short-circuits the copying for the case where the
614  // column stride is one element long (using memcpy() on each row) but has to
615  // copy one element at a time otherwise.
616  // There is also the matter if deciding whether to invert the image in y,
617  // which complicates the index calculation and the calculation of the
618  // strides.
619  int cols = cMax - cMin + 1;
620  int linelen = cols * sizeof(data[0]);
621  if (colStride == 1) {
622  for (unsigned d = dMin; d <= dMax; d++) {
623  for (unsigned r = rMin; r <= rMax; r++) {
624  unsigned rActual;
625  if (invert_rows) {
626  rActual = (nRows - 1) - r;
627  }
628  else {
629  rActual = r;
630  }
631  if (buflen < linelen) {
632  return false;
633  }
634  memcpy(msgbuf,
635  &data[d * depthStride + rActual * rowStride + cMin],
636  linelen);
637  msgbuf += linelen;
638  buflen -= linelen;
639  }
640  }
641  }
642  else {
643  if (buflen < (int)((dMax - dMin + 1) * (rMax - rMin + 1) *
644  (cMax - cMin + 1) * sizeof(data[0]))) {
645  return false;
646  }
647  long rowStep = rowStride;
648  if (invert_rows) {
649  rowStep *= -1;
650  }
651  for (unsigned d = dMin; d <= dMax; d++) {
652  // XXX Turn the depth calculation into start and += like the others
653  const vrpn_uint16 *rowStart =
654  &data[d * depthStride + rMin * rowStride + cMin];
655  if (invert_rows) {
656  rowStart = &data[d * depthStride +
657  (nRows - 1 - rMin) * rowStride + cMin];
658  }
659  const vrpn_uint16 *copyFrom = rowStart;
660  for (unsigned r = rMin; r <= rMax; r++) {
661  for (unsigned c = cMin; c <= cMax; c++) {
662  memcpy(msgbuf, copyFrom, sizeof(*copyFrom));
663  msgbuf +=
664  sizeof(*copyFrom); //< Skip to the next buffer location
665  copyFrom +=
666  colStride; //< Skip appropriate number of elements
667  }
668  rowStart += rowStep; //< Skip to the start of the next row
669  copyFrom = rowStart;
670  }
671  }
672  buflen -= (rMax - rMin + 1) * (cMax - cMin + 1) * sizeof(data[0]);
673  }
674 
675  // Swap endian-ness of the buffer if we are on a big-endian machine.
676  if (vrpn_big_endian) {
677  fprintf(stderr, "XXX Imager Region needs swapping on Big-endian\n");
678  return false;
679  }
680 
681  // Pack the message
682  vrpn_int32 len = sizeof(fbuf) - buflen;
683  if (d_connection &&
684  d_connection->pack_message(len, timestamp, d_regionu16_m_id,
685  d_sender_id, (char *)(void *)fbuf,
687  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
688  "cannot write message: tossing\n");
689  return false;
690  }
691 
692  return true;
693 }
694 
717  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
718  vrpn_uint16 rMax, const vrpn_float32 *data, vrpn_uint32 colStride,
719  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
720  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
721  const struct timeval *time)
722 {
723  // msgbuf must be float64-aligned! It is the buffer to send to the client
724  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
725  char *msgbuf = (char *)fbuf;
726  int buflen = sizeof(fbuf);
727  struct timeval timestamp;
728 
729  // If we are discarding frames, return failure to send.
730  if (d_dropped_due_to_throttle > 0) {
731  return false;
732  }
733 
734  // Make sure the region request has a valid channel, has indices all
735  // within the image size, and is not too large to fit into the data
736  // array (which is sized the way it is to make sure it can be sent in
737  // one VRPN reliable message).
738  if ((chanIndex < 0) || (chanIndex >= d_nChannels)) {
739  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
740  "Invalid channel index (%d)\n",
741  chanIndex);
742  return false;
743  }
744  if ((dMax >= d_nDepth) || (dMin > dMax)) {
745  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
746  "Invalid depth range (%d..%d)\n",
747  dMin, dMax);
748  return false;
749  }
750  if ((rMax >= d_nRows) || (rMin > rMax)) {
751  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
752  "Invalid row range (%d..%d)\n",
753  rMin, rMax);
754  return false;
755  }
756  if ((cMax >= d_nCols) || (cMin > cMax)) {
757  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
758  "Invalid column range (%d..%d)\n",
759  cMin, cMax);
760  return false;
761  }
762  if (static_cast<unsigned>((rMax - rMin + 1) * (cMax - cMin + 1) *
763  (dMax - dMin + 1)) > vrpn_IMAGER_MAX_REGIONf32) {
764  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
765  "Region too large (%d,%d,%d to %d,%d,%d)\n",
766  cMin, rMin, dMin, cMax, rMax, dMax);
767  return false;
768  }
769  if (invert_rows && (nRows < rMax)) {
770  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
771  "nRows must not be less than rMax\n");
772  return false;
773  }
774 
775  // Make sure we've sent the description before we send any regions
776  if (!d_description_sent) {
778  d_description_sent = true;
779  }
780 
781  // If the user didn't specify a time, assume they want "now" and look it up.
782  if (time != NULL) {
783  timestamp = *time;
784  }
785  else {
786  vrpn_gettimeofday(&timestamp, NULL);
787  }
788 
789  // Check the compression status and prepare to do compression if it is
790  // called for.
791  if (d_channels[chanIndex].d_compression != vrpn_Imager_Channel::NONE) {
792  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
793  "Compression not implemented\n");
794  return false;
795  }
796 
797  // Tell which channel this region is for, and what the borders of the
798  // region are.
799  if (vrpn_buffer(&msgbuf, &buflen, chanIndex) ||
800  vrpn_buffer(&msgbuf, &buflen, dMin) ||
801  vrpn_buffer(&msgbuf, &buflen, dMax) ||
802  vrpn_buffer(&msgbuf, &buflen, rMin) ||
803  vrpn_buffer(&msgbuf, &buflen, rMax) ||
804  vrpn_buffer(&msgbuf, &buflen, cMin) ||
805  vrpn_buffer(&msgbuf, &buflen, cMax) ||
806  vrpn_buffer(&msgbuf, &buflen, vrpn_IMAGER_VALTYPE_FLOAT32)) {
807  return false;
808  }
809 
810  // Insert the data into the buffer, copying it as efficiently as possible
811  // from the caller's buffer into the buffer we are going to send. Note that
812  // the send buffer is going to be little-endian. The code looks a little
813  // complicated because it short-circuits the copying for the case where the
814  // column stride is one element long (using memcpy() on each row) but has to
815  // copy one element at a time otherwise.
816  // There is also the matter if deciding whether to invert the image in y,
817  // which complicates the index calculation and the calculation of the
818  // strides.
819  int cols = cMax - cMin + 1;
820  int linelen = cols * sizeof(data[0]);
821  if (colStride == 1) {
822  for (unsigned d = dMin; d <= dMax; d++) {
823  for (unsigned r = rMin; r <= rMax; r++) {
824  unsigned rActual;
825  if (invert_rows) {
826  rActual = (nRows - 1) - r;
827  }
828  else {
829  rActual = r;
830  }
831  if (buflen < linelen) {
832  return false;
833  }
834  memcpy(msgbuf,
835  &data[d * depthStride + rActual * rowStride + cMin],
836  linelen);
837  msgbuf += linelen;
838  buflen -= linelen;
839  }
840  }
841  }
842  else {
843  if (buflen < (int)((dMax - dMin + 1) * (rMax - rMin + 1) *
844  (cMax - cMin + 1) * sizeof(data[0]))) {
845  return false;
846  }
847  long rowStep = rowStride;
848  if (invert_rows) {
849  rowStep *= -1;
850  }
851  for (unsigned d = dMin; d <= dMax; d++) {
852  // XXX Turn the depth calculation into start and += like the others
853  const vrpn_float32 *rowStart =
854  &data[d * depthStride + rMin * rowStride + cMin];
855  if (invert_rows) {
856  rowStart = &data[d * depthStride +
857  (nRows - 1 - rMin) * rowStride + cMin];
858  }
859  const vrpn_float32 *copyFrom = rowStart;
860  for (unsigned r = rMin; r <= rMax; r++) {
861  for (unsigned c = cMin; c <= cMax; c++) {
862  memcpy(msgbuf, copyFrom, sizeof(*copyFrom));
863  msgbuf +=
864  sizeof(*copyFrom); //< Skip to the next buffer location
865  copyFrom +=
866  colStride; //< Skip appropriate number of elements
867  }
868  rowStart += rowStep; //< Skip to the start of the next row
869  copyFrom = rowStart;
870  }
871  }
872  buflen -= (rMax - rMin + 1) * (cMax - cMin + 1) * sizeof(data[0]);
873  }
874 
875  // Swap endian-ness of the buffer if we are on a big-endian machine.
876  if (vrpn_big_endian) {
877  fprintf(stderr, "XXX Imager Region needs swapping on Big-endian\n");
878  return false;
879  }
880 
881  // Pack the message
882  vrpn_int32 len = sizeof(fbuf) - buflen;
883  if (d_connection &&
884  d_connection->pack_message(len, timestamp, d_regionf32_m_id,
885  d_sender_id, (char *)(void *)fbuf,
887  fprintf(stderr, "vrpn_Imager_Server::send_region_using_base_pointer(): "
888  "cannot write message: tossing\n");
889  return false;
890  }
891 
892  return true;
893 }
894 
918  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
919  vrpn_uint16 rMax, const vrpn_uint8 *data, vrpn_uint32 colStride,
920  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
921  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
922  const struct timeval *time)
923 {
924  // If we are discarding frames, return failure to send.
925  if (d_dropped_due_to_throttle > 0) {
926  return false;
927  }
928 
929  // Point the data pointer back before the first pointer, to the place it
930  // should be to make the index math work out.
931  const vrpn_uint8 *new_base =
932  data - (cMin + rowStride * rMin + depthStride * dMin);
934  chanIndex, cMin, cMax, rMin, rMax, new_base, colStride, rowStride,
935  nRows, invert_rows, depthStride, dMin, dMax, time)) {
936  return true;
937  }
938  else {
939  fprintf(stderr, "vrpn_Imager_Server::send_region_using_first_pointer():"
940  " Call to send using offset base_pointer failed.\n");
941  return false;
942  }
943 }
944 
968  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
969  vrpn_uint16 rMax, const vrpn_uint16 *data, vrpn_uint32 colStride,
970  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
971  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
972  const struct timeval *time)
973 {
974  // If we are discarding frames, return failure to send.
975  if (d_dropped_due_to_throttle > 0) {
976  return false;
977  }
978 
979  // Point the data pointer back before the first pointer, to the place it
980  // should be to make the index math work out.
981  const vrpn_uint16 *new_base =
982  data - (cMin + rowStride * rMin + depthStride * dMin);
984  chanIndex, cMin, cMax, rMin, rMax, new_base, colStride, rowStride,
985  nRows, invert_rows, depthStride, dMin, dMax, time)) {
986  return true;
987  }
988  else {
989  fprintf(stderr, "vrpn_Imager_Server::send_region_using_first_pointer():"
990  " Call to send using offset base_pointer failed.\n");
991  return false;
992  }
993 }
994 
1018  vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin,
1019  vrpn_uint16 rMax, const vrpn_float32 *data, vrpn_uint32 colStride,
1020  vrpn_uint32 rowStride, vrpn_uint16 nRows, bool invert_rows,
1021  vrpn_uint32 depthStride, vrpn_uint16 dMin, vrpn_uint16 dMax,
1022  const struct timeval *time)
1023 {
1024  // If we are discarding frames, return failure to send.
1025  if (d_dropped_due_to_throttle > 0) {
1026  return false;
1027  }
1028 
1029  // Point the data pointer back before the first pointer, to the place it
1030  // should be to make the index math work out.
1031  const vrpn_float32 *new_base =
1032  data - (cMin + rowStride * rMin + depthStride * dMin);
1034  chanIndex, cMin, cMax, rMin, rMax, new_base, colStride, rowStride,
1035  nRows, invert_rows, depthStride, dMin, dMax, time)) {
1036  return true;
1037  }
1038  else {
1039  fprintf(stderr, "vrpn_Imager_Server::send_region_using_first_pointer():"
1040  " Call to send using offset base_pointer failed.\n");
1041  return false;
1042  }
1043 }
1044 
1046 {
1047  // msgbuf must be float64-aligned!
1048  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
1049  char *msgbuf = (char *)fbuf;
1050  int buflen = sizeof(fbuf);
1051  struct timeval timestamp;
1052  int i;
1053 
1054  // Pack the description of all of the fields in the imager into the buffer,
1055  // including the channel descriptions.
1056  if (vrpn_buffer(&msgbuf, &buflen, d_nDepth) ||
1057  vrpn_buffer(&msgbuf, &buflen, d_nRows) ||
1058  vrpn_buffer(&msgbuf, &buflen, d_nCols) ||
1059  vrpn_buffer(&msgbuf, &buflen, d_nChannels)) {
1060  fprintf(stderr, "vrpn_Imager_Server::send_description(): Can't pack "
1061  "message header, tossing\n");
1062  return false;
1063  }
1064  for (i = 0; i < d_nChannels; i++) {
1065  if (!d_channels[i].buffer(&msgbuf, &buflen)) {
1066  fprintf(stderr, "vrpn_Imager_Server::send_description(): Can't "
1067  "pack message channel, tossing\n");
1068  return false;
1069  }
1070  }
1071 
1072  // Pack the buffer into the connection's outgoing reliable queue, if we have
1073  // a valid connection.
1074  vrpn_int32 len = sizeof(fbuf) - buflen;
1075  vrpn_gettimeofday(&timestamp, NULL);
1076  if (d_connection &&
1077  d_connection->pack_message(len, timestamp, d_description_m_id,
1078  d_sender_id, (char *)(void *)fbuf,
1080  fprintf(stderr, "vrpn_Imager_Server::send_description(): cannot write "
1081  "message: tossing\n");
1082  return false;
1083  }
1084 
1085  d_description_sent = true;
1086  return true;
1087 }
1088 
1089 bool vrpn_Imager_Server::set_resolution(vrpn_int32 nCols, vrpn_int32 nRows,
1090  vrpn_int32 nDepth)
1091 {
1092  if ((nCols <= 0) || (nRows <= 0) || (nDepth <= 0)) {
1093  fprintf(
1094  stderr,
1095  "vrpn_Imager_Server::set_resolution(): Invalid size (%d, %d, %d)\n",
1096  nCols, nRows, nDepth);
1097  return false;
1098  }
1099  d_nDepth = nDepth;
1100  d_nCols = nCols;
1101  d_nRows = nRows;
1102  return send_description();
1103 }
1104 
1106 
1108 {
1110  me->send_description();
1111  return 0;
1112 }
1113 
1116 {
1117  const char *bufptr = p.buffer;
1119 
1120  // Get the requested number of frames from the buffer
1121  vrpn_int32 frames_to_send;
1122  if (vrpn_unbuffer(&bufptr, &frames_to_send)) {
1123  return -1;
1124  }
1125 
1126  // If the requested number of frames is negative, then we set
1127  // for unbounded sending. The next time a begin_frame message
1128  // is sent, it will start the process going again.
1129  if (frames_to_send < 0) {
1130  me->d_frames_to_send = -1;
1131  return 0;
1132  }
1133 
1134  // If we were sending continuously, store the number of frames
1135  // to send.
1136  if (me->d_frames_to_send == -1) {
1137  me->d_frames_to_send = frames_to_send;
1138 
1139  // If we already had a throttle limit set, then increment it
1140  // by the count.
1141  }
1142  else {
1143  me->d_frames_to_send += frames_to_send;
1144  }
1145 
1146  return 0;
1147 }
1148 
1151 {
1153 
1154  // Last connection has dropped, so set the throttling behavior back to
1155  // the default, which is to send as fast as we can.
1156  me->d_frames_to_send = -1;
1157  me->d_dropped_due_to_throttle = 0;
1158  return 0;
1159 }
1160 
1162  : vrpn_Imager(name, c)
1163  , d_got_description(false)
1164 {
1165  // Register the handlers for the description message and the region change
1166  // messages
1168  this, d_sender_id);
1169 
1170  // Register the region-handling messages for the different message types.
1171  // All of the types use the same handler, since the type of region is
1172  // encoded
1173  // in one of the parameters of the region function.
1175  d_sender_id);
1177  d_sender_id);
1179  d_sender_id);
1181  this, d_sender_id);
1183  this, d_sender_id);
1186  d_sender_id);
1187 
1188  // Register the handler for the connection dropped message
1192 }
1193 
1195 {
1196  client_mainloop();
1197  if (d_connection) {
1199  };
1200 }
1201 
1202 const vrpn_Imager_Channel *vrpn_Imager_Remote::channel(unsigned chanNum) const
1203 {
1204  if (chanNum >= (unsigned)d_nChannels) {
1205  return NULL;
1206  }
1207  return &d_channels[chanNum];
1208 }
1209 
1212 {
1213  const char *bufptr = p.buffer;
1215  int i;
1216 
1217  // Get my new information from the buffer
1218  if (vrpn_unbuffer(&bufptr, &me->d_nDepth) ||
1219  vrpn_unbuffer(&bufptr, &me->d_nRows) ||
1220  vrpn_unbuffer(&bufptr, &me->d_nCols) ||
1221  vrpn_unbuffer(&bufptr, &me->d_nChannels)) {
1222  return -1;
1223  }
1224  for (i = 0; i < me->d_nChannels; i++) {
1225  if (!me->d_channels[i].unbuffer(&bufptr)) {
1226  return -1;
1227  }
1228  }
1229 
1230  // Go down the list of callbacks that have been registered.
1231  // Fill in the parameter and call each.
1233 
1234  me->d_got_description = true;
1235  return 0;
1236 }
1237 
1240 {
1241  const char *bufptr = p.buffer;
1244  vrpn_Imager_Region reg;
1245 
1246  // Create an instance of a region helper class and read its
1247  // parameters from the buffer (setting its _valBuf pointer at
1248  // the start of the data in the buffer). Set it to valid and then
1249  // call the user callback and then set it to invalid before
1250  // deleting it.
1251  if (vrpn_unbuffer(&bufptr, &reg.d_chanIndex) ||
1252  vrpn_unbuffer(&bufptr, &reg.d_dMin) ||
1253  vrpn_unbuffer(&bufptr, &reg.d_dMax) ||
1254  vrpn_unbuffer(&bufptr, &reg.d_rMin) ||
1255  vrpn_unbuffer(&bufptr, &reg.d_rMax) ||
1256  vrpn_unbuffer(&bufptr, &reg.d_cMin) ||
1257  vrpn_unbuffer(&bufptr, &reg.d_cMax) ||
1258  vrpn_unbuffer(&bufptr, &reg.d_valType)) {
1259  fprintf(stderr, "vrpn_Imager_Remote::handle_region_message(): Can't "
1260  "unbuffer parameters!\n");
1261  return -1;
1262  }
1263  reg.d_valBuf = bufptr;
1264  reg.d_valid = true;
1265 
1266  // Check the compression status and prepare to do decompression if it is
1267  // called for.
1268  if (me->d_channels[reg.d_chanIndex].d_compression !=
1270  fprintf(stderr, "vrpn_Imager_Remote::handle_region_message(): "
1271  "Compression not implemented\n");
1272  return -1;
1273  }
1274 
1275  // Fill in a user callback structure with the data
1276  rp.msg_time = p.msg_time;
1277  rp.region = &reg;
1278 
1279  // ONLY if we have gotten a description message,
1280  // Go down the list of callbacks that have been registered.
1281  // Fill in the parameter and call each.
1282  if (me->d_got_description) {
1283  me->d_region_list.call_handlers(rp);
1284  }
1285 
1286  reg.d_valid = false;
1287  return 0;
1288 }
1289 
1292 {
1293  const char *bufptr = p.buffer;
1296 
1297  bf.msg_time = p.msg_time;
1298  if (vrpn_unbuffer(&bufptr, &bf.dMin) || vrpn_unbuffer(&bufptr, &bf.dMax) ||
1299  vrpn_unbuffer(&bufptr, &bf.rMin) || vrpn_unbuffer(&bufptr, &bf.rMax) ||
1300  vrpn_unbuffer(&bufptr, &bf.cMin) || vrpn_unbuffer(&bufptr, &bf.cMax)) {
1301  fprintf(stderr, "vrpn_Imager_Remote::handle_begin_frame_message(): "
1302  "Can't unbuffer parameters!\n");
1303  return -1;
1304  }
1305 
1306  // ONLY if we have gotten a description message,
1307  // Go down the list of callbacks that have been registered.
1308  // Fill in the parameter and call each.
1309  if (me->d_got_description) {
1311  }
1312 
1313  return 0;
1314 }
1315 
1318 {
1319  const char *bufptr = p.buffer;
1322 
1323  ef.msg_time = p.msg_time;
1324  if (vrpn_unbuffer(&bufptr, &ef.dMin) || vrpn_unbuffer(&bufptr, &ef.dMax) ||
1325  vrpn_unbuffer(&bufptr, &ef.rMin) || vrpn_unbuffer(&bufptr, &ef.rMax) ||
1326  vrpn_unbuffer(&bufptr, &ef.cMin) || vrpn_unbuffer(&bufptr, &ef.cMax)) {
1327  fprintf(stderr, "vrpn_Imager_Remote::handle_end_frame_message(): Can't "
1328  "unbuffer parameters!\n");
1329  return -1;
1330  }
1331 
1332  // ONLY if we have gotten a description message,
1333  // Go down the list of callbacks that have been registered.
1334  // Fill in the parameter and call each.
1335  if (me->d_got_description) {
1337  }
1338 
1339  return 0;
1340 }
1341 
1344 {
1345  const char *bufptr = p.buffer;
1348 
1349  df.msg_time = p.msg_time;
1350  if (vrpn_unbuffer(&bufptr, &df.count)) {
1351  fprintf(stderr, "vrpn_Imager_Remote::handle_discarded_frames_message():"
1352  " Can't unbuffer parameters!\n");
1353  return -1;
1354  }
1355 
1356  // ONLY if we have gotten a description message,
1357  // Go down the list of callbacks that have been registered.
1358  // Fill in the parameter and call each.
1359  if (me->d_got_description) {
1361  }
1362 
1363  return 0;
1364 }
1365 
1368 {
1370 
1371  // We have no description message, so don't call region callbacks
1372  me->d_got_description = false;
1373 
1374  return 0;
1375 }
1376 
1378 {
1379  // msgbuf must be float64-aligned!
1380  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
1381  char *msgbuf = (char *)fbuf;
1382  int buflen = sizeof(fbuf);
1383  struct timeval timestamp;
1384 
1385  // Pack the throttle count request.
1386  if (vrpn_buffer(&msgbuf, &buflen, N)) {
1387  fprintf(stderr, "vrpn_ImagerPose_Server::throttle_sender(): Can't pack "
1388  "message header, tossing\n");
1389  return false;
1390  }
1391 
1392  // Pack the buffer into the connection's outgoing reliable queue, if we have
1393  // a valid connection.
1394  vrpn_int32 len = sizeof(fbuf) - buflen;
1395  vrpn_gettimeofday(&timestamp, NULL);
1396  if (d_connection &&
1398  d_sender_id, (char *)(void *)fbuf,
1400  fprintf(stderr, "vrpn_ImagerPose_Server::throttle_sender(): cannot "
1401  "write message: tossing\n");
1402  return false;
1403  }
1404 
1405  return true;
1406 }
1407 
1442  vrpn_uint8 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride,
1443  vrpn_uint32 depthStride, vrpn_uint16 nRows, bool invert_rows,
1444  unsigned repeat) const
1445 {
1446  // Make sure the parameters are reasonable
1447  if (colStride < repeat) {
1448  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1449  "pointer(): colStride must be >= repeat\n");
1450  return false;
1451  }
1452 
1453  if (invert_rows && (nRows < d_rMax)) {
1454  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1455  "pointer(): nRows must not be less than _rMax\n");
1456  return false;
1457  }
1458 
1459  // If the type of data in the buffer doesn't match the type of data the user
1460  // wants, we need to convert each element along the way.
1462  // The data type matches what we the user is asking for. No transcoding
1463  // needed.
1464  // Insert the data into the buffer, copying it as efficiently as
1465  // possible
1466  // from the network buffer into the caller's buffer . Note that
1467  // the network buffer is little-endian. The code looks a little
1468  // complicated because it short-circuits the copying for the case where
1469  // the
1470  // column stride and repeat are one element long (using memcpy() on each
1471  // row) but has to
1472  // copy one element at a time otherwise.
1473  int cols = d_cMax - d_cMin + 1;
1474  int linelen = cols * sizeof(data[0]);
1475  if ((colStride == 1) && (repeat == 1)) {
1476  const vrpn_uint8 *msgbuf = (const vrpn_uint8 *)d_valBuf;
1477  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1478  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1479  unsigned rActual;
1480  if (invert_rows) {
1481  rActual = (nRows - 1) - r;
1482  }
1483  else {
1484  rActual = r;
1485  }
1486  memcpy(
1487  &data[d * depthStride + rActual * rowStride + d_cMin],
1488  msgbuf, linelen);
1489  msgbuf += linelen;
1490  }
1491  }
1492  }
1493  else {
1494  long rowStep = rowStride;
1495  if (invert_rows) {
1496  rowStep *= -1;
1497  }
1498  const vrpn_uint8 *msgbuf = (const vrpn_uint8 *)d_valBuf;
1499  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1500  vrpn_uint8 *rowStart =
1501  &data[d * depthStride + d_rMin * rowStride +
1502  d_cMin * repeat];
1503  if (invert_rows) {
1504  rowStart = &data[d * depthStride +
1505  (nRows - 1 - d_rMin) * rowStride +
1506  d_cMin * repeat];
1507  }
1508  vrpn_uint8 *copyTo = rowStart;
1509  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1510  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1511  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1512  *(copyTo + rpt) =
1513  *msgbuf; //< Copy the current element
1514  }
1515  msgbuf++; //< Skip to the next buffer location
1516  copyTo +=
1517  colStride; //< Skip appropriate number of elements
1518  }
1519  rowStart += rowStep; //< Skip to the start of the next row
1520  copyTo = rowStart;
1521  }
1522  }
1523  }
1524  }
1525  else if (d_valType == vrpn_IMAGER_VALTYPE_FLOAT32) {
1526  // Transcode from 32-bit floating-point to 8-bit values during the
1527  // conversion process.
1528  // As this is unscaled, we do not adjust the values -- simply jam the
1529  // values in and
1530  // let C++ conversion do the work for us.
1531 
1532  // Swap endian-ness of the buffer if we are on a big-endian machine.
1533  if (vrpn_big_endian) {
1534  fprintf(stderr, "XXX Imager Region needs swapping on Big-endian\n");
1535  return false;
1536  }
1537 
1538  long rowStep = rowStride;
1539  if (invert_rows) {
1540  rowStep *= -1;
1541  }
1542  const vrpn_float32 *msgbuf = (const vrpn_float32 *)d_valBuf;
1543  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1544  vrpn_uint8 *rowStart =
1545  &data[d * depthStride + d_rMin * rowStride + d_cMin * repeat];
1546  if (invert_rows) {
1547  rowStart =
1548  &data[d * depthStride + (nRows - 1 - d_rMin) * rowStride +
1549  d_cMin * repeat];
1550  }
1551  vrpn_uint8 *copyTo = rowStart;
1552  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1553  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1554  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1555  *(copyTo + rpt) = static_cast<vrpn_uint8>(
1556  *msgbuf); //< Copy the current element
1557  }
1558  msgbuf++; //< Skip to the next buffer location
1559  copyTo += colStride; //< Skip appropriate number of elements
1560  }
1561  rowStart += rowStep; //< Skip to the start of the next row
1562  copyTo = rowStart;
1563  }
1564  }
1565  }
1566  else if (d_valType == vrpn_IMAGER_VALTYPE_UINT16) {
1567  // transcode from 16 bit image to 8 bit data for app
1568 
1569  long rowStep = rowStride;
1570  if (invert_rows) {
1571  rowStep *= -1;
1572  }
1573  const vrpn_uint16 *msgbuf = (const vrpn_uint16 *)d_valBuf;
1574  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1575  vrpn_uint8 *rowStart =
1576  &data[d * depthStride + d_rMin * rowStride + d_cMin * repeat];
1577  if (invert_rows) {
1578  rowStart =
1579  &data[d * depthStride + (nRows - 1 - d_rMin) * rowStride +
1580  d_cMin * repeat];
1581  }
1582  vrpn_uint8 *copyTo = rowStart;
1583  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1584  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1585  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1586  *(copyTo + rpt) = static_cast<vrpn_uint8>(
1587  (*msgbuf) >>
1588  8); //< Copy the current element (take top 8 bits)
1589  }
1590  msgbuf++; //< Skip to the next buffer location
1591  copyTo += colStride; //< Skip appropriate number of elements
1592  }
1593  rowStart += rowStep; //< Skip to the start of the next row
1594  copyTo = rowStart;
1595  }
1596  }
1597  }
1598  else {
1599  printf("vrpn_Imager_Region::decode_unscaled_region_using_base_pointer()"
1600  ": Transcoding not implemented yet for this type\n");
1601  printf("d_valType = %i\n", d_valType);
1602  return false;
1603  }
1604 
1605  // No need to swap endianness on single-byte entities.
1606  return true;
1607 }
1608 
1609 // This routine handles both 16-bit and 12-bit-in-16 iamges.
1611  vrpn_uint16 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride,
1612  vrpn_uint32 depthStride, vrpn_uint16 nRows, bool invert_rows,
1613  unsigned repeat) const
1614 {
1615  // Make sure the parameters are reasonable
1616  if (colStride < repeat) {
1617  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1618  "pointer(): colStride must be >= repeat\n");
1619  return false;
1620  }
1621  if (invert_rows && (nRows < d_rMax)) {
1622  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1623  "pointer(): nRows must not be less than _rMax\n");
1624  return false;
1625  }
1626 
1627  // If the type of data in the buffer matches the type of data the user
1628  // wants, no need to convert each element along the way.
1631 
1632  // The data type matches what we the user is asking for. No transcoding
1633  // needed.
1634  // Insert the data into the buffer, copying it as efficiently as
1635  // possible
1636  // from the network buffer into the caller's buffer . Note that
1637  // the network buffer is little-endian. The code looks a little
1638  // complicated because it short-circuits the copying for the case where
1639  // the
1640  // column stride and repeat are one element long (using memcpy() on each
1641  // row) but has to
1642  // copy one element at a time otherwise.
1643  int cols = d_cMax - d_cMin + 1;
1644  int linelen = cols * sizeof(data[0]);
1645  if ((colStride == 1) && (repeat == 1)) {
1646  const vrpn_uint16 *msgbuf = (const vrpn_uint16 *)d_valBuf;
1647  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1648  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1649  unsigned rActual;
1650  if (invert_rows) {
1651  rActual = (nRows - 1) - r;
1652  }
1653  else {
1654  rActual = r;
1655  }
1656  memcpy(
1657  &data[d * depthStride + rActual * rowStride + d_cMin],
1658  msgbuf, linelen);
1659  msgbuf += cols;
1660  }
1661  }
1662  }
1663  else {
1664  long rowStep = rowStride;
1665  if (invert_rows) {
1666  rowStep *= -1;
1667  }
1668  const vrpn_uint16 *msgbuf = (const vrpn_uint16 *)d_valBuf;
1669  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1670  vrpn_uint16 *rowStart =
1671  &data[d * depthStride + d_rMin * rowStride +
1672  d_cMin * repeat];
1673  if (invert_rows) {
1674  rowStart = &data[d * depthStride +
1675  (nRows - 1 - d_rMin) * rowStride +
1676  d_cMin * repeat];
1677  }
1678  vrpn_uint16 *copyTo = rowStart;
1679  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1680  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1681  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1682  *(copyTo + rpt) =
1683  *msgbuf; //< Copy the current element
1684  }
1685  msgbuf++; //< Skip to the next buffer location
1686  copyTo +=
1687  colStride; //< Skip appropriate number of elements
1688  }
1689  rowStart += rowStep; //< Skip to the start of the next row
1690  copyTo = rowStart;
1691  }
1692  }
1693  }
1694 
1695  // The data type sent does not match the type asked for. We will need
1696  // to trans-code
1697  // from the format it is in to the format they want.
1698  }
1699  else if (d_valType == vrpn_IMAGER_VALTYPE_UINT8) {
1700  // Convert from unsigned integer 8-bit to unsigned integer 16-bit
1701  // by shifting each left 8 bits (same as multiplying by 256). Note
1702  // that this does not map 255 to the maximum 16-bit value, but doing
1703  // that would require either floating-point math or precomputing that
1704  // math and using table look-up.
1705  long rowStep = rowStride;
1706  if (invert_rows) {
1707  rowStep *= -1;
1708  }
1709  const vrpn_uint8 *msgbuf = (const vrpn_uint8 *)d_valBuf;
1710  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1711  vrpn_uint16 *rowStart =
1712  &data[d * depthStride + d_rMin * rowStride + d_cMin * repeat];
1713  if (invert_rows) {
1714  rowStart =
1715  &data[d * depthStride + (nRows - 1 - d_rMin) * rowStride +
1716  d_cMin * repeat];
1717  }
1718  vrpn_uint16 *copyTo = rowStart;
1719  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1720  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1721  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1722  //< Shift and copy the current element
1723  *(copyTo + rpt) =
1724  (static_cast<vrpn_uint16>(*msgbuf) << 8);
1725  }
1726  msgbuf++; //< Skip to the next buffer location
1727  copyTo += colStride; //< Skip appropriate number of elements
1728  }
1729  rowStart += rowStep; //< Skip to the start of the next row
1730  copyTo = rowStart;
1731  }
1732  }
1733  }
1734  else {
1735  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1736  "pointer(): XXX Transcoding this type not yet "
1737  "implemented\n");
1738  return false;
1739  }
1740 
1741  // Swap endian-ness of the buffer if we are on a big-endian machine.
1742  if (vrpn_big_endian) {
1743  fprintf(stderr, "XXX Imager Region needs swapping on Big-endian\n");
1744  return false;
1745  }
1746 
1747  return true;
1748 }
1749 
1751  vrpn_float32 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride,
1752  vrpn_uint32 depthStride, vrpn_uint16 nRows, bool invert_rows,
1753  unsigned repeat) const
1754 {
1755  // Make sure the parameters are reasonable
1756  if (colStride < repeat) {
1757  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1758  "pointer(): colStride must be >= repeat\n");
1759  return false;
1760  }
1761 
1762  // If the type of data in the buffer doesn't match the type of data the user
1763  // wants, we need to convert each element along the way.
1765  printf("vrpn_Imager_Region::decode_unscaled_region_using_base_pointer()"
1766  ": Transcoding not implemented yet\n");
1767  return false;
1768  }
1769  if (invert_rows && (nRows < d_rMax)) {
1770  fprintf(stderr, "vrpn_Imager_Region::decode_unscaled_region_using_base_"
1771  "pointer(): nRows must not be less than _rMax\n");
1772  return false;
1773  }
1774 
1775  // The data type matches what we the user is asking for. No transcoding
1776  // needed.
1777  // Insert the data into the buffer, copying it as efficiently as possible
1778  // from the network buffer into the caller's buffer . Note that
1779  // the network buffer is little-endian. The code looks a little
1780  // complicated because it short-circuits the copying for the case where the
1781  // column stride and repeat are one element long (using memcpy() on each
1782  // row) but has to
1783  // copy one element at a time otherwise.
1784  int cols = d_cMax - d_cMin + 1;
1785  int linelen = cols * sizeof(data[0]);
1786  if ((colStride == 1) && (repeat == 1)) {
1787  const vrpn_float32 *msgbuf = (const vrpn_float32 *)d_valBuf;
1788  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1789  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1790  unsigned rActual;
1791  if (invert_rows) {
1792  rActual = (nRows - 1) - r;
1793  }
1794  else {
1795  rActual = r;
1796  }
1797  memcpy(&data[d * depthStride + rActual * rowStride + d_cMin],
1798  msgbuf, linelen);
1799  msgbuf += linelen;
1800  }
1801  }
1802  }
1803  else {
1804  long rowStep = rowStride;
1805  if (invert_rows) {
1806  rowStep *= -1;
1807  }
1808  const vrpn_float32 *msgbuf = (const vrpn_float32 *)d_valBuf;
1809  for (unsigned d = d_dMin; d <= d_dMax; d++) {
1810  vrpn_float32 *rowStart =
1811  &data[d * depthStride + d_rMin * rowStride + d_cMin * repeat];
1812  if (invert_rows) {
1813  rowStart =
1814  &data[d * depthStride + (nRows - 1 - d_rMin) * rowStride +
1815  d_cMin * repeat];
1816  }
1817  vrpn_float32 *copyTo = rowStart;
1818  for (unsigned r = d_rMin; r <= d_rMax; r++) {
1819  for (unsigned c = d_cMin; c <= d_cMax; c++) {
1820  for (unsigned rpt = 0; rpt < repeat; rpt++) {
1821  *(copyTo + rpt) = *msgbuf; //< Copy the current element
1822  }
1823  msgbuf++; //< Skip to the next buffer location
1824  copyTo += colStride; //< Skip appropriate number of elements
1825  }
1826  rowStart += rowStep; //< Skip to the start of the next row
1827  copyTo = rowStart;
1828  }
1829  }
1830  }
1831 
1832  // Swap endian-ness of the buffer if we are on a big-endian machine.
1833  if (vrpn_big_endian) {
1834  fprintf(stderr, "XXX Imager Region needs swapping on Big-endian\n");
1835  return false;
1836  }
1837 
1838  return true;
1839 }
1840 
1842  : vrpn_BaseClass(name, c)
1843 {
1845 
1846  d_origin[0] = d_origin[1] = d_origin[2] = 0.0;
1847  d_dCol[0] = d_dCol[1] = d_dCol[2] = 0.0;
1848  d_dRow[0] = d_dRow[1] = d_dRow[2] = 0.0;
1849  d_dDepth[0] = d_dDepth[1] = d_dDepth[2] = 0.0;
1850 };
1851 
1853 {
1855  d_connection->register_message_type("vrpn_ImagerPose Description");
1856  if (d_description_m_id == -1) {
1857  return -1;
1858  }
1859  else {
1860  return 0;
1861  }
1862 }
1863 
1864 bool vrpn_ImagerPose::compute_pixel_center(vrpn_float64 *center,
1865  const vrpn_Imager &image,
1866  vrpn_uint16 col, vrpn_uint16 row,
1867  vrpn_uint16 depth)
1868 {
1869  // Make sure we don't have a NULL pointer to fill our return into.
1870  if (center == NULL) {
1871  fprintf(
1872  stderr,
1873  "vrpn_ImagerPose::compute_pixel_center(): NULL center pointer\n");
1874  return false;
1875  }
1876 
1877  // Ensure that the pixel coordinate is within bounds
1878  if ((col >= image.nCols()) || (row >= image.nRows()) ||
1879  (depth >= image.nDepth())) {
1880  fprintf(stderr, "vrpn_ImagerPose::compute_pixel_center(): Pixel index "
1881  "out of range\n");
1882  return false;
1883  }
1884 
1885  // The pixel centers are located at the midpoint in row, column, and
1886  // depth space of each pixel. The pixel range is therefore half a
1887  // pixel past the centers of all pixels in the image. This means that
1888  // there is one extra pixel-step included in the range (half to the
1889  // negative of the origin, half to the positive of the last entry).
1890  // So, the pixel center is one half-step plus a number of whole steps
1891  // equal to its index.
1892  vrpn_float64 stepC = 1.0 / image.nCols();
1893  vrpn_float64 stepR = 1.0 / image.nRows();
1894  vrpn_float64 stepD = 1.0 / image.nDepth();
1895 
1896  center[0] = d_origin[0] + (0.5 + col) * stepC * d_dCol[0] +
1897  (0.5 + row) * stepR * d_dRow[0] +
1898  (0.5 + depth) * stepD * d_dDepth[0];
1899  center[1] = d_origin[1] + (0.5 + col) * stepC * d_dCol[1] +
1900  (0.5 + row) * stepR * d_dRow[1] +
1901  (0.5 + depth) * stepD * d_dDepth[1];
1902  center[2] = d_origin[2] + (0.5 + col) * stepC * d_dCol[2] +
1903  (0.5 + row) * stepR * d_dRow[2] +
1904  (0.5 + depth) * stepD * d_dDepth[2];
1905 
1906  return true;
1907 }
1908 
1910  const char *name, const vrpn_float64 origin[3], const vrpn_float64 dCol[3],
1911  const vrpn_float64 dRow[3], const vrpn_float64 *dDepth, vrpn_Connection *c)
1912  : vrpn_ImagerPose(name, c)
1913 {
1914  memcpy(d_origin, origin, sizeof(d_origin));
1915  memcpy(d_dCol, dCol, sizeof(d_dCol));
1916  memcpy(d_dRow, dRow, sizeof(d_dRow));
1917  if (dDepth != NULL) {
1918  memcpy(d_dDepth, dDepth, sizeof(d_dDepth));
1919  }
1920 
1921  // Set up callback handler for ping message from client so that it
1922  // sends the description. This will make sure that the other side has
1923  // heard the descrption before it hears a region message. Also set this up
1924  // to fire on the "new connection" system message.
1925 
1927  d_sender_id);
1931 };
1932 
1933 bool vrpn_ImagerPose_Server::set_range(const vrpn_float64 origin[3],
1934  const vrpn_float64 dCol[3],
1935  const vrpn_float64 dRow[3],
1936  const vrpn_float64 *dDepth)
1937 {
1938  memcpy(d_origin, origin, sizeof(d_origin));
1939  memcpy(d_dCol, dCol, sizeof(d_dCol));
1940  memcpy(d_dRow, dRow, sizeof(d_dRow));
1941  if (dDepth != NULL) {
1942  memcpy(d_dDepth, dDepth, sizeof(d_dDepth));
1943  }
1944  return send_description();
1945 }
1946 
1948 {
1949  // msgbuf must be float64-aligned!
1950  vrpn_float64 fbuf[vrpn_CONNECTION_TCP_BUFLEN / sizeof(vrpn_float64)];
1951  char *msgbuf = (char *)fbuf;
1952  int buflen = sizeof(fbuf);
1953  struct timeval timestamp;
1954 
1955  // Pack the description of all of the fields in the imager into the buffer,
1956  // including the channel descriptions.
1957  if (vrpn_buffer(&msgbuf, &buflen, d_origin[0]) ||
1958  vrpn_buffer(&msgbuf, &buflen, d_origin[1]) ||
1959  vrpn_buffer(&msgbuf, &buflen, d_origin[2]) ||
1960  vrpn_buffer(&msgbuf, &buflen, d_dDepth[0]) ||
1961  vrpn_buffer(&msgbuf, &buflen, d_dDepth[1]) ||
1962  vrpn_buffer(&msgbuf, &buflen, d_dDepth[2]) ||
1963  vrpn_buffer(&msgbuf, &buflen, d_dRow[0]) ||
1964  vrpn_buffer(&msgbuf, &buflen, d_dRow[1]) ||
1965  vrpn_buffer(&msgbuf, &buflen, d_dRow[2]) ||
1966  vrpn_buffer(&msgbuf, &buflen, d_dCol[0]) ||
1967  vrpn_buffer(&msgbuf, &buflen, d_dCol[1]) ||
1968  vrpn_buffer(&msgbuf, &buflen, d_dCol[2])) {
1969  fprintf(stderr, "vrpn_ImagerPose_Server::send_description(): Can't "
1970  "pack message header, tossing\n");
1971  return false;
1972  }
1973 
1974  // Pack the buffer into the connection's outgoing reliable queue, if we have
1975  // a valid connection.
1976  vrpn_int32 len = sizeof(fbuf) - buflen;
1977  vrpn_gettimeofday(&timestamp, NULL);
1978  if (d_connection &&
1979  d_connection->pack_message(len, timestamp, d_description_m_id,
1980  d_sender_id, (char *)(void *)fbuf,
1982  fprintf(stderr, "vrpn_ImagerPose_Server::send_description(): cannot "
1983  "write message: tossing\n");
1984  return false;
1985  }
1986 
1987  return true;
1988 }
1989 
1992 {
1994  me->send_description();
1995  return 0;
1996 }
1997 
1999 
2001  vrpn_Connection *c)
2002  : vrpn_ImagerPose(name, c)
2003 {
2004  // Register the handlers for the description message
2006  this, d_sender_id);
2007 }
2008 
2011 {
2012  const char *bufptr = p.buffer;
2014 
2015  // Get my new information from the buffer
2016  if (vrpn_unbuffer(&bufptr, &me->d_origin[0]) ||
2017  vrpn_unbuffer(&bufptr, &me->d_origin[1]) ||
2018  vrpn_unbuffer(&bufptr, &me->d_origin[2]) ||
2019  vrpn_unbuffer(&bufptr, &me->d_dDepth[0]) ||
2020  vrpn_unbuffer(&bufptr, &me->d_dDepth[1]) ||
2021  vrpn_unbuffer(&bufptr, &me->d_dDepth[2]) ||
2022  vrpn_unbuffer(&bufptr, &me->d_dRow[0]) ||
2023  vrpn_unbuffer(&bufptr, &me->d_dRow[1]) ||
2024  vrpn_unbuffer(&bufptr, &me->d_dRow[2]) ||
2025  vrpn_unbuffer(&bufptr, &me->d_dCol[0]) ||
2026  vrpn_unbuffer(&bufptr, &me->d_dCol[1]) ||
2027  vrpn_unbuffer(&bufptr, &me->d_dCol[2])) {
2028  return -1;
2029  }
2030 
2031  // Go down the list of callbacks that have been registered.
2032  // Fill in the parameter and call each.
2034 
2035  return 0;
2036 }
2037 
2039 {
2040  client_mainloop();
2041  if (d_connection) {
2043  };
2044 }
vrpn_Imager_Remote::d_description_list
vrpn_Callback_List< struct timeval > d_description_list
Definition: vrpn_Imager.h:732
vrpn_ImagerPose_Server
Definition: vrpn_Imager.h:343
vrpn_IMAGERBEGINFRAMECB::rMax
vrpn_uint16 rMax
Definition: vrpn_Imager.h:405
vrpn_Imager::d_nChannels
vrpn_int32 d_nChannels
Definition: vrpn_Imager.h:131
vrpn_BaseClassUnique::register_autodeleted_handler
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.
Definition: vrpn_BaseClass.C:503
vrpn_Connection::pack_message
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...
Definition: vrpn_Connection.C:4632
vrpn_BaseClassUnique::client_mainloop
void client_mainloop(void)
Handles functions that all clients should provide in their mainloop() (warning of no server,...
Definition: vrpn_BaseClass.C:637
vrpn_Imager::d_regionu16_m_id
vrpn_int32 d_regionu16_m_id
Definition: vrpn_Imager.h:150
vrpn_IMAGERDISCARDEDFRAMESCB::msg_time
struct timeval msg_time
Definition: vrpn_Imager.h:423
vrpn_Imager_Remote::throttle_sender
virtual bool throttle_sender(vrpn_int32 N)
Request that the server send at most N more frames until a new request is sent.
Definition: vrpn_Imager.C:1377
vrpn_Imager_Remote::vrpn_Imager_Remote
vrpn_Imager_Remote(const char *name, vrpn_Connection *c=NULL)
Definition: vrpn_Imager.C:1161
vrpn_ImagerPose::register_types
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail.
Definition: vrpn_Imager.C:1852
vrpn_Imager::d_regionu12in16_m_id
vrpn_int32 d_regionu12in16_m_id
Definition: vrpn_Imager.h:147
vrpn_got_connection
const char * vrpn_got_connection
Definition: vrpn_Connection.C:185
vrpn_Imager::d_channels
vrpn_Imager_Channel d_channels[vrpn_IMAGER_MAX_CHANNELS]
Definition: vrpn_Imager.h:132
vrpn_Imager::d_end_frame_m_id
vrpn_int32 d_end_frame_m_id
Definition: vrpn_Imager.h:139
vrpn_BaseClassUnique::d_ping_message_id
vrpn_int32 d_ping_message_id
Ask the server if they are there.
Definition: vrpn_BaseClass.h:230
vrpn_ImagerPose_Server::handle_ping_message
static int VRPN_CALLBACK handle_ping_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Imager.C:1990
vrpn_IMAGER_VALTYPE_UINT8
const vrpn_uint16 vrpn_IMAGER_VALTYPE_UINT8
Definition: vrpn_Imager.h:378
vrpn_Imager_Server::add_channel
int add_channel(const char *name, const char *units="unsigned8bit", vrpn_float32 minVal=0, vrpn_float32 maxVal=255, vrpn_float32 scale=1, vrpn_float32 offset=0)
Add a channel to the server, returns index of the channel or -1 on failure.
Definition: vrpn_Imager.C:81
vrpn_Imager_Remote::handle_discarded_frames_message
static int VRPN_CALLBACK handle_discarded_frames_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for discarded-frames message from the server.
Definition: vrpn_Imager.C:1342
vrpn_Imager_Region::d_valType
vrpn_uint16 d_valType
Definition: vrpn_Imager.h:617
vrpn_Imager_Server::send_begin_frame
bool send_begin_frame(const vrpn_uint16 cMin, const vrpn_uint16 cMax, const vrpn_uint16 rMin, const vrpn_uint16 rMax, const vrpn_uint16 dMin=0, const vrpn_uint16 dMax=0, const struct timeval *time=NULL)
Servers must send begin/end frame pairs around contiguous sections of the image.
Definition: vrpn_Imager.C:107
vrpn_ImagerPose::d_origin
vrpn_float64 d_origin[3]
Definition: vrpn_Imager.h:332
vrpn_ImagerPose::d_dCol
vrpn_float64 d_dCol[3]
Definition: vrpn_Imager.h:334
vrpn_ImagerPose::d_dDepth
vrpn_float64 d_dDepth[3]
Definition: vrpn_Imager.h:336
vrpn_dropped_last_connection
const char * vrpn_dropped_last_connection
Definition: vrpn_Connection.C:187
vrpn_ImagerPose_Remote::mainloop
virtual void mainloop(void)
Call this each time through the program's main loop.
Definition: vrpn_Imager.C:2038
vrpn_IMAGER_VALTYPE_UINT16
const vrpn_uint16 vrpn_IMAGER_VALTYPE_UINT16
Definition: vrpn_Imager.h:383
vrpn_Imager_Server::d_dropped_due_to_throttle
vrpn_uint16 d_dropped_due_to_throttle
Definition: vrpn_Imager.h:264
vrpn_Imager_Remote::d_region_list
vrpn_Callback_List< vrpn_IMAGERREGIONCB > d_region_list
Definition: vrpn_Imager.h:733
vrpn_BaseClassUnique::userdata
void * userdata
Definition: vrpn_BaseClass.h:287
vrpn_Imager_Remote::handle_begin_frame_message
static int VRPN_CALLBACK handle_begin_frame_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for begin-frame message from the server.
Definition: vrpn_Imager.C:1290
vrpn_Imager_Server::send_end_frame
bool send_end_frame(const vrpn_uint16 cMin, const vrpn_uint16 cMax, const vrpn_uint16 rMin, const vrpn_uint16 rMax, const vrpn_uint16 dMin=0, const vrpn_uint16 dMax=0, const struct timeval *time=NULL)
Definition: vrpn_Imager.C:190
vrpn_ImagerPose_Remote::handle_description_message
static int VRPN_CALLBACK handle_description_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for resolution and channel list message from the server.
Definition: vrpn_Imager.C:2009
vrpn_IMAGERBEGINFRAMECB::cMin
vrpn_uint16 cMin
Definition: vrpn_Imager.h:406
vrpn_IMAGERENDFRAMECB::msg_time
struct timeval msg_time
Definition: vrpn_Imager.h:413
vrpn_Imager::d_regionu8_m_id
vrpn_int32 d_regionu8_m_id
Definition: vrpn_Imager.h:145
vrpn_IMAGERBEGINFRAMECB::msg_time
struct timeval msg_time
Definition: vrpn_Imager.h:403
vrpn_Imager_Channel
Holds the description needed to convert from raw data to values for a channel.
Definition: vrpn_Imager.h:53
vrpn_IMAGER_MAX_REGIONu8
const unsigned vrpn_IMAGER_MAX_REGIONu8
Set of constants to tell how many points you can put into a region depending on the type you are putt...
Definition: vrpn_Imager.h:37
vrpn_CONNECTION_TCP_BUFLEN
const int vrpn_CONNECTION_TCP_BUFLEN
Definition: vrpn_Connection.h:95
vrpn_Imager_Remote::channel
const vrpn_Imager_Channel * channel(unsigned chanNum) const
Accessors for the member variables: can be queried in the handler for object changes.
Definition: vrpn_Imager.C:1202
vrpn_Imager_Channel::NONE
Definition: vrpn_Imager.h:112
vrpn_Imager_Channel::scale
vrpn_float32 scale
Definition: vrpn_Imager.h:73
vrpn_Imager_Server::send_region_using_base_pointer
bool send_region_using_base_pointer(vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin, vrpn_uint16 rMax, const vrpn_uint8 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride, vrpn_uint16 nRows=0, bool invert_rows=false, vrpn_uint32 depthStride=0, vrpn_uint16 dMin=0, vrpn_uint16 dMax=0, const struct timeval *time=NULL)
Pack and send the region as efficiently as possible; strides are in steps of the element being sent.
Definition: vrpn_Imager.C:320
vrpn_Imager_Remote::d_begin_frame_list
vrpn_Callback_List< vrpn_IMAGERBEGINFRAMECB > d_begin_frame_list
Definition: vrpn_Imager.h:734
vrpn_ImagerPose::compute_pixel_center
bool compute_pixel_center(vrpn_float64 *center, const vrpn_Imager &image, vrpn_uint16 col, vrpn_uint16 row, vrpn_uint16 depth=0)
This will return the location of the center of the specified.
Definition: vrpn_Imager.C:1864
vrpn_Imager_Region::d_dMin
vrpn_uint16 d_dMin
Definition: vrpn_Imager.h:613
vrpn_IMAGERENDFRAMECB::dMin
vrpn_uint16 dMin
Definition: vrpn_Imager.h:418
vrpn_IMAGER_VALTYPE_UINT12IN16
const vrpn_uint16 vrpn_IMAGER_VALTYPE_UINT12IN16
Definition: vrpn_Imager.h:384
vrpn_unbuffer
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_Imager_Channel::d_compression
ChannelCompression d_compression
Definition: vrpn_Imager.h:113
vrpn_Imager_Server::handle_throttle_message
static int VRPN_CALLBACK handle_throttle_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Imager.C:1114
vrpn_IMAGERENDFRAMECB::dMax
vrpn_uint16 dMax
Definition: vrpn_Imager.h:419
vrpn_BaseClassUnique::d_connection
vrpn_Connection * d_connection
Connection that this object talks to.
Definition: vrpn_BaseClass.h:224
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_Imager_Region::d_rMax
vrpn_uint16 d_rMax
Definition: vrpn_Imager.h:611
vrpn_ImagerPose_Remote::vrpn_ImagerPose_Remote
vrpn_ImagerPose_Remote(const char *name, vrpn_Connection *c=NULL)
Definition: vrpn_Imager.C:2000
vrpn_Connection::register_message_type
virtual vrpn_int32 register_message_type(const char *name)
Definition: vrpn_Connection.C:5074
vrpn_Imager_Region::d_valid
bool d_valid
Definition: vrpn_Imager.h:618
vrpn_Imager_Region::d_chanIndex
vrpn_int16 d_chanIndex
Definition: vrpn_Imager.h:610
vrpn_IMAGERBEGINFRAMECB::rMin
vrpn_uint16 rMin
Definition: vrpn_Imager.h:404
vrpn_ImagerPose::d_description_m_id
vrpn_int32 d_description_m_id
Definition: vrpn_Imager.h:339
vrpn_Imager_Remote::handle_region_message
static int VRPN_CALLBACK handle_region_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for region update message from the server.
Definition: vrpn_Imager.C:1238
vrpn_IMAGER_VALTYPE_FLOAT32
const vrpn_uint16 vrpn_IMAGER_VALTYPE_FLOAT32
Definition: vrpn_Imager.h:385
vrpn_dropped_connection
const char * vrpn_dropped_connection
Definition: vrpn_Connection.C:186
vrpn_CONNECTION_RELIABLE
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
Definition: vrpn_Connection.h:120
vrpn_Imager::d_discarded_frames_m_id
vrpn_int32 d_discarded_frames_m_id
Definition: vrpn_Imager.h:141
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_Imager_Channel::minVal
vrpn_float32 minVal
Definition: vrpn_Imager.h:71
vrpn_Imager_Remote::handle_description_message
static int VRPN_CALLBACK handle_description_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for resolution and channel list message from the server.
Definition: vrpn_Imager.C:1210
vrpn_IMAGERBEGINFRAMECB::dMin
vrpn_uint16 dMin
Definition: vrpn_Imager.h:408
vrpn_BaseClassUnique::d_sender_id
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Definition: vrpn_BaseClass.h:228
vrpn_Imager_Server::set_resolution
bool set_resolution(vrpn_int32 nCols, vrpn_int32 nRows, vrpn_int32 nDepth=1)
Set the resolution to a different value than it had been before. Returns true on success.
Definition: vrpn_Imager.C:1089
vrpn_Imager::d_nDepth
vrpn_int32 d_nDepth
Definition: vrpn_Imager.h:130
vrpn_ImagerPose::vrpn_ImagerPose
vrpn_ImagerPose(const char *name, vrpn_Connection *c=NULL)
Definition: vrpn_Imager.C:1841
vrpn_IMAGERENDFRAMECB::rMin
vrpn_uint16 rMin
Definition: vrpn_Imager.h:414
vrpn_Imager_Region
Helper function to convert data for a sub-region of one channel of.
Definition: vrpn_Imager.h:439
vrpn_Imager_Server::handle_last_drop_message
static int VRPN_CALLBACK handle_last_drop_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Imager.C:1149
vrpn_ImagerPose_Server::mainloop
virtual void mainloop(void)
Handle baseclass ping/pong messages.
Definition: vrpn_Imager.C:1998
vrpn_Connection::mainloop
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_Imager_Server::handle_ping_message
static int VRPN_CALLBACK handle_ping_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Imager.C:1107
vrpn_HANDLERPARAM::msg_time
struct timeval msg_time
Definition: vrpn_Connection.h:47
vrpn_Imager_Server::send_description
bool send_description(void)
Sends a description of the imager so the remote can process the region messages.
Definition: vrpn_Imager.C:1045
vrpn_Imager_Server::vrpn_Imager_Server
vrpn_Imager_Server(const char *name, vrpn_Connection *c, vrpn_int32 nCols, vrpn_int32 nRows, vrpn_int32 nDepth=1)
Definition: vrpn_Imager.C:47
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_Imager::nRows
vrpn_int32 nRows(void) const
Definition: vrpn_Imager.h:122
vrpn_Imager_Server::send_discarded_frames
bool send_discarded_frames(const vrpn_uint16 count=0, const struct timeval *time=NULL)
Definition: vrpn_Imager.C:258
vrpn_Imager::d_nCols
vrpn_int32 d_nCols
Definition: vrpn_Imager.h:129
vrpn_IMAGERREGIONCB::region
const vrpn_Imager_Region * region
Definition: vrpn_Imager.h:391
vrpn_IMAGERREGIONCB
Definition: vrpn_Imager.h:389
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_ImagerPose_Server::send_description
bool send_description(void)
Sends a description of the imager so the remote can process the region messages.
Definition: vrpn_Imager.C:1947
vrpn_Imager_Remote::handle_end_frame_message
static int VRPN_CALLBACK handle_end_frame_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for end-frame message from the server.
Definition: vrpn_Imager.C:1316
vrpn_Imager::d_regionf32_m_id
vrpn_int32 d_regionf32_m_id
Definition: vrpn_Imager.h:152
vrpn_IMAGERBEGINFRAMECB::dMax
vrpn_uint16 dMax
Definition: vrpn_Imager.h:409
vrpn_Imager_Remote::handle_connection_dropped_message
static int VRPN_CALLBACK handle_connection_dropped_message(void *userdata, vrpn_HANDLERPARAM p)
Handler for connection dropped message.
Definition: vrpn_Imager.C:1366
vrpn_ANY_SENDER
const int vrpn_ANY_SENDER
vrpn_ANY_SENDER can be used to register callbacks on a given message type from any sender.
Definition: vrpn_Connection.h:77
vrpn_ImagerPose_Server::vrpn_ImagerPose_Server
vrpn_ImagerPose_Server(const char *name, const vrpn_float64 origin[3], const vrpn_float64 dCol[3], const vrpn_float64 dRow[3], const vrpn_float64 *dDepth=NULL, vrpn_Connection *c=NULL)
Definition: vrpn_Imager.C:1909
vrpn_Imager_Remote::mainloop
virtual void mainloop(void)
XXX It could be nice to let the user specify separate callbacks for.
Definition: vrpn_Imager.C:1194
vrpn_Imager::d_begin_frame_m_id
vrpn_int32 d_begin_frame_m_id
Definition: vrpn_Imager.h:137
vrpn_ImagerPose_Remote
Definition: vrpn_Imager.h:770
vrpn_Imager_Server::d_description_sent
bool d_description_sent
Definition: vrpn_Imager.h:260
vrpn_ImagerPose_Server::set_range
bool set_range(const vrpn_float64 origin[3], const vrpn_float64 dCol[3], const vrpn_float64 dRow[3], const vrpn_float64 *dDepth=NULL)
Set the range or units. Return true on success.
Definition: vrpn_Imager.C:1933
vrpn_IMAGERBEGINFRAMECB::cMax
vrpn_uint16 cMax
Definition: vrpn_Imager.h:407
vrpn_Imager_Region::d_valBuf
const void * d_valBuf
Definition: vrpn_Imager.h:616
vrpn_IMAGER_MAX_CHANNELS
const unsigned vrpn_IMAGER_MAX_CHANNELS
Definition: vrpn_Imager.h:32
vrpn_Imager
Base class for Imager class.
Definition: vrpn_Imager.h:117
vrpn_IMAGERDISCARDEDFRAMESCB
Definition: vrpn_Imager.h:422
vrpn_IMAGER_MAX_REGIONf32
const unsigned vrpn_IMAGER_MAX_REGIONf32
Definition: vrpn_Imager.h:46
vrpn_IMAGERREGIONCB::msg_time
struct timeval msg_time
Definition: vrpn_Imager.h:390
vrpn_Imager_Region::decode_unscaled_region_using_base_pointer
bool decode_unscaled_region_using_base_pointer(vrpn_uint8 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride, vrpn_uint32 depthStride=0, vrpn_uint16 nRows=0, bool invert_rows=false, unsigned repeat=1) const
As efficiently as possible, pull the values out of the VRPN buffer and put them into the array whose ...
Definition: vrpn_Imager.C:1441
vrpn_Imager::vrpn_Imager
vrpn_Imager(const char *name, vrpn_Connection *c=NULL)
Definition: vrpn_Imager.C:6
vrpn_IMAGERENDFRAMECB::rMax
vrpn_uint16 rMax
Definition: vrpn_Imager.h:415
vrpn_Imager::d_throttle_frames_m_id
vrpn_int32 d_throttle_frames_m_id
Definition: vrpn_Imager.h:143
vrpn_IMAGERBEGINFRAMECB
Definition: vrpn_Imager.h:402
vrpn_Imager_Server::mainloop
virtual void mainloop(void)
Handle baseclass ping/pong messages.
Definition: vrpn_Imager.C:1105
vrpn_IMAGERENDFRAMECB::cMax
vrpn_uint16 cMax
Definition: vrpn_Imager.h:417
vrpn_Imager::d_description_m_id
vrpn_int32 d_description_m_id
Definition: vrpn_Imager.h:135
vrpn_Imager::nDepth
vrpn_int32 nDepth(void) const
Definition: vrpn_Imager.h:124
vrpn_ImagerPose_Remote::d_description_list
vrpn_Callback_List< struct timeval > d_description_list
Definition: vrpn_Imager.h:794
vrpn_ImagerPose::d_dRow
vrpn_float64 d_dRow[3]
Definition: vrpn_Imager.h:335
vrpn_BaseClass::init
virtual int init(void)
Initialize things that the constructor can't. Returns 0 on success, -1 on failure.
Definition: vrpn_BaseClass.C:363
vrpn_Imager_Region::d_cMax
vrpn_uint16 d_cMax
Definition: vrpn_Imager.h:612
vrpn_Imager_Channel::maxVal
vrpn_float32 maxVal
Definition: vrpn_Imager.h:71
vrpn_buffer
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
cName
char cName[100]
Length of names within VRPN.
Definition: vrpn_Connection.h:158
vrpn_Imager_Channel::unbuffer
bool unbuffer(const char **buffer)
Definition: vrpn_Imager.h:96
vrpn_Callback_List::call_handlers
void call_handlers(const CALLBACK_STRUCT &info)
This will pass the referenced parameter as a const to all the callbacks.
Definition: vrpn_BaseClass.h:451
vrpn_Imager_Server::d_frames_to_send
vrpn_int32 d_frames_to_send
Definition: vrpn_Imager.h:261
vrpn_Imager_Remote::d_end_frame_list
vrpn_Callback_List< vrpn_IMAGERENDFRAMECB > d_end_frame_list
Definition: vrpn_Imager.h:735
vrpn_Imager_Server::send_region_using_first_pointer
bool send_region_using_first_pointer(vrpn_int16 chanIndex, vrpn_uint16 cMin, vrpn_uint16 cMax, vrpn_uint16 rMin, vrpn_uint16 rMax, const vrpn_uint8 *data, vrpn_uint32 colStride, vrpn_uint32 rowStride, vrpn_uint16 nRows=0, bool invert_rows=false, vrpn_uint32 depthStride=0, vrpn_uint16 dMin=0, vrpn_uint16 dMax=0, const struct timeval *time=NULL)
Pack and send the region as efficiently as possible; strides are in steps of the element being sent.
Definition: vrpn_Imager.C:917
vrpn_Imager::register_types
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail.
Definition: vrpn_Imager.C:16
vrpn_Imager::d_nRows
vrpn_int32 d_nRows
Definition: vrpn_Imager.h:125
vrpn_IMAGERENDFRAMECB::cMin
vrpn_uint16 cMin
Definition: vrpn_Imager.h:416
vrpn_Imager_Remote
This is the class users deal with: it tells the format and the region data when it arrives.
Definition: vrpn_Imager.h:623
vrpn_Imager_Server
Definition: vrpn_Imager.h:156
vrpn_Imager_Region::d_rMin
vrpn_uint16 d_rMin
Definition: vrpn_Imager.h:611
vrpn_ImagerPose
Definition: vrpn_Imager.h:279
vrpn_Imager::nCols
vrpn_int32 nCols(void) const
Definition: vrpn_Imager.h:123
vrpn_IMAGER_MAX_REGIONu16
const unsigned vrpn_IMAGER_MAX_REGIONu16
Definition: vrpn_Imager.h:41
vrpn_Imager_Remote::d_got_description
bool d_got_description
Definition: vrpn_Imager.h:730
vrpn_Imager_Region::d_cMin
vrpn_uint16 d_cMin
Definition: vrpn_Imager.h:612
vrpn_Imager_Channel::offset
vrpn_float32 offset
Definition: vrpn_Imager.h:73
vrpn_IMAGERDISCARDEDFRAMESCB::count
vrpn_uint16 count
Definition: vrpn_Imager.h:424
vrpn_BaseClassUnique::server_mainloop
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Definition: vrpn_BaseClass.C:603
vrpn_BaseClass
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
Definition: vrpn_BaseClass.h:313
vrpn_Imager_Remote::d_discarded_frames_list
vrpn_Callback_List< vrpn_IMAGERDISCARDEDFRAMESCB > d_discarded_frames_list
Definition: vrpn_Imager.h:736
vrpn_Imager.h
vrpn_Imager_Region::d_dMax
vrpn_uint16 d_dMax
Definition: vrpn_Imager.h:613
vrpn_IMAGERENDFRAMECB
Definition: vrpn_Imager.h:412