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
vrpnAnalog.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
VrpnDialDevice
The Panda interface to a VRPN dial device.
Definition: vrpnDialDevice.h:30
vrpnTracker.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnAnalog::poll
void poll()
Polls the connected device.
Definition: vrpnAnalog.I:37
VrpnAnalog::unmark
void unmark(VrpnAnalogDevice *device)
Removes the indicated VrpnAnalogDevice from the list of devices that are sharing this VrpnAnalog.
Definition: vrpnAnalog.cxx:60
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnDial::get_dial_name
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
VrpnAnalogDevice::get_vrpn_analog
VrpnAnalog * get_vrpn_analog() const
Returns a pointer to the particular VrpnAnalog this device gets its data from.
Definition: vrpnAnalogDevice.I:19
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnButton::is_empty
bool is_empty() const
Returns true if no VrpnButtonDevices reference this VrpnButton, or false otherwise.
Definition: vrpnButton.I:28
ClientDevice
Any of a number of different devices that might be attached to a ClientBase, including trackers,...
Definition: clientDevice.h:27
config_vrpn.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnTracker::get_tracker_name
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
VrpnTracker::unmark
void unmark(VrpnTrackerDevice *device)
Removes the indicated VrpnTrackerDevice from the list of devices that are sharing this VrpnTracker.
Definition: vrpnTracker.cxx:62
VrpnButton
This is the actual interface to a particular VRPN button device, and all of its numbered buttons.
Definition: vrpnButton.h:37
VrpnClient
A specific ClientBase that connects to a VRPN server and records information on the connected VRPN de...
Definition: vrpnClient.h:35
vrpnButtonDevice.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnDial
This is the actual interface to a particular VRPN dial device, and all of its numbered dials.
Definition: vrpnDial.h:37
VrpnAnalog::get_analog_name
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
PT
PT(ClientDevice) VrpnClient
Creates and returns a new ClientDevice of the appropriate type, according to the requested device_typ...
Definition: vrpnClient.cxx:130
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
vrpnClient.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnButton::mark
void mark(VrpnButtonDevice *device)
Adds the indicated VrpnButtonDevice to the list of devices that are sharing this VrpnButton.
Definition: vrpnButton.cxx:48
VrpnTracker::poll
void poll()
Polls the connected device.
Definition: vrpnTracker.I:37
VrpnDial::is_empty
bool is_empty() const
Returns true if no VrpnDialDevices reference this VrpnDial, or false otherwise.
Definition: vrpnDial.I:27
VrpnTracker::mark
void mark(VrpnTrackerDevice *device)
Adds the indicated VrpnTrackerDevice to the list of devices that are sharing this VrpnTracker.
Definition: vrpnTracker.cxx:50
string_to_int
int string_to_int(const string &str, string &tail)
A string-interface wrapper around the C library strtol().
Definition: string_utils.cxx:324
vrpnButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
vrpnAnalogDevice.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
vrpnTrackerDevice.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnAnalog::is_empty
bool is_empty() const
Returns true if no VrpnAnalogDevices reference this VrpnAnalog, or false otherwise.
Definition: vrpnAnalog.I:28
VrpnDial::unmark
void unmark(VrpnDialDevice *device)
Removes the indicated VrpnDialDevice from the list of devices that are sharing this VrpnDial.
Definition: vrpnDial.cxx:60
VrpnTrackerDevice
The Panda interface to a VRPN tracker.
Definition: vrpnTrackerDevice.h:34
VrpnAnalog
This is the actual interface to a particular VRPN analog device, and all of its numbered controls.
Definition: vrpnAnalog.h:38
VrpnDial::mark
void mark(VrpnDialDevice *device)
Adds the indicated VrpnDialDevice to the list of devices that are sharing this VrpnDial.
Definition: vrpnDial.cxx:48
VrpnButton::poll
void poll()
Polls the connected device.
Definition: vrpnButton.I:37
VrpnAnalog::mark
void mark(VrpnAnalogDevice *device)
Adds the indicated VrpnAnalogDevice to the list of devices that are sharing this VrpnAnalog.
Definition: vrpnAnalog.cxx:48
VrpnDial::poll
void poll()
Polls the connected device.
Definition: vrpnDial.I:36
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnAnalogDevice
The Panda interface to a VRPN analog device.
Definition: vrpnAnalogDevice.h:30
VrpnTracker::is_empty
bool is_empty() const
Returns true if no VrpnTrackerDevices reference this VrpnTracker, or false otherwise.
Definition: vrpnTracker.I:28
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
vrpnDialDevice.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnButton::unmark
void unmark(VrpnButtonDevice *device)
Removes the indicated VrpnButtonDevice from the list of devices that are sharing this VrpnButton.
Definition: vrpnButton.cxx:60
VrpnTracker
This is the actual interface to a particular VRPN tracker object, and all of its sensors.
Definition: vrpnTracker.h:37
VrpnButtonDevice::get_vrpn_button
VrpnButton * get_vrpn_button() const
Returns a pointer to the particular VrpnButton this device gets its data from.
Definition: vrpnButtonDevice.I:19
VrpnTrackerDevice::get_vrpn_tracker
VrpnTracker * get_vrpn_tracker() const
Returns a pointer to the particular VrpnTracker this device gets its data from.
Definition: vrpnTrackerDevice.I:38
VrpnButton::get_button_name
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
VrpnButtonDevice
The Panda interface to a VRPN button.
Definition: vrpnButtonDevice.h:30
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
VrpnClient::is_connected
bool is_connected() const
Returns true if the connection is established successfully, false otherwise.
Definition: vrpnClient.I:36
VrpnDialDevice::get_vrpn_dial
VrpnDial * get_vrpn_dial() const
Returns a pointer to the particular VrpnDial this device gets its data from.
Definition: vrpnDialDevice.I:19
vrpnDial.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VrpnClient::write
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
VrpnClient::is_valid
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