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