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