Panda3D
Loading...
Searching...
No Matches
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
29using std::string;
30
31TypeHandle VrpnClient::_type_handle;
32
33/**
34 *
35 */
36VrpnClient::
37VrpnClient(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 */
58VrpnClient::
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 */
68is_valid() const {
69 return (_connection->doing_okay() != 0);
70}
71
72/**
73 * Returns true if the connection is established successfully, false
74 * otherwise.
75 */
77is_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 */
86write(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 */
148PT(ClientDevice) VrpnClient::
149make_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 */
175bool VrpnClient::
176disconnect_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 */
209void VrpnClient::
210do_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 */
266PT(ClientDevice) VrpnClient::
267make_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 */
326PT(ClientDevice) VrpnClient::
327make_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 */
351PT(ClientDevice) VrpnClient::
352make_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 */
376PT(ClientDevice) VrpnClient::
377make_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 */
400void VrpnClient::
401disconnect_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 */
412void VrpnClient::
413disconnect_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 */
424void VrpnClient::
425disconnect_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 */
436void VrpnClient::
437disconnect_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 */
449VrpnTracker *VrpnClient::
450get_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 */
473void VrpnClient::
474free_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 */
495VrpnButton *VrpnClient::
496get_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 */
519void VrpnClient::
520free_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 */
541VrpnAnalog *VrpnClient::
542get_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 */
565void VrpnClient::
566free_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 */
587VrpnDial *VrpnClient::
588get_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 */
611void VrpnClient::
612free_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
635typedef 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 */
644bool VrpnClient::
645add_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 */
673bool VrpnClient::
674add_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 */
699bool VrpnClient::
700add_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 */
725bool VrpnClient::
726add_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 */
751int VrpnClient::
752max_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 */
764void VrpnClient::
765poll_tracker(const string &tracker) {
766 _vrpn_trackers[tracker]->mainloop();
767}
768
769/**
770 * Calls mainloop for the registered analog object
771 */
772void VrpnClient::
773poll_analog(const string &analog) {
774 _vrpn_analogs[analog]->mainloop();
775}
776
777/**
778 * Calls mainloop for the registered button object
779 */
780void VrpnClient::
781poll_button(const string &button) {
782 _vrpn_buttons[button]->mainloop();
783}
784
785/**
786 * Calls mainloop for the registered dial object
787 */
788void VrpnClient::
789poll_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 */
797void VRPN_CALLBACK VrpnClient::
798st_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 */
807void VRPN_CALLBACK VrpnClient::
808st_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 */
816void VRPN_CALLBACK VrpnClient::
817st_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 */
826void VrpnClient::
827st_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 */
836void VrpnClient::
837st_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 */
846void VrpnClient::
847st_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,...
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.
void mark(VrpnAnalogDevice *device)
Adds the indicated VrpnAnalogDevice to the list of devices that are sharing this VrpnAnalog.
void poll()
Polls the connected device.
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.
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.
void mark(VrpnButtonDevice *device)
Adds the indicated VrpnButtonDevice to the list of devices that are sharing this VrpnButton.
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.
bool is_valid() const
Returns true if everything seems to be kosher with the server (even if there is no connection),...
bool is_connected() const
Returns true if the connection is established successfully, false otherwise.
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.
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.
void poll()
Polls the connected device.
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.
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.