936 lines
31 KiB
C++
936 lines
31 KiB
C++
// Filename: vrpnClient.cxx
|
|
// Created by: jason (04Aug00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "vrpnClient.h"
|
|
#include "vrpnTracker.h"
|
|
#include "vrpnTrackerDevice.h"
|
|
#include "vrpnButton.h"
|
|
#include "vrpnButtonDevice.h"
|
|
#include "vrpnAnalog.h"
|
|
#include "vrpnAnalogDevice.h"
|
|
#include "vrpnDial.h"
|
|
#include "vrpnDialDevice.h"
|
|
#include "config_vrpn.h"
|
|
|
|
#include "dcast.h"
|
|
#include "string_utils.h"
|
|
#include "indent.h"
|
|
|
|
TypeHandle VrpnClient::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnClient::
|
|
VrpnClient(const string &server_name) :
|
|
_server_name(server_name)
|
|
{
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Attempting to connect to VRPN server " << _server_name
|
|
<< "\n";
|
|
}
|
|
_connection = vrpn_get_connection_by_name(_server_name.c_str());
|
|
nassertv(_connection != (vrpn_Connection *)NULL);
|
|
|
|
if (!is_valid()) {
|
|
vrpn_cat.warning()
|
|
<< "Unable to establish connection to VRPN server " << _server_name
|
|
<< "\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnClient::
|
|
~VrpnClient() {
|
|
delete _connection;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::write
|
|
// Access: Public
|
|
// Description: Writes a list of the active devices that the
|
|
// VrpnClient is currently polling each frame.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
write(ostream &out, int indent_level) const {
|
|
indent(out, indent_level)
|
|
<< "VrpnClient, server " << _server_name << "\n";
|
|
|
|
if (!is_valid()) {
|
|
indent(out, indent_level + 2)
|
|
<< "(error)\n";
|
|
} else if (!is_connected()) {
|
|
indent(out, indent_level + 2)
|
|
<< "(no connection)\n";
|
|
}
|
|
|
|
if (!_trackers.empty()) {
|
|
indent(out, indent_level + 2)
|
|
<< _trackers.size() << " trackers:\n";
|
|
Trackers::const_iterator ti;
|
|
for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
|
|
VrpnTracker *vrpn_tracker = (*ti).second;
|
|
vrpn_tracker->write(out, indent_level + 4);
|
|
}
|
|
}
|
|
|
|
if (!_buttons.empty()) {
|
|
indent(out, indent_level + 2)
|
|
<< _buttons.size() << " buttons:\n";
|
|
Buttons::const_iterator bi;
|
|
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
|
VrpnButton *vrpn_button = (*bi).second;
|
|
vrpn_button->write(out, indent_level + 4);
|
|
}
|
|
}
|
|
|
|
if (!_analogs.empty()) {
|
|
indent(out, indent_level + 2)
|
|
<< _analogs.size() << " analogs:\n";
|
|
Analogs::const_iterator ai;
|
|
for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
|
|
VrpnAnalog *vrpn_analog = (*ai).second;
|
|
vrpn_analog->write(out, indent_level + 4);
|
|
}
|
|
}
|
|
|
|
if (!_dials.empty()) {
|
|
indent(out, indent_level + 2)
|
|
<< _dials.size() << " dials:\n";
|
|
Dials::const_iterator di;
|
|
for (di = _dials.begin(); di != _dials.end(); ++di) {
|
|
VrpnDial *vrpn_dial = (*di).second;
|
|
vrpn_dial->write(out, indent_level + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::make_device
|
|
// Access: Protected, Virtual
|
|
// Description: Creates and returns a new ClientDevice of the
|
|
// appropriate type, according to the requested
|
|
// device_type and device_name. Returns NULL if a
|
|
// matching device cannot be found.
|
|
//
|
|
// This is guaranteed not to be called twice for a given
|
|
// device_type/device_name combination (unless
|
|
// disconnect_device() has already been called for the
|
|
// same device_type/device_name).
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ClientDevice) VrpnClient::
|
|
make_device(TypeHandle device_type, const string &device_name) {
|
|
if (device_type == ClientTrackerDevice::get_class_type()) {
|
|
return make_tracker_device(device_name);
|
|
|
|
} else if (device_type == ClientButtonDevice::get_class_type()) {
|
|
return make_button_device(device_name);
|
|
|
|
} else if (device_type == ClientAnalogDevice::get_class_type()) {
|
|
return make_analog_device(device_name);
|
|
|
|
} else if (device_type == ClientDialDevice::get_class_type()) {
|
|
return make_dial_device(device_name);
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::disconnect_device
|
|
// Access: Protected, Virtual
|
|
// Description: Removes the device, which is presumably about to
|
|
// destruct, from the list of connected devices, and
|
|
// frees any data required to support it. This device
|
|
// will no longer receive automatic updates with each
|
|
// poll.
|
|
//
|
|
// The return value is true if the device was
|
|
// disconnected, or false if it was unknown (e.g. it was
|
|
// disconnected previously).
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VrpnClient::
|
|
disconnect_device(TypeHandle device_type, const string &device_name,
|
|
ClientDevice *device) {
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Disconnecting device " << *device << "\n";
|
|
}
|
|
|
|
if (ClientBase::disconnect_device(device_type, device_name, device)) {
|
|
if (device->is_of_type(VrpnTrackerDevice::get_class_type())) {
|
|
disconnect_tracker_device(DCAST(VrpnTrackerDevice, device));
|
|
|
|
} else if (device->is_of_type(VrpnButtonDevice::get_class_type())) {
|
|
disconnect_button_device(DCAST(VrpnButtonDevice, device));
|
|
|
|
} else if (device->is_of_type(VrpnAnalogDevice::get_class_type())) {
|
|
disconnect_analog_device(DCAST(VrpnAnalogDevice, device));
|
|
|
|
} else if (device->is_of_type(VrpnDialDevice::get_class_type())) {
|
|
disconnect_dial_device(DCAST(VrpnDialDevice, device));
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::do_poll
|
|
// Access: Protected, Virtual
|
|
// Description: Implements the polling and updating of connected
|
|
// devices, if the ClientBase requires this. This may
|
|
// be called in a sub-thread if
|
|
// fork_asynchronous_thread() was called; otherwise, it
|
|
// will be called once per frame.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
do_poll() {
|
|
ClientBase::do_poll();
|
|
|
|
if (vrpn_cat.is_spam()) {
|
|
vrpn_cat.spam()
|
|
<< "VrpnClient " << _server_name << " polling "
|
|
<< _trackers.size() + _buttons.size() + _analogs.size() + _dials.size()
|
|
<< " devices.\n";
|
|
}
|
|
|
|
Trackers::iterator ti;
|
|
for (ti = _trackers.begin(); ti != _trackers.end(); ++ti) {
|
|
VrpnTracker *vrpn_tracker = (*ti).second;
|
|
vrpn_tracker->poll();
|
|
}
|
|
|
|
Buttons::iterator bi;
|
|
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
|
|
VrpnButton *vrpn_button = (*bi).second;
|
|
vrpn_button->poll();
|
|
}
|
|
|
|
Analogs::iterator ai;
|
|
for (ai = _analogs.begin(); ai != _analogs.end(); ++ai) {
|
|
VrpnAnalog *vrpn_analog = (*ai).second;
|
|
vrpn_analog->poll();
|
|
}
|
|
|
|
Dials::iterator di;
|
|
for (di = _dials.begin(); di != _dials.end(); ++di) {
|
|
VrpnDial *vrpn_dial = (*di).second;
|
|
vrpn_dial->poll();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::make_tracker_device
|
|
// Access: Private
|
|
// Description: Creates a new tracker device. The device_name is
|
|
// parsed for sensor and data_type information.
|
|
//
|
|
// The device_name may be one of the following:
|
|
//
|
|
// tracker_name
|
|
// tracker_name:N
|
|
// tracker_name:N[pva]
|
|
//
|
|
// Where N is an integer sensor number, and [pva] is one
|
|
// of the lowercase letters p, v, or a.
|
|
//
|
|
// In the first form, the device connects to the
|
|
// indicated tracker, and reports position information
|
|
// on sensor number 0.
|
|
//
|
|
// In the second form, the device connects to the
|
|
// indicated tracker, and reports position information
|
|
// on the indicated sensor number.
|
|
//
|
|
// In the third form, the device connects to the
|
|
// indicated tracker, and reports either position,
|
|
// velocity, or acceleration information on the
|
|
// indicated sensor number.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ClientDevice) VrpnClient::
|
|
make_tracker_device(const string &device_name) {
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Making tracker device for " << device_name << "\n";
|
|
}
|
|
|
|
string tracker_name = device_name;
|
|
int sensor = 0;
|
|
VrpnTrackerDevice::DataType data_type = VrpnTrackerDevice::DT_position;
|
|
|
|
size_t colon = device_name.rfind(':');
|
|
if (colon != string::npos && colon + 1 < device_name.length()) {
|
|
size_t begin = colon + 1;
|
|
size_t end = device_name.length();
|
|
VrpnTrackerDevice::DataType maybe_data_type = data_type;
|
|
|
|
switch (device_name[end - 1]) {
|
|
case 'p':
|
|
maybe_data_type = VrpnTrackerDevice::DT_position;
|
|
end--;
|
|
break;
|
|
|
|
case 'v':
|
|
maybe_data_type = VrpnTrackerDevice::DT_velocity;
|
|
end--;
|
|
break;
|
|
|
|
case 'a':
|
|
maybe_data_type = VrpnTrackerDevice::DT_acceleration;
|
|
end--;
|
|
break;
|
|
}
|
|
int maybe_sensor;
|
|
if (string_to_int(device_name.substr(begin, end - begin), maybe_sensor)) {
|
|
// It seems to be a legitimate integer!
|
|
sensor = maybe_sensor;
|
|
data_type = maybe_data_type;
|
|
tracker_name = device_name.substr(0, colon);
|
|
}
|
|
}
|
|
|
|
VrpnTracker *tracker = get_tracker(tracker_name);
|
|
|
|
VrpnTrackerDevice *device =
|
|
new VrpnTrackerDevice(this, device_name, sensor, data_type, tracker);
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating " << *device << "\n";
|
|
}
|
|
|
|
tracker->mark(device);
|
|
return device;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::make_button_device
|
|
// Access: Private
|
|
// Description: Creates a new button device. The device_name is sent
|
|
// verbatim to the VRPN library.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ClientDevice) VrpnClient::
|
|
make_button_device(const string &device_name) {
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Making button device for " << device_name << "\n";
|
|
}
|
|
|
|
VrpnButton *button = get_button(device_name);
|
|
|
|
VrpnButtonDevice *device =
|
|
new VrpnButtonDevice(this, device_name, button);
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating " << *device << "\n";
|
|
}
|
|
|
|
button->mark(device);
|
|
return device;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::make_analog_device
|
|
// Access: Private
|
|
// Description: Creates a new analog device. The device_name is sent
|
|
// verbatim to the VRPN library.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ClientDevice) VrpnClient::
|
|
make_analog_device(const string &device_name) {
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Making analog device for " << device_name << "\n";
|
|
}
|
|
|
|
VrpnAnalog *analog = get_analog(device_name);
|
|
|
|
VrpnAnalogDevice *device =
|
|
new VrpnAnalogDevice(this, device_name, analog);
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating " << *device << "\n";
|
|
}
|
|
|
|
analog->mark(device);
|
|
return device;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::make_dial_device
|
|
// Access: Private
|
|
// Description: Creates a new dial device. The device_name is sent
|
|
// verbatim to the VRPN library.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(ClientDevice) VrpnClient::
|
|
make_dial_device(const string &device_name) {
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Making dial device for " << device_name << "\n";
|
|
}
|
|
|
|
VrpnDial *dial = get_dial(device_name);
|
|
|
|
VrpnDialDevice *device =
|
|
new VrpnDialDevice(this, device_name, dial);
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating " << *device << "\n";
|
|
}
|
|
|
|
dial->mark(device);
|
|
return device;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::disconnect_tracker_device
|
|
// Access: Private
|
|
// Description: Removes the tracker device from the list of things to
|
|
// be updated.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
disconnect_tracker_device(VrpnTrackerDevice *device) {
|
|
VrpnTracker *vrpn_tracker = device->get_vrpn_tracker();
|
|
vrpn_tracker->unmark(device);
|
|
if (vrpn_tracker->is_empty()) {
|
|
free_tracker(vrpn_tracker);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::disconnect_button_device
|
|
// Access: Private
|
|
// Description: Removes the button device from the list of things to
|
|
// be updated.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
disconnect_button_device(VrpnButtonDevice *device) {
|
|
VrpnButton *vrpn_button = device->get_vrpn_button();
|
|
vrpn_button->unmark(device);
|
|
if (vrpn_button->is_empty()) {
|
|
free_button(vrpn_button);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::disconnect_analog_device
|
|
// Access: Private
|
|
// Description: Removes the analog device from the list of things to
|
|
// be updated.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
disconnect_analog_device(VrpnAnalogDevice *device) {
|
|
VrpnAnalog *vrpn_analog = device->get_vrpn_analog();
|
|
vrpn_analog->unmark(device);
|
|
if (vrpn_analog->is_empty()) {
|
|
free_analog(vrpn_analog);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::disconnect_dial_device
|
|
// Access: Private
|
|
// Description: Removes the dial device from the list of things to
|
|
// be updated.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
disconnect_dial_device(VrpnDialDevice *device) {
|
|
VrpnDial *vrpn_dial = device->get_vrpn_dial();
|
|
vrpn_dial->unmark(device);
|
|
if (vrpn_dial->is_empty()) {
|
|
free_dial(vrpn_dial);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::get_tracker
|
|
// Access: Private
|
|
// Description: Finds a VrpnTracker of the indicated name, and
|
|
// returns it if one already exists, or creates a new
|
|
// one if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnTracker *VrpnClient::
|
|
get_tracker(const string &tracker_name) {
|
|
Trackers::iterator ti;
|
|
ti = _trackers.find(tracker_name);
|
|
|
|
if (ti != _trackers.end()) {
|
|
return (*ti).second;
|
|
}
|
|
|
|
VrpnTracker *vrpn_tracker = new VrpnTracker(tracker_name, _connection);
|
|
_trackers.insert(Trackers::value_type(tracker_name, vrpn_tracker));
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating tracker " << *vrpn_tracker << "\n";
|
|
}
|
|
|
|
return vrpn_tracker;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::free_tracker
|
|
// Access: Private
|
|
// Description: Removes and deletes the indicated VrpnTracker, which
|
|
// is no longer referenced by any VrpnTrackerDevices.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
free_tracker(VrpnTracker *vrpn_tracker) {
|
|
nassertv(vrpn_tracker->is_empty());
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Deleting tracker " << *vrpn_tracker << "\n";
|
|
}
|
|
|
|
Trackers::iterator ti;
|
|
ti = _trackers.find(vrpn_tracker->get_tracker_name());
|
|
nassertv(ti != _trackers.end());
|
|
nassertv((*ti).second == vrpn_tracker);
|
|
|
|
_trackers.erase(ti);
|
|
delete vrpn_tracker;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::get_button
|
|
// Access: Private
|
|
// Description: Finds a VrpnButton of the indicated name, and
|
|
// returns it if one already exists, or creates a new
|
|
// one if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnButton *VrpnClient::
|
|
get_button(const string &button_name) {
|
|
Buttons::iterator bi;
|
|
bi = _buttons.find(button_name);
|
|
|
|
if (bi != _buttons.end()) {
|
|
return (*bi).second;
|
|
}
|
|
|
|
VrpnButton *vrpn_button = new VrpnButton(button_name, _connection);
|
|
_buttons.insert(Buttons::value_type(button_name, vrpn_button));
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating button " << *vrpn_button << "\n";
|
|
}
|
|
|
|
return vrpn_button;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::free_button
|
|
// Access: Private
|
|
// Description: Removes and deletes the indicated VrpnButton, which
|
|
// is no longer referenced by any VrpnButtonDevices.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
free_button(VrpnButton *vrpn_button) {
|
|
nassertv(vrpn_button->is_empty());
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Deleting button " << *vrpn_button << "\n";
|
|
}
|
|
|
|
Buttons::iterator bi;
|
|
bi = _buttons.find(vrpn_button->get_button_name());
|
|
nassertv(bi != _buttons.end());
|
|
nassertv((*bi).second == vrpn_button);
|
|
|
|
_buttons.erase(bi);
|
|
delete vrpn_button;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::get_analog
|
|
// Access: Private
|
|
// Description: Finds a VrpnAnalog of the indicated name, and
|
|
// returns it if one already exists, or creates a new
|
|
// one if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnAnalog *VrpnClient::
|
|
get_analog(const string &analog_name) {
|
|
Analogs::iterator ai;
|
|
ai = _analogs.find(analog_name);
|
|
|
|
if (ai != _analogs.end()) {
|
|
return (*ai).second;
|
|
}
|
|
|
|
VrpnAnalog *vrpn_analog = new VrpnAnalog(analog_name, _connection);
|
|
_analogs.insert(Analogs::value_type(analog_name, vrpn_analog));
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating analog " << *vrpn_analog << "\n";
|
|
}
|
|
|
|
return vrpn_analog;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::free_analog
|
|
// Access: Private
|
|
// Description: Removes and deletes the indicated VrpnAnalog, which
|
|
// is no longer referenced by any VrpnAnalogDevices.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
free_analog(VrpnAnalog *vrpn_analog) {
|
|
nassertv(vrpn_analog->is_empty());
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Deleting analog " << *vrpn_analog << "\n";
|
|
}
|
|
|
|
Analogs::iterator ai;
|
|
ai = _analogs.find(vrpn_analog->get_analog_name());
|
|
nassertv(ai != _analogs.end());
|
|
nassertv((*ai).second == vrpn_analog);
|
|
|
|
_analogs.erase(ai);
|
|
delete vrpn_analog;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::get_dial
|
|
// Access: Private
|
|
// Description: Finds a VrpnDial of the indicated name, and
|
|
// returns it if one already exists, or creates a new
|
|
// one if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
VrpnDial *VrpnClient::
|
|
get_dial(const string &dial_name) {
|
|
Dials::iterator di;
|
|
di = _dials.find(dial_name);
|
|
|
|
if (di != _dials.end()) {
|
|
return (*di).second;
|
|
}
|
|
|
|
VrpnDial *vrpn_dial = new VrpnDial(dial_name, _connection);
|
|
_dials.insert(Dials::value_type(dial_name, vrpn_dial));
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Creating dial " << *vrpn_dial << "\n";
|
|
}
|
|
|
|
return vrpn_dial;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::free_dial
|
|
// Access: Private
|
|
// Description: Removes and deletes the indicated VrpnDial, which
|
|
// is no longer referenced by any VrpnDialDevices.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
free_dial(VrpnDial *vrpn_dial) {
|
|
nassertv(vrpn_dial->is_empty());
|
|
|
|
if (vrpn_cat.is_debug()) {
|
|
vrpn_cat.debug()
|
|
<< "Deleting dial " << *vrpn_dial << "\n";
|
|
}
|
|
|
|
Dials::iterator di;
|
|
di = _dials.find(vrpn_dial->get_dial_name());
|
|
nassertv(di != _dials.end());
|
|
nassertv((*di).second == vrpn_dial);
|
|
|
|
_dials.erase(di);
|
|
delete vrpn_dial;
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
#include <datagram.h>
|
|
#include <datagramIterator.h>
|
|
|
|
typedef struct {
|
|
string device_name;
|
|
void *self;
|
|
} VrpnClientInfo;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::add_remote_tracker
|
|
// Access: Public, Virtual
|
|
// Description: Creates a new vrpn remote tracker object and registers
|
|
// a callback with it.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VrpnClient::
|
|
add_remote_tracker(const string &tracker, int sensor) {
|
|
|
|
vrpn_Tracker_Remote *vrpn_tracker = new vrpn_Tracker_Remote(tracker.c_str(), _connection);
|
|
if (vrpn_tracker == (vrpn_Tracker_Remote *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
//Now package up the information that needs to be passed to the
|
|
//callback function to allow it to determine for which tracker we
|
|
//are receiving information for
|
|
VrpnClientInfo *data = new VrpnClientInfo;
|
|
data->device_name = tracker;
|
|
data->self = this;
|
|
|
|
vrpn_tracker->register_change_handler((void*)data, st_tracker_position);
|
|
vrpn_tracker->register_change_handler((void*)data, st_tracker_velocity);
|
|
vrpn_tracker->register_change_handler((void*)data, st_tracker_acceleration);
|
|
|
|
_vrpn_trackers[tracker] = vrpn_tracker;
|
|
_trackers.push_back(tracker);
|
|
_sensors[tracker].push_back(sensor);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::add_remote_analog
|
|
// Access: Public, Virtual
|
|
// Description: Creates a new vrpn remote analog object and registers
|
|
// a callback with it.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VrpnClient::
|
|
add_remote_analog(const string &analog) {
|
|
|
|
vrpn_Analog_Remote *vrpn_analog = new vrpn_Analog_Remote(analog.c_str(), _connection);
|
|
if (vrpn_analog == (vrpn_Analog_Remote *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
//Now package up the information that needs to be passed to the
|
|
//callback function to allow it to determine for which analog we
|
|
//are receiving information for
|
|
VrpnClientInfo *data = new VrpnClientInfo;
|
|
data->device_name = analog;
|
|
data->self = this;
|
|
|
|
vrpn_analog->register_change_handler((void*)data, st_analog);
|
|
|
|
_vrpn_analogs[analog] = vrpn_analog;
|
|
_analogs.push_back(analog);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::add_remote_button
|
|
// Access: Public, Virtual
|
|
// Description: Creates a new vrpn remote button object and registers
|
|
// a callback with it.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VrpnClient::
|
|
add_remote_button(const string &button) {
|
|
|
|
vrpn_Button_Remote *vrpn_button = new vrpn_Button_Remote(button.c_str(), _connection);
|
|
if (vrpn_button == (vrpn_Button_Remote *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
//Now package up the information that needs to be passed to the
|
|
//callback function to allow it to determine for which button we
|
|
//are receiving information for
|
|
VrpnClientInfo *data = new VrpnClientInfo;
|
|
data->device_name = button;
|
|
data->self = this;
|
|
|
|
vrpn_button->register_change_handler((void*)data, st_button);
|
|
|
|
_vrpn_buttons[button] = vrpn_button;
|
|
_buttons.push_back(button);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::add_remote_dial
|
|
// Access: Public, Virtual
|
|
// Description: Creates a new vrpn remote dial object and registers
|
|
// a callback with it.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VrpnClient::
|
|
add_remote_dial(const string &dial) {
|
|
|
|
vrpn_Dial_Remote *vrpn_dial = new vrpn_Dial_Remote(dial.c_str(), _connection);
|
|
if (vrpn_dial == (vrpn_Dial_Remote *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
//Now package up the information that needs to be passed to the
|
|
//callback function to allow it to determine for which dial we
|
|
//are receiving information for
|
|
VrpnClientInfo *data = new VrpnClientInfo;
|
|
data->device_name = dial;
|
|
data->self = this;
|
|
|
|
vrpn_dial->register_change_handler((void*)data, st_dial);
|
|
|
|
_vrpn_dials[dial] = vrpn_dial;
|
|
_dials.push_back(dial);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::max_analog_channels
|
|
// Access: Public, Virtual
|
|
// Description: Max number of analog channels
|
|
////////////////////////////////////////////////////////////////////
|
|
int VrpnClient::
|
|
max_analog_channels() {
|
|
return vrpn_CHANNEL_MAX;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::poll_trackers
|
|
// Access: Public, Virtual
|
|
// Description: Calls mainloop for the registered tracker object
|
|
// Note: In a non-threaded case, this may need to come up with
|
|
// some kind of cacheing scheme so we don't call mainloop
|
|
// multiple times when a user is just asking for the data
|
|
// of multiple sensors on 1 tracker (as that is the interface
|
|
// supported). This is a non-trivial problem as it is
|
|
// difficult to know when we should and shouldn't cache.
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
poll_tracker(const string &tracker) {
|
|
_vrpn_trackers[tracker]->mainloop();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::poll_analog
|
|
// Access: Public, Virtual
|
|
// Description: Calls mainloop for the registered analog object
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
poll_analog(const string &analog) {
|
|
_vrpn_analogs[analog]->mainloop();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::poll_button
|
|
// Access: Public, Virtual
|
|
// Description: Calls mainloop for the registered button object
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
poll_button(const string &button) {
|
|
_vrpn_buttons[button]->mainloop();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::poll_dial
|
|
// Access: Public, Virtual
|
|
// Description: Calls mainloop for the registered dial object
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
poll_dial(const string &dial) {
|
|
_vrpn_dials[dial]->mainloop();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_tracker_position
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_tracker_position(void *userdata, const vrpn_TRACKERCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->tracker_position(data->device_name, info);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_tracker_velocity
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_tracker_velocity(void *userdata, const vrpn_TRACKERVELCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->tracker_velocity(data->device_name, info);
|
|
}
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_tracker_acceleration
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_tracker_acceleration(void *userdata, const vrpn_TRACKERACCCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->tracker_acceleration(data->device_name, info);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_analog
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_analog(void *userdata, const vrpn_ANALOGCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->analog(data->device_name, info);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_button
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_button(void *userdata, const vrpn_BUTTONCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->button(data->device_name, info);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VrpnClient::st_dial
|
|
// Access: Private, Static
|
|
// Description: Callback function that merely passes the data down
|
|
// to the appropriate non-static function
|
|
////////////////////////////////////////////////////////////////////
|
|
void VrpnClient::
|
|
st_dial(void *userdata, const vrpn_DIALCB info) {
|
|
VrpnClientInfo *data = (VrpnClientInfo *)userdata;
|
|
((VrpnClient *)data->self)->dial(data->device_name, info);
|
|
}
|
|
|
|
#endif
|