Panda3D
 All Classes Functions Variables Enumerations
vrpnClient.cxx
1 // Filename: vrpnClient.cxx
2 // Created by: jason (04Aug00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "vrpnClient.h"
16 #include "vrpnTracker.h"
17 #include "vrpnTrackerDevice.h"
18 #include "vrpnButton.h"
19 #include "vrpnButtonDevice.h"
20 #include "vrpnAnalog.h"
21 #include "vrpnAnalogDevice.h"
22 #include "vrpnDial.h"
23 #include "vrpnDialDevice.h"
24 #include "config_vrpn.h"
25 
26 #include "dcast.h"
27 #include "string_utils.h"
28 #include "indent.h"
29 
30 TypeHandle VrpnClient::_type_handle;
31 
32 ////////////////////////////////////////////////////////////////////
33 // Function: VrpnClient::Constructor
34 // Access: Public
35 // Description:
36 ////////////////////////////////////////////////////////////////////
37 VrpnClient::
38 VrpnClient(const string &server_name) :
39  _server_name(server_name)
40 {
41  if (vrpn_cat.is_debug()) {
42  vrpn_cat.debug()
43  << "Attempting to connect to VRPN server " << _server_name
44  << "\n";
45  }
46  _connection = vrpn_get_connection_by_name(_server_name.c_str());
47  nassertv(_connection != (vrpn_Connection *)NULL);
48 
49  if (!is_valid()) {
50  vrpn_cat.warning()
51  << "Unable to establish connection to VRPN server " << _server_name
52  << "\n";
53  }
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: VrpnClient::Constructor
58 // Access: Public
59 // Description:
60 ////////////////////////////////////////////////////////////////////
61 VrpnClient::
62 ~VrpnClient() {
63  delete _connection;
64 }
65 
66 ////////////////////////////////////////////////////////////////////
67 // Function: VrpnClient::write
68 // Access: Public
69 // Description: Writes a list of the active devices that the
70 // VrpnClient is currently polling each frame.
71 ////////////////////////////////////////////////////////////////////
72 void VrpnClient::
73 write(ostream &out, int indent_level) const {
74  indent(out, indent_level)
75  << "VrpnClient, server " << _server_name << "\n";
76 
77  if (!is_valid()) {
78  indent(out, indent_level + 2)
79  << "(error)\n";
80  } else if (!is_connected()) {
81  indent(out, indent_level + 2)
82  << "(no connection)\n";
83  }
84 
85  if (!_trackers.empty()) {
86  indent(out, indent_level + 2)
87  << _trackers.size() << " trackers:\n";
88  Trackers::const_iterator ti;
89  for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
90  VrpnTracker *vrpn_tracker = (*ti).second;
91  vrpn_tracker->write(out, indent_level + 4);
92  }
93  }
94 
95  if (!_buttons.empty()) {
96  indent(out, indent_level + 2)
97  << _buttons.size() << " buttons:\n";
98  Buttons::const_iterator bi;
99  for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
100  VrpnButton *vrpn_button = (*bi).second;
101  vrpn_button->write(out, indent_level + 4);
102  }
103  }
104 
105  if (!_analogs.empty()) {
106  indent(out, indent_level + 2)
107  << _analogs.size() << " analogs:\n";
108  Analogs::const_iterator ai;
109  for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
110  VrpnAnalog *vrpn_analog = (*ai).second;
111  vrpn_analog->write(out, indent_level + 4);
112  }
113  }
114 
115  if (!_dials.empty()) {
116  indent(out, indent_level + 2)
117  << _dials.size() << " dials:\n";
118  Dials::const_iterator di;
119  for (di = _dials.begin(); di != _dials.end(); ++di) {
120  VrpnDial *vrpn_dial = (*di).second;
121  vrpn_dial->write(out, indent_level + 4);
122  }
123  }
124 }
125 
126 ////////////////////////////////////////////////////////////////////
127 // Function: VrpnClient::make_device
128 // Access: Protected, Virtual
129 // Description: Creates and returns a new ClientDevice of the
130 // appropriate type, according to the requested
131 // device_type and device_name. Returns NULL if a
132 // matching device cannot be found.
133 //
134 // This is guaranteed not to be called twice for a given
135 // device_type/device_name combination (unless
136 // disconnect_device() has already been called for the
137 // same device_type/device_name).
138 ////////////////////////////////////////////////////////////////////
140 make_device(TypeHandle device_type, const string &device_name) {
141  if (device_type == ClientTrackerDevice::get_class_type()) {
142  return make_tracker_device(device_name);
143 
144  } else if (device_type == ClientButtonDevice::get_class_type()) {
145  return make_button_device(device_name);
146 
147  } else if (device_type == ClientAnalogDevice::get_class_type()) {
148  return make_analog_device(device_name);
149 
150  } else if (device_type == ClientDialDevice::get_class_type()) {
151  return make_dial_device(device_name);
152 
153  } else {
154  return NULL;
155  }
156 }
157 
158 ////////////////////////////////////////////////////////////////////
159 // Function: VrpnClient::disconnect_device
160 // Access: Protected, Virtual
161 // Description: Removes the device, which is presumably about to
162 // destruct, from the list of connected devices, and
163 // frees any data required to support it. This device
164 // will no longer receive automatic updates with each
165 // poll.
166 //
167 // The return value is true if the device was
168 // disconnected, or false if it was unknown (e.g. it was
169 // disconnected previously).
170 ////////////////////////////////////////////////////////////////////
171 bool VrpnClient::
172 disconnect_device(TypeHandle device_type, const string &device_name,
173  ClientDevice *device) {
174  if (vrpn_cat.is_debug()) {
175  vrpn_cat.debug()
176  << "Disconnecting device " << *device << "\n";
177  }
178 
179  if (ClientBase::disconnect_device(device_type, device_name, device)) {
180  if (device->is_of_type(VrpnTrackerDevice::get_class_type())) {
181  disconnect_tracker_device(DCAST(VrpnTrackerDevice, device));
182 
183  } else if (device->is_of_type(VrpnButtonDevice::get_class_type())) {
184  disconnect_button_device(DCAST(VrpnButtonDevice, device));
185 
186  } else if (device->is_of_type(VrpnAnalogDevice::get_class_type())) {
187  disconnect_analog_device(DCAST(VrpnAnalogDevice, device));
188 
189  } else if (device->is_of_type(VrpnDialDevice::get_class_type())) {
190  disconnect_dial_device(DCAST(VrpnDialDevice, device));
191 
192  }
193  return true;
194  }
195 
196  return false;
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: VrpnClient::do_poll
201 // Access: Protected, Virtual
202 // Description: Implements the polling and updating of connected
203 // devices, if the ClientBase requires this. This may
204 // be called in a sub-thread if
205 // fork_asynchronous_thread() was called; otherwise, it
206 // will be called once per frame.
207 ////////////////////////////////////////////////////////////////////
208 void VrpnClient::
209 do_poll() {
210  ClientBase::do_poll();
211 
212  if (vrpn_cat.is_spam()) {
213  vrpn_cat.spam()
214  << "VrpnClient " << _server_name << " polling "
215  << _trackers.size() + _buttons.size() + _analogs.size() + _dials.size()
216  << " devices.\n";
217  }
218 
219  Trackers::iterator ti;
220  for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
221  VrpnTracker *vrpn_tracker = (*ti).second;
222  vrpn_tracker->poll();
223  }
224 
225  Buttons::iterator bi;
226  for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
227  VrpnButton *vrpn_button = (*bi).second;
228  vrpn_button->poll();
229  }
230 
231  Analogs::iterator ai;
232  for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
233  VrpnAnalog *vrpn_analog = (*ai).second;
234  vrpn_analog->poll();
235  }
236 
237  Dials::iterator di;
238  for (di = _dials.begin(); di != _dials.end(); ++di) {
239  VrpnDial *vrpn_dial = (*di).second;
240  vrpn_dial->poll();
241  }
242 }
243 
244 ////////////////////////////////////////////////////////////////////
245 // Function: VrpnClient::make_tracker_device
246 // Access: Private
247 // Description: Creates a new tracker device. The device_name is
248 // parsed for sensor and data_type information.
249 //
250 // The device_name may be one of the following:
251 //
252 // tracker_name
253 // tracker_name:N
254 // tracker_name:N[pva]
255 //
256 // Where N is an integer sensor number, and [pva] is one
257 // of the lowercase letters p, v, or a.
258 //
259 // In the first form, the device connects to the
260 // indicated tracker, and reports position information
261 // on sensor number 0.
262 //
263 // In the second form, the device connects to the
264 // indicated tracker, and reports position information
265 // on the indicated sensor number.
266 //
267 // In the third form, the device connects to the
268 // indicated tracker, and reports either position,
269 // velocity, or acceleration information on the
270 // indicated sensor number.
271 ////////////////////////////////////////////////////////////////////
273 make_tracker_device(const string &device_name) {
274  if (vrpn_cat.is_debug()) {
275  vrpn_cat.debug()
276  << "Making tracker device for " << device_name << "\n";
277  }
278 
279  string tracker_name = device_name;
280  int sensor = 0;
281  VrpnTrackerDevice::DataType data_type = VrpnTrackerDevice::DT_position;
282 
283  size_t colon = device_name.rfind(':');
284  if (colon != string::npos && colon + 1 < device_name.length()) {
285  size_t begin = colon + 1;
286  size_t end = device_name.length();
287  VrpnTrackerDevice::DataType maybe_data_type = data_type;
288 
289  switch (device_name[end - 1]) {
290  case 'p':
291  maybe_data_type = VrpnTrackerDevice::DT_position;
292  end--;
293  break;
294 
295  case 'v':
296  maybe_data_type = VrpnTrackerDevice::DT_velocity;
297  end--;
298  break;
299 
300  case 'a':
301  maybe_data_type = VrpnTrackerDevice::DT_acceleration;
302  end--;
303  break;
304  }
305  int maybe_sensor;
306  if (string_to_int(device_name.substr(begin, end - begin), maybe_sensor)) {
307  // It seems to be a legitimate integer!
308  sensor = maybe_sensor;
309  data_type = maybe_data_type;
310  tracker_name = device_name.substr(0, colon);
311  }
312  }
313 
314  VrpnTracker *tracker = get_tracker(tracker_name);
315 
316  VrpnTrackerDevice *device =
317  new VrpnTrackerDevice(this, device_name, sensor, data_type, tracker);
318 
319  if (vrpn_cat.is_debug()) {
320  vrpn_cat.debug()
321  << "Creating " << *device << "\n";
322  }
323 
324  tracker->mark(device);
325  return device;
326 }
327 
328 ////////////////////////////////////////////////////////////////////
329 // Function: VrpnClient::make_button_device
330 // Access: Private
331 // Description: Creates a new button device. The device_name is sent
332 // verbatim to the VRPN library.
333 ////////////////////////////////////////////////////////////////////
335 make_button_device(const string &device_name) {
336  if (vrpn_cat.is_debug()) {
337  vrpn_cat.debug()
338  << "Making button device for " << device_name << "\n";
339  }
340 
341  VrpnButton *button = get_button(device_name);
342 
343  VrpnButtonDevice *device =
344  new VrpnButtonDevice(this, device_name, button);
345 
346  if (vrpn_cat.is_debug()) {
347  vrpn_cat.debug()
348  << "Creating " << *device << "\n";
349  }
350 
351  button->mark(device);
352  return device;
353 }
354 
355 ////////////////////////////////////////////////////////////////////
356 // Function: VrpnClient::make_analog_device
357 // Access: Private
358 // Description: Creates a new analog device. The device_name is sent
359 // verbatim to the VRPN library.
360 ////////////////////////////////////////////////////////////////////
362 make_analog_device(const string &device_name) {
363  if (vrpn_cat.is_debug()) {
364  vrpn_cat.debug()
365  << "Making analog device for " << device_name << "\n";
366  }
367 
368  VrpnAnalog *analog = get_analog(device_name);
369 
370  VrpnAnalogDevice *device =
371  new VrpnAnalogDevice(this, device_name, analog);
372 
373  if (vrpn_cat.is_debug()) {
374  vrpn_cat.debug()
375  << "Creating " << *device << "\n";
376  }
377 
378  analog->mark(device);
379  return device;
380 }
381 
382 ////////////////////////////////////////////////////////////////////
383 // Function: VrpnClient::make_dial_device
384 // Access: Private
385 // Description: Creates a new dial device. The device_name is sent
386 // verbatim to the VRPN library.
387 ////////////////////////////////////////////////////////////////////
389 make_dial_device(const string &device_name) {
390  if (vrpn_cat.is_debug()) {
391  vrpn_cat.debug()
392  << "Making dial device for " << device_name << "\n";
393  }
394 
395  VrpnDial *dial = get_dial(device_name);
396 
397  VrpnDialDevice *device =
398  new VrpnDialDevice(this, device_name, dial);
399 
400  if (vrpn_cat.is_debug()) {
401  vrpn_cat.debug()
402  << "Creating " << *device << "\n";
403  }
404 
405  dial->mark(device);
406  return device;
407 }
408 
409 ////////////////////////////////////////////////////////////////////
410 // Function: VrpnClient::disconnect_tracker_device
411 // Access: Private
412 // Description: Removes the tracker device from the list of things to
413 // be updated.
414 ////////////////////////////////////////////////////////////////////
415 void VrpnClient::
416 disconnect_tracker_device(VrpnTrackerDevice *device) {
417  VrpnTracker *vrpn_tracker = device->get_vrpn_tracker();
418  vrpn_tracker->unmark(device);
419  if (vrpn_tracker->is_empty()) {
420  free_tracker(vrpn_tracker);
421  }
422 }
423 
424 ////////////////////////////////////////////////////////////////////
425 // Function: VrpnClient::disconnect_button_device
426 // Access: Private
427 // Description: Removes the button device from the list of things to
428 // be updated.
429 ////////////////////////////////////////////////////////////////////
430 void VrpnClient::
431 disconnect_button_device(VrpnButtonDevice *device) {
432  VrpnButton *vrpn_button = device->get_vrpn_button();
433  vrpn_button->unmark(device);
434  if (vrpn_button->is_empty()) {
435  free_button(vrpn_button);
436  }
437 }
438 
439 ////////////////////////////////////////////////////////////////////
440 // Function: VrpnClient::disconnect_analog_device
441 // Access: Private
442 // Description: Removes the analog device from the list of things to
443 // be updated.
444 ////////////////////////////////////////////////////////////////////
445 void VrpnClient::
446 disconnect_analog_device(VrpnAnalogDevice *device) {
447  VrpnAnalog *vrpn_analog = device->get_vrpn_analog();
448  vrpn_analog->unmark(device);
449  if (vrpn_analog->is_empty()) {
450  free_analog(vrpn_analog);
451  }
452 }
453 
454 ////////////////////////////////////////////////////////////////////
455 // Function: VrpnClient::disconnect_dial_device
456 // Access: Private
457 // Description: Removes the dial device from the list of things to
458 // be updated.
459 ////////////////////////////////////////////////////////////////////
460 void VrpnClient::
461 disconnect_dial_device(VrpnDialDevice *device) {
462  VrpnDial *vrpn_dial = device->get_vrpn_dial();
463  vrpn_dial->unmark(device);
464  if (vrpn_dial->is_empty()) {
465  free_dial(vrpn_dial);
466  }
467 }
468 
469 ////////////////////////////////////////////////////////////////////
470 // Function: VrpnClient::get_tracker
471 // Access: Private
472 // Description: Finds a VrpnTracker of the indicated name, and
473 // returns it if one already exists, or creates a new
474 // one if it does not.
475 ////////////////////////////////////////////////////////////////////
476 VrpnTracker *VrpnClient::
477 get_tracker(const string &tracker_name) {
478  Trackers::iterator ti;
479  ti = _trackers.find(tracker_name);
480 
481  if (ti != _trackers.end()) {
482  return (*ti).second;
483  }
484 
485  VrpnTracker *vrpn_tracker = new VrpnTracker(tracker_name, _connection);
486  _trackers.insert(Trackers::value_type(tracker_name, vrpn_tracker));
487 
488  if (vrpn_cat.is_debug()) {
489  vrpn_cat.debug()
490  << "Creating tracker " << *vrpn_tracker << "\n";
491  }
492 
493  return vrpn_tracker;
494 }
495 
496 ////////////////////////////////////////////////////////////////////
497 // Function: VrpnClient::free_tracker
498 // Access: Private
499 // Description: Removes and deletes the indicated VrpnTracker, which
500 // is no longer referenced by any VrpnTrackerDevices.
501 ////////////////////////////////////////////////////////////////////
502 void VrpnClient::
503 free_tracker(VrpnTracker *vrpn_tracker) {
504  nassertv(vrpn_tracker->is_empty());
505 
506  if (vrpn_cat.is_debug()) {
507  vrpn_cat.debug()
508  << "Deleting tracker " << *vrpn_tracker << "\n";
509  }
510 
511  Trackers::iterator ti;
512  ti = _trackers.find(vrpn_tracker->get_tracker_name());
513  nassertv(ti != _trackers.end());
514  nassertv((*ti).second == vrpn_tracker);
515 
516  _trackers.erase(ti);
517  delete vrpn_tracker;
518 }
519 
520 ////////////////////////////////////////////////////////////////////
521 // Function: VrpnClient::get_button
522 // Access: Private
523 // Description: Finds a VrpnButton of the indicated name, and
524 // returns it if one already exists, or creates a new
525 // one if it does not.
526 ////////////////////////////////////////////////////////////////////
527 VrpnButton *VrpnClient::
528 get_button(const string &button_name) {
529  Buttons::iterator bi;
530  bi = _buttons.find(button_name);
531 
532  if (bi != _buttons.end()) {
533  return (*bi).second;
534  }
535 
536  VrpnButton *vrpn_button = new VrpnButton(button_name, _connection);
537  _buttons.insert(Buttons::value_type(button_name, vrpn_button));
538 
539  if (vrpn_cat.is_debug()) {
540  vrpn_cat.debug()
541  << "Creating button " << *vrpn_button << "\n";
542  }
543 
544  return vrpn_button;
545 }
546 
547 ////////////////////////////////////////////////////////////////////
548 // Function: VrpnClient::free_button
549 // Access: Private
550 // Description: Removes and deletes the indicated VrpnButton, which
551 // is no longer referenced by any VrpnButtonDevices.
552 ////////////////////////////////////////////////////////////////////
553 void VrpnClient::
554 free_button(VrpnButton *vrpn_button) {
555  nassertv(vrpn_button->is_empty());
556 
557  if (vrpn_cat.is_debug()) {
558  vrpn_cat.debug()
559  << "Deleting button " << *vrpn_button << "\n";
560  }
561 
562  Buttons::iterator bi;
563  bi = _buttons.find(vrpn_button->get_button_name());
564  nassertv(bi != _buttons.end());
565  nassertv((*bi).second == vrpn_button);
566 
567  _buttons.erase(bi);
568  delete vrpn_button;
569 }
570 
571 ////////////////////////////////////////////////////////////////////
572 // Function: VrpnClient::get_analog
573 // Access: Private
574 // Description: Finds a VrpnAnalog of the indicated name, and
575 // returns it if one already exists, or creates a new
576 // one if it does not.
577 ////////////////////////////////////////////////////////////////////
578 VrpnAnalog *VrpnClient::
579 get_analog(const string &analog_name) {
580  Analogs::iterator ai;
581  ai = _analogs.find(analog_name);
582 
583  if (ai != _analogs.end()) {
584  return (*ai).second;
585  }
586 
587  VrpnAnalog *vrpn_analog = new VrpnAnalog(analog_name, _connection);
588  _analogs.insert(Analogs::value_type(analog_name, vrpn_analog));
589 
590  if (vrpn_cat.is_debug()) {
591  vrpn_cat.debug()
592  << "Creating analog " << *vrpn_analog << "\n";
593  }
594 
595  return vrpn_analog;
596 }
597 
598 ////////////////////////////////////////////////////////////////////
599 // Function: VrpnClient::free_analog
600 // Access: Private
601 // Description: Removes and deletes the indicated VrpnAnalog, which
602 // is no longer referenced by any VrpnAnalogDevices.
603 ////////////////////////////////////////////////////////////////////
604 void VrpnClient::
605 free_analog(VrpnAnalog *vrpn_analog) {
606  nassertv(vrpn_analog->is_empty());
607 
608  if (vrpn_cat.is_debug()) {
609  vrpn_cat.debug()
610  << "Deleting analog " << *vrpn_analog << "\n";
611  }
612 
613  Analogs::iterator ai;
614  ai = _analogs.find(vrpn_analog->get_analog_name());
615  nassertv(ai != _analogs.end());
616  nassertv((*ai).second == vrpn_analog);
617 
618  _analogs.erase(ai);
619  delete vrpn_analog;
620 }
621 
622 ////////////////////////////////////////////////////////////////////
623 // Function: VrpnClient::get_dial
624 // Access: Private
625 // Description: Finds a VrpnDial of the indicated name, and
626 // returns it if one already exists, or creates a new
627 // one if it does not.
628 ////////////////////////////////////////////////////////////////////
629 VrpnDial *VrpnClient::
630 get_dial(const string &dial_name) {
631  Dials::iterator di;
632  di = _dials.find(dial_name);
633 
634  if (di != _dials.end()) {
635  return (*di).second;
636  }
637 
638  VrpnDial *vrpn_dial = new VrpnDial(dial_name, _connection);
639  _dials.insert(Dials::value_type(dial_name, vrpn_dial));
640 
641  if (vrpn_cat.is_debug()) {
642  vrpn_cat.debug()
643  << "Creating dial " << *vrpn_dial << "\n";
644  }
645 
646  return vrpn_dial;
647 }
648 
649 ////////////////////////////////////////////////////////////////////
650 // Function: VrpnClient::free_dial
651 // Access: Private
652 // Description: Removes and deletes the indicated VrpnDial, which
653 // is no longer referenced by any VrpnDialDevices.
654 ////////////////////////////////////////////////////////////////////
655 void VrpnClient::
656 free_dial(VrpnDial *vrpn_dial) {
657  nassertv(vrpn_dial->is_empty());
658 
659  if (vrpn_cat.is_debug()) {
660  vrpn_cat.debug()
661  << "Deleting dial " << *vrpn_dial << "\n";
662  }
663 
664  Dials::iterator di;
665  di = _dials.find(vrpn_dial->get_dial_name());
666  nassertv(di != _dials.end());
667  nassertv((*di).second == vrpn_dial);
668 
669  _dials.erase(di);
670  delete vrpn_dial;
671 }
672 
673 
674 #if 0
675 
676 #include "datagram.h"
677 #include "datagramIterator.h"
678 
679 typedef struct {
680  string device_name;
681  void *self;
682 } VrpnClientInfo;
683 
684 
685 ////////////////////////////////////////////////////////////////////
686 // Function: VrpnClient::add_remote_tracker
687 // Access: Public, Virtual
688 // Description: Creates a new vrpn remote tracker object and registers
689 // a callback with it.
690 ////////////////////////////////////////////////////////////////////
691 bool VrpnClient::
692 add_remote_tracker(const string &tracker, int sensor) {
693 
694  vrpn_Tracker_Remote *vrpn_tracker = new vrpn_Tracker_Remote(tracker.c_str(), _connection);
695  if (vrpn_tracker == (vrpn_Tracker_Remote *)NULL) {
696  return false;
697  }
698 
699  //Now package up the information that needs to be passed to the
700  //callback function to allow it to determine for which tracker we
701  //are receiving information for
702  VrpnClientInfo *data = new VrpnClientInfo;
703  data->device_name = tracker;
704  data->self = this;
705 
706  vrpn_tracker->register_change_handler((void*)data, st_tracker_position);
707  vrpn_tracker->register_change_handler((void*)data, st_tracker_velocity);
708  vrpn_tracker->register_change_handler((void*)data, st_tracker_acceleration);
709 
710  _vrpn_trackers[tracker] = vrpn_tracker;
711  _trackers.push_back(tracker);
712  _sensors[tracker].push_back(sensor);
713 
714  return true;
715 }
716 
717 ////////////////////////////////////////////////////////////////////
718 // Function: VrpnClient::add_remote_analog
719 // Access: Public, Virtual
720 // Description: Creates a new vrpn remote analog object and registers
721 // a callback with it.
722 ////////////////////////////////////////////////////////////////////
723 bool VrpnClient::
724 add_remote_analog(const string &analog) {
725 
726  vrpn_Analog_Remote *vrpn_analog = new vrpn_Analog_Remote(analog.c_str(), _connection);
727  if (vrpn_analog == (vrpn_Analog_Remote *)NULL) {
728  return false;
729  }
730 
731  //Now package up the information that needs to be passed to the
732  //callback function to allow it to determine for which analog we
733  //are receiving information for
734  VrpnClientInfo *data = new VrpnClientInfo;
735  data->device_name = analog;
736  data->self = this;
737 
738  vrpn_analog->register_change_handler((void*)data, st_analog);
739 
740  _vrpn_analogs[analog] = vrpn_analog;
741  _analogs.push_back(analog);
742 
743  return true;
744 }
745 
746 ////////////////////////////////////////////////////////////////////
747 // Function: VrpnClient::add_remote_button
748 // Access: Public, Virtual
749 // Description: Creates a new vrpn remote button object and registers
750 // a callback with it.
751 ////////////////////////////////////////////////////////////////////
752 bool VrpnClient::
753 add_remote_button(const string &button) {
754 
755  vrpn_Button_Remote *vrpn_button = new vrpn_Button_Remote(button.c_str(), _connection);
756  if (vrpn_button == (vrpn_Button_Remote *)NULL) {
757  return false;
758  }
759 
760  //Now package up the information that needs to be passed to the
761  //callback function to allow it to determine for which button we
762  //are receiving information for
763  VrpnClientInfo *data = new VrpnClientInfo;
764  data->device_name = button;
765  data->self = this;
766 
767  vrpn_button->register_change_handler((void*)data, st_button);
768 
769  _vrpn_buttons[button] = vrpn_button;
770  _buttons.push_back(button);
771 
772  return true;
773 }
774 
775 ////////////////////////////////////////////////////////////////////
776 // Function: VrpnClient::add_remote_dial
777 // Access: Public, Virtual
778 // Description: Creates a new vrpn remote dial object and registers
779 // a callback with it.
780 ////////////////////////////////////////////////////////////////////
781 bool VrpnClient::
782 add_remote_dial(const string &dial) {
783 
784  vrpn_Dial_Remote *vrpn_dial = new vrpn_Dial_Remote(dial.c_str(), _connection);
785  if (vrpn_dial == (vrpn_Dial_Remote *)NULL) {
786  return false;
787  }
788 
789  //Now package up the information that needs to be passed to the
790  //callback function to allow it to determine for which dial we
791  //are receiving information for
792  VrpnClientInfo *data = new VrpnClientInfo;
793  data->device_name = dial;
794  data->self = this;
795 
796  vrpn_dial->register_change_handler((void*)data, st_dial);
797 
798  _vrpn_dials[dial] = vrpn_dial;
799  _dials.push_back(dial);
800 
801  return true;
802 }
803 
804 ////////////////////////////////////////////////////////////////////
805 // Function: VrpnClient::max_analog_channels
806 // Access: Public, Virtual
807 // Description: Max number of analog channels
808 ////////////////////////////////////////////////////////////////////
809 int VrpnClient::
810 max_analog_channels() {
811  return vrpn_CHANNEL_MAX;
812 }
813 
814 ////////////////////////////////////////////////////////////////////
815 // Function: VrpnClient::poll_trackers
816 // Access: Public, Virtual
817 // Description: Calls mainloop for the registered tracker object
818 // Note: In a non-threaded case, this may need to come up with
819 // some kind of cacheing scheme so we don't call mainloop
820 // multiple times when a user is just asking for the data
821 // of multiple sensors on 1 tracker (as that is the interface
822 // supported). This is a non-trivial problem as it is
823 // difficult to know when we should and shouldn't cache.
824 ////////////////////////////////////////////////////////////////////
825 void VrpnClient::
826 poll_tracker(const string &tracker) {
827  _vrpn_trackers[tracker]->mainloop();
828 }
829 
830 ////////////////////////////////////////////////////////////////////
831 // Function: VrpnClient::poll_analog
832 // Access: Public, Virtual
833 // Description: Calls mainloop for the registered analog object
834 ////////////////////////////////////////////////////////////////////
835 void VrpnClient::
836 poll_analog(const string &analog) {
837  _vrpn_analogs[analog]->mainloop();
838 }
839 
840 ////////////////////////////////////////////////////////////////////
841 // Function: VrpnClient::poll_button
842 // Access: Public, Virtual
843 // Description: Calls mainloop for the registered button object
844 ////////////////////////////////////////////////////////////////////
845 void VrpnClient::
846 poll_button(const string &button) {
847  _vrpn_buttons[button]->mainloop();
848 }
849 
850 ////////////////////////////////////////////////////////////////////
851 // Function: VrpnClient::poll_dial
852 // Access: Public, Virtual
853 // Description: Calls mainloop for the registered dial object
854 ////////////////////////////////////////////////////////////////////
855 void VrpnClient::
856 poll_dial(const string &dial) {
857  _vrpn_dials[dial]->mainloop();
858 }
859 
860 ////////////////////////////////////////////////////////////////////
861 // Function: VrpnClient::st_tracker_position
862 // Access: Private, Static
863 // Description: Callback function that merely passes the data down
864 // to the appropriate non-static function
865 ////////////////////////////////////////////////////////////////////
866 void VRPN_CALLBACK VrpnClient::
867 st_tracker_position(void *userdata, const vrpn_TRACKERCB info) {
868  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
869  ((VrpnClient *)data->self)->tracker_position(data->device_name, info);
870 }
871 
872 ////////////////////////////////////////////////////////////////////
873 // Function: VrpnClient::st_tracker_velocity
874 // Access: Private, Static
875 // Description: Callback function that merely passes the data down
876 // to the appropriate non-static function
877 ////////////////////////////////////////////////////////////////////
878 void VRPN_CALLBACK VrpnClient::
879 st_tracker_velocity(void *userdata, const vrpn_TRACKERVELCB info) {
880  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
881  ((VrpnClient *)data->self)->tracker_velocity(data->device_name, info);
882 }
883 ////////////////////////////////////////////////////////////////////
884 // Function: VrpnClient::st_tracker_acceleration
885 // Access: Private, Static
886 // Description: Callback function that merely passes the data down
887 // to the appropriate non-static function
888 ////////////////////////////////////////////////////////////////////
889 void VRPN_CALLBACK VrpnClient::
890 st_tracker_acceleration(void *userdata, const vrpn_TRACKERACCCB info) {
891  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
892  ((VrpnClient *)data->self)->tracker_acceleration(data->device_name, info);
893 }
894 
895 ////////////////////////////////////////////////////////////////////
896 // Function: VrpnClient::st_analog
897 // Access: Private, Static
898 // Description: Callback function that merely passes the data down
899 // to the appropriate non-static function
900 ////////////////////////////////////////////////////////////////////
901 void VrpnClient::
902 st_analog(void *userdata, const vrpn_ANALOGCB info) {
903  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
904  ((VrpnClient *)data->self)->analog(data->device_name, info);
905 }
906 
907 ////////////////////////////////////////////////////////////////////
908 // Function: VrpnClient::st_button
909 // Access: Private, Static
910 // Description: Callback function that merely passes the data down
911 // to the appropriate non-static function
912 ////////////////////////////////////////////////////////////////////
913 void VrpnClient::
914 st_button(void *userdata, const vrpn_BUTTONCB info) {
915  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
916  ((VrpnClient *)data->self)->button(data->device_name, info);
917 }
918 
919 ////////////////////////////////////////////////////////////////////
920 // Function: VrpnClient::st_dial
921 // Access: Private, Static
922 // Description: Callback function that merely passes the data down
923 // to the appropriate non-static function
924 ////////////////////////////////////////////////////////////////////
925 void VrpnClient::
926 st_dial(void *userdata, const vrpn_DIALCB info) {
927  VrpnClientInfo *data = (VrpnClientInfo *)userdata;
928  ((VrpnClient *)data->self)->dial(data->device_name, info);
929 }
930 
931 #endif
void unmark(VrpnButtonDevice *device)
Removes the indicated VrpnButtonDevice from the list of devices that are sharing this VrpnButton...
Definition: vrpnButton.cxx:69
void poll()
Polls the connected device.
Definition: vrpnButton.I:45
A specific ClientBase that connects to a VRPN server and records information on the connected VRPN de...
Definition: vrpnClient.h:38
void unmark(VrpnAnalogDevice *device)
Removes the indicated VrpnAnalogDevice from the list of devices that are sharing this VrpnAnalog...
Definition: vrpnAnalog.cxx:69
void poll()
Polls the connected device.
Definition: vrpnAnalog.I:45
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
void mark(VrpnButtonDevice *device)
Adds the indicated VrpnButtonDevice to the list of devices that are sharing this VrpnButton.
Definition: vrpnButton.cxx:55
void unmark(VrpnTrackerDevice *device)
Removes the indicated VrpnTrackerDevice from the list of devices that are sharing this VrpnTracker...
Definition: vrpnTracker.cxx:71
VrpnDial * get_vrpn_dial() const
Returns a pointer to the particular VrpnDial this device gets its data from.
The Panda interface to a VRPN analog device.
This is the actual interface to a particular VRPN tracker object, and all of its sensors.
Definition: vrpnTracker.h:41
The Panda interface to a VRPN button.
const string & get_dial_name() const
Returns the name of the dial device that was used to create this VrpnDial.
Definition: vrpnDial.I:22
The Panda interface to a VRPN tracker.
The Panda interface to a VRPN dial device.
bool is_connected() const
Returns true if the connection is established successfully, false otherwise.
Definition: vrpnClient.I:47
This is the actual interface to a particular VRPN button device, and all of its numbered buttons...
Definition: vrpnButton.h:42
void mark(VrpnTrackerDevice *device)
Adds the indicated VrpnTrackerDevice to the list of devices that are sharing this VrpnTracker...
Definition: vrpnTracker.cxx:57
void mark(VrpnDialDevice *device)
Adds the indicated VrpnDialDevice to the list of devices that are sharing this VrpnDial.
Definition: vrpnDial.cxx:55
void poll()
Polls the connected device.
Definition: vrpnTracker.I:45
bool is_empty() const
Returns true if no VrpnAnalogDevices reference this VrpnAnalog, or false otherwise.
Definition: vrpnAnalog.I:33
bool is_empty() const
Returns true if no VrpnDialDevices reference this VrpnDial, or false otherwise.
Definition: vrpnDial.I:33
VrpnAnalog * get_vrpn_analog() const
Returns a pointer to the particular VrpnAnalog this device gets its data from.
const string & get_tracker_name() const
Returns the name of the tracker device that was used to create this VrpnTracker.
Definition: vrpnTracker.I:22
void poll()
Polls the connected device.
Definition: vrpnDial.I:45
VrpnTracker * get_vrpn_tracker() const
Returns a pointer to the particular VrpnTracker this device gets its data from.
This is the actual interface to a particular VRPN dial device, and all of its numbered dials...
Definition: vrpnDial.h:42
const string & get_button_name() const
Returns the name of the button device that was used to create this VrpnButton.
Definition: vrpnButton.I:22
void unmark(VrpnDialDevice *device)
Removes the indicated VrpnDialDevice from the list of devices that are sharing this VrpnDial...
Definition: vrpnDial.cxx:69
bool is_empty() const
Returns true if no VrpnButtonDevices reference this VrpnButton, or false otherwise.
Definition: vrpnButton.I:33
void mark(VrpnAnalogDevice *device)
Adds the indicated VrpnAnalogDevice to the list of devices that are sharing this VrpnAnalog.
Definition: vrpnAnalog.cxx:55
bool is_valid() const
Returns true if everything seems to be kosher with the server (even if there is no connection)...
Definition: vrpnClient.I:36
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void write(ostream &out, int indent_level=0) const
Writes a list of the active devices that the VrpnClient is currently polling each frame...
Definition: vrpnClient.cxx:73
bool is_empty() const
Returns true if no VrpnTrackerDevices reference this VrpnTracker, or false otherwise.
Definition: vrpnTracker.I:33
This is the actual interface to a particular VRPN analog device, and all of its numbered controls...
Definition: vrpnAnalog.h:42
Any of a number of different devices that might be attached to a ClientBase, including trackers...
Definition: clientDevice.h:35
VrpnButton * get_vrpn_button() const
Returns a pointer to the particular VrpnButton this device gets its data from.
const string & get_analog_name() const
Returns the name of the analog device that was used to create this VrpnAnalog.
Definition: vrpnAnalog.I:22