Files
OpenSceneGraph/src/osgPlugins/osc/OscReceivingDevice.cpp

1155 lines
37 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include "OscReceivingDevice.hpp"
#include <OpenThreads/Thread>
#include <osg/UserDataContainer>
#include <osg/ValueObject>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgPresentation/PropertyManager>
#include "osc/OscPrintReceivedElements.h"
#include "osc/OscHostEndianness.h"
namespace OscDevice {
template <class T, int SIZE>
struct NativeTypeTraits {
typedef T type;
static T create(const std::vector<T>& t) { return type(t); }
};
template<>
struct NativeTypeTraits<float,2> {
typedef osg::Vec2f type;
static type create(const std::vector<float>& t) { return type(t[0], t[1]); }
};
template<>
struct NativeTypeTraits<float,3> {
typedef osg::Vec3f type;
static type create(const std::vector<float>& t) { return type(t[0], t[1], t[2]); }
};
template<>
struct NativeTypeTraits<float,4> {
typedef osg::Vec4f type;
static type create(const std::vector<float>& t) { return type(t[0], t[1], t[2], t[3]); }
};
template<>
struct NativeTypeTraits<float,16> {
typedef osg::Matrixf type;
static type create(const std::vector<float>& t) { return type(&t.front()); }
};
template<>
struct NativeTypeTraits<double,2> {
typedef osg::Vec2d type;
static type create(const std::vector<double>& t) { return type(t[0], t[1]); }
};
template<>
struct NativeTypeTraits<double,3> {
typedef osg::Vec3d type;
static type create(const std::vector<double>& t) { return type(t[0], t[1], t[2]); }
};
template<>
struct NativeTypeTraits<double,4> {
typedef osg::Vec4d type;
static type create(const std::vector<double>& t) { return type(t[0], t[1], t[2], t[3]); }
};
template<>
struct NativeTypeTraits<double,16> {
typedef osg::Matrixd type;
static type create(const std::vector<double>& t) { return type(&t.front()); }
};
class StandardRequestHandler : public OscReceivingDevice::RequestHandler {
public:
StandardRequestHandler(const std::string& request_handler, bool treat_first_argument_as_value_name)
: OscReceivingDevice::RequestHandler(request_handler)
, _treatFirstArgumentAsValueName(treat_first_argument_as_value_name)
{
}
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m, const IpEndpointName& remoteEndPoint);
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << ": add all transmitted arguments as ValueObjects to an event";
if (_treatFirstArgumentAsValueName)
out << ", the first argument is used as the name of the value, if it's a string";
}
private:
void addArgumentToUdc(osg::UserDataContainer* udc, const std::string& key, const osc::ReceivedMessageArgumentIterator& itr);
template <class T>
bool addNativeTypeFromVector(osg::UserDataContainer* udc, const std::string& key, const std::vector<T>& arr)
{
switch (arr.size()) {
case 2:
udc->setUserValue(key, NativeTypeTraits<T,2>::create(arr));
return true;
break;
case 3:
udc->setUserValue(key, NativeTypeTraits<T,3>::create(arr));
return true;
break;
case 4:
udc->setUserValue(key, NativeTypeTraits<T,4>::create(arr));
return true;
break;
case 16:
udc->setUserValue(key, NativeTypeTraits<T,16>::create(arr));
return true;
break;
default:
return false;
}
return false;
}
bool _treatFirstArgumentAsValueName;
};
bool StandardRequestHandler::operator()(const std::string& /*request_path*/, const std::string& full_request_path, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try
{
std::string path = osgDB::getFilePath(full_request_path);
std::string last_elem = osgDB::getSimpleFileName(full_request_path);
osg::ref_ptr<osgGA::Event> ea = getDevice()->getOrCreateUserDataEvent();
osg::UserDataContainer* udc = ea->getOrCreateUserDataContainer();
ea->setName(_treatFirstArgumentAsValueName ? full_request_path : path);
udc->setName(ea->getName());
if (m.ArgumentCount() == 0) {
return true;
}
// if we have only one argument, get it and save it to the udc
else if (m.ArgumentCount() == 1)
{
addArgumentToUdc(udc, last_elem, m.ArgumentsBegin());
return true;
}
else
{
unsigned int i(0);
osc::ReceivedMessageArgumentIterator start = m.ArgumentsBegin();
if ((_treatFirstArgumentAsValueName) && (start->TypeTag() == osc::STRING_TYPE_TAG))
{
last_elem = start->AsString();
++start;
// if we hav only 2 arguments, then save the value and return
if (m.ArgumentCount() == 2)
{
addArgumentToUdc(udc, last_elem, start);
return true;
}
}
std::vector<float> float_vec;
std::vector<double> double_vec;
bool mixed_arguments(false);
for(osc::ReceivedMessageArgumentIterator itr = start; itr != m.ArgumentsEnd(); ++itr, ++i)
{
if(itr->TypeTag() == osc::FLOAT_TYPE_TAG)
{
float_vec.push_back(itr->AsFloat());
}
else if(itr->TypeTag() == osc::DOUBLE_TYPE_TAG)
{
double_vec.push_back(itr->AsDouble());
}
else if(itr->TypeTag() == osc::INT32_TYPE_TAG)
{
float_vec.push_back(itr->AsInt32());
}
else {
mixed_arguments = true;
break;
}
}
if (!mixed_arguments)
{
unsigned int sum = float_vec.size() + double_vec.size();
if (sum == float_vec.size())
{
if (addNativeTypeFromVector(udc, last_elem, float_vec))
return true;
}
else if (sum == double_vec.size())
{
if (addNativeTypeFromVector(udc, last_elem, double_vec))
return true;
}
}
for(osc::ReceivedMessageArgumentIterator itr = start; itr != m.ArgumentsEnd(); ++itr, ++i)
{
std::ostringstream ss;
ss << last_elem << "_" << i;
addArgumentToUdc(udc, ss.str(), itr);
}
}
return true;
}
catch(osc::Exception& e)
{
handleException(e);
return false;
}
return false;
}
void StandardRequestHandler::addArgumentToUdc(osg::UserDataContainer* udc, const std::string& key, const osc::ReceivedMessageArgumentIterator& itr)
{
switch((*itr).TypeTag())
{
case osc::TRUE_TYPE_TAG:
udc->setUserValue(key, true);
break;
case osc::FALSE_TYPE_TAG:
udc->setUserValue(key, false);
break;
case osc::INT32_TYPE_TAG:
udc->setUserValue(key, (int)((*itr).AsInt32Unchecked()));
break;
case osc::FLOAT_TYPE_TAG:
udc->setUserValue(key, (*itr).AsFloatUnchecked());
break;
case osc::CHAR_TYPE_TAG:
udc->setUserValue(key, (*itr).AsCharUnchecked());
break;
case osc::RGBA_COLOR_TYPE_TAG:
// TODO: should we convert the color to an osg::Vec4?
udc->setUserValue(key, static_cast<unsigned int>((*itr).AsRgbaColorUnchecked()));
break;
case osc::INT64_TYPE_TAG:
// TODO 64bit ints not supported by ValueObject
udc->setUserValue(key, static_cast<double>((*itr).AsInt64Unchecked()));
break;
case osc::TIME_TAG_TYPE_TAG:
// TODO 64bit ints not supported by ValueObject
udc->setUserValue(key, static_cast<double>((*itr).AsTimeTagUnchecked()));
break;
case osc::DOUBLE_TYPE_TAG:
udc->setUserValue(key, (*itr).AsDoubleUnchecked());
break;
case osc::STRING_TYPE_TAG:
udc->setUserValue(key, std::string((*itr).AsStringUnchecked()));
break;
case osc::SYMBOL_TYPE_TAG:
udc->setUserValue(key, std::string((*itr).AsSymbol()));
break;
default:
break;
}
}
class SetMouseInputRangeRequestHandler : public OscReceivingDevice::RequestHandler {
public:
SetMouseInputRangeRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/mouse/set_input_range")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
float x_min(-1.0f), y_min(-1.0f), x_max(1.0f), y_max(1.0f);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> x_min >> y_min >> x_max >> y_max >> osc::EndMessage;
getDevice()->getEventQueue()->setMouseInputRange(x_min, y_min, x_max, y_max);
return true;
}
catch(osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float x_min, float y_min, float x_max, float y_max): sets the mouse-input-range" << std::dec;
}
};
class SetMouseOrientationRequestHandler : public OscReceivingDevice::RequestHandler {
public:
SetMouseOrientationRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/mouse/y_orientation_increasing_upwards")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
bool increasing_upwards(false);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >>increasing_upwards >> osc::EndMessage;
getDevice()->getEventQueue()->getCurrentEventState()->setMouseYOrientation(
increasing_upwards ? osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS : osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
return true;
}
catch(osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float x_min, float y_min, float x_max, float y_max): sets the mouse-input-range" << std::dec;
}
};
class KeyCodeRequestHandler : public OscReceivingDevice::RequestHandler {
public:
KeyCodeRequestHandler(bool handle_key_press)
: OscReceivingDevice::RequestHandler(std::string("/osgga/key/") + ((handle_key_press) ? "press" : "release"))
, _handleKeyPress(handle_key_press)
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
osc::int32 keycode(0);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> keycode >> osc::EndMessage;
if (_handleKeyPress)
getDevice()->getEventQueue()->keyPress(keycode, getLocalTime());
else
getDevice()->getEventQueue()->keyRelease(keycode, getLocalTime());
return true;
}
catch(osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(int keycode): send KEY_" << (_handleKeyPress ? "DOWN" : "UP");
}
private:
bool _handleKeyPress;
};
class KeyPressAndReleaseRequestHandler : public OscReceivingDevice::RequestHandler {
public:
KeyPressAndReleaseRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/key/press_and_release")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
osc::int32 keycode(0);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> keycode >> osc::EndMessage;
getDevice()->getEventQueue()->keyPress(keycode, getLocalTime());
getDevice()->getEventQueue()->keyRelease(keycode, getLocalTime());
return true;
}
catch(osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(int keycode): send KEY_DOWN and KEY_UP";
}
};
class MouseMotionRequestHandler : public OscReceivingDevice::RequestHandler {
public:
MouseMotionRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/mouse/motion")
, _lastX(0.0f)
, _lastY(0.0f)
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> _lastX >> _lastY >> osc::EndMessage;
getDevice()->getEventQueue()->mouseMotion(_lastX, _lastY, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float x, float y): send mouse motion";
}
float getLastX() const { return _lastX; }
float getLastY() const { return _lastY; }
private:
float _lastX, _lastY;
};
class MouseScrollRequestHandler : public OscReceivingDevice::RequestHandler {
public:
MouseScrollRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/mouse/scroll")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
osc::int32 sm(osgGA::GUIEventAdapter::SCROLL_NONE);
float delta_x(0.0f), delta_y(0.0f);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> sm >> delta_x >> delta_y >> osc::EndMessage;
if (sm != osgGA::GUIEventAdapter::SCROLL_NONE)
getDevice()->getEventQueue()->mouseScroll((osgGA::GUIEventAdapter::ScrollingMotion)sm, getLocalTime());
if ((delta_x != 0.0f) || (delta_y != 0.0f))
getDevice()->getEventQueue()->mouseScroll2D(delta_x, delta_y, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(int scroll_motion, float x, float y): send mouse scroll-motion";
}
};
class MouseButtonToggleRequestHandler : public OscReceivingDevice::RequestHandler {
public:
MouseButtonToggleRequestHandler(const std::string& btn_name, MouseMotionRequestHandler* mm_handler)
: OscReceivingDevice::RequestHandler("/osgga/mouse/toggle/"+btn_name)
, _mmHandler(mm_handler)
, _btnNum(atoi(btn_name.c_str()))
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
float down(0.0f);
try {
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> down >> osc::EndMessage;
if (down > 0)
getDevice()->getEventQueue()->mouseButtonPress(_mmHandler->getLastX(), _mmHandler->getLastY(), _btnNum, getLocalTime());
else
getDevice()->getEventQueue()->mouseButtonRelease(_mmHandler->getLastX(), _mmHandler->getLastY(), _btnNum, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float down): toggle mouse button";
}
private:
osg::observer_ptr<MouseMotionRequestHandler> _mmHandler;
int _btnNum;
};
class MouseButtonRequestHandler : public OscReceivingDevice::RequestHandler {
public:
enum Mode { PRESS, RELEASE, DOUBLE_PRESS};
MouseButtonRequestHandler(Mode mode)
: OscReceivingDevice::RequestHandler("")
, _mode(mode)
{
switch(mode) {
case PRESS:
setRequestPath("/osgga/mouse/press");
break;
case RELEASE:
setRequestPath("/osgga/mouse/release");
break;
case DOUBLE_PRESS:
setRequestPath("/osgga/mouse/doublepress");
break;
}
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
float x(0.0f), y(0.0f);
osc::int32 btn(0);
try {
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> x >> y >> btn >> osc::EndMessage;
switch (_mode) {
case PRESS:
getDevice()->getEventQueue()->mouseButtonPress(x,y, btn, getLocalTime());
break;
case RELEASE:
getDevice()->getEventQueue()->mouseButtonRelease(x,y, btn, getLocalTime());
break;
case DOUBLE_PRESS:
getDevice()->getEventQueue()->mouseDoubleButtonPress(x,y, btn, getLocalTime());
break;
}
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float x, float y, int btn): send mouse ";
switch (_mode) {
case PRESS:
out << "press"; break;
case RELEASE:
out << "release"; break;
case DOUBLE_PRESS:
out << "double press"; break;
}
}
private:
Mode _mode;
};
class PenPressureRequestHandler : public OscReceivingDevice::RequestHandler {
public:
PenPressureRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/pen/pressure")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
float pressure(0.0f);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> pressure >> osc::EndMessage;
getDevice()->getEventQueue()->penPressure(pressure, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float pressure): send pen pressure";
}
};
class PenProximityRequestHandler : public OscReceivingDevice::RequestHandler {
public:
PenProximityRequestHandler(bool handle_enter)
: OscReceivingDevice::RequestHandler(std::string("/osgga/pen/proximity/") + ((handle_enter) ? std::string("enter") : std::string("leave")))
, _handleEnter(handle_enter)
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
osc::int32 pt(osgGA::GUIEventAdapter::UNKNOWN);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> pt >> osc::EndMessage;
getDevice()->getEventQueue()->penProximity((osgGA::GUIEventAdapter::TabletPointerType)pt, _handleEnter, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(int table_pointer_type): send pen proximity " << (_handleEnter ? "enter":"leave");
}
private:
bool _handleEnter;
};
class PenOrientationRequestHandler : public OscReceivingDevice::RequestHandler {
public:
PenOrientationRequestHandler()
: OscReceivingDevice::RequestHandler("/osgga/pen/orientation")
{
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& /*remoteEndPoint*/)
{
try {
float rotation(0.0f), tilt_x(0.0f), tilt_y(0.0f);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> rotation >> tilt_x >> tilt_y >> osc::EndMessage;
getDevice()->getEventQueue()->penOrientation(tilt_x, tilt_y, rotation, getLocalTime());
return true;
}
catch (osc::Exception e) {
handleException(e);
}
return false;
}
virtual void describeTo(std::ostream& out) const
{
out << getRequestPath() << "(float rotation, float tilt_x, float tilt_y): send pen orientation";
}
};
class TUIO2DCursorRequestHandler : public OscReceivingDevice::RequestHandler {
public:
struct Cursor {
std::string end_point;
unsigned int id, frameId;
osg::Vec2f pos, vel;
float accel;
osgGA::GUIEventAdapter::TouchPhase phase;
Cursor() : end_point(), id(0), frameId(0), pos(), vel(), accel(), phase(osgGA::GUIEventAdapter::TOUCH_UNKNOWN) {}
};
struct EndpointData {
std::string source;
osc::int32 frameId;
bool mayClearUnhandledPointer;
std::set<unsigned int> unhandled;
};
typedef std::map<std::string, EndpointData> EndpointDataMap;
typedef std::map<unsigned int, Cursor> CursorMap;
typedef std::map<std::string, CursorMap> ApplicationCursorMap;
typedef std::map<std::string, unsigned int> SourceIdMap;
TUIO2DCursorRequestHandler()
: OscReceivingDevice::RequestHandler("/tuio/2Dcur")
{
}
virtual void setDevice(OscReceivingDevice* device) {
OscReceivingDevice::RequestHandler::setDevice(device);
device->addHandleOnCheckEvents(this);
}
virtual bool operator()(const std::string& /*request_path*/, const std::string& /*full_request_path*/, const osc::ReceivedMessage& m, const IpEndpointName& remoteEndPoint)
{
// std::cout << m << std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
std::string end_point(' ', IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH);
remoteEndPoint.AddressAndPortAsString(&end_point[0]);
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
const char* str;
args >> str;
std::string what(str);
if (what == "source")
{
args >> str;
_endpointData[end_point].source = std::string(str);
updateSourceIdMap(_endpointData[end_point].source);
_endpointData[end_point].unhandled.clear();
_endpointData[end_point].mayClearUnhandledPointer = true;
return true;
}
else if (what == "fseq")
{
args >> _endpointData[end_point].frameId;
return true;
}
else
{
std::string source = _endpointData[end_point].source;
unsigned int frame_id = _endpointData[end_point].frameId;
if (what == "alive")
{
while (!args.Eos())
{
osc::int32 id;
args >> id;
_endpointData[end_point].unhandled.insert(id);
}
return true;
}
else if (what == "set")
{
osc::int32 id;
args >> id;
if (_alive[source].find(id) == _alive[source].end())
{
_alive[source][id] = Cursor();
}
Cursor& c(_alive[source][id]);
args >> c.pos.x() >> c.pos.y() >> c.vel.x() >> c.vel.y() >> c.accel >> osc::EndMessage;
c.frameId = frame_id;
c.end_point = end_point;
_endpointData[end_point].unhandled.insert(id);
return true;
}
}
return false;
}
virtual void operator()(osgGA::EventQueue* queue)
{
// dispatch all touchpoints in one GUIEventAdapter
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
osg::ref_ptr<osgGA::GUIEventAdapter> event = NULL;
for(ApplicationCursorMap::iterator i = _alive.begin(); i != _alive.end(); ++i)
{
const std::string& source(i->first);
CursorMap& cursormap = i->second;
/*
std::cout << source << ": ";
for(std::set<unsigned int>::iterator k = _endpointData[source].unhandled.begin();
k != _endpointData[source].unhandled.end();
++k)
{
std::cout << *k << " ";
}
std::cout << std::endl;
*/
// remove all touchpoints which are not transmitted via alive-message, dispatching TOUCH_ENDED
unsigned int source_id = getSourceId(source);
std::vector<unsigned int> to_delete;
for(CursorMap::iterator k = cursormap.begin(); k != cursormap.end(); ++k)
{
EndpointData& endpoint_data(_endpointData[k->second.end_point]);
/*if (!endpoint_data.mayClearUnhandledPointer)
{
continue;
}*/
//create a unique touchpoint-id
unsigned int touch_id = (source_id << 16) + k->first;
std::set<unsigned int>& unhandled(endpoint_data.unhandled);
if ((unhandled.find(k->first) == unhandled.end()))
{
// std::cout << "deleting: " << k->first << " from " << k->second.end_point << std::endl;
to_delete.push_back(k->first);
float win_x = k->second.pos.x();
float win_y = k->second.pos.y();
if (!event)
event = queue->touchEnded(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1);
else
event->addTouchPoint(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1);
}
}
// remove "dead" cursors
for(std::vector<unsigned int>::iterator k = to_delete.begin(); k != to_delete.end(); ++k)
{
cursormap.erase(cursormap.find(*k));
}
if (i->second.size() == 0)
{
// std::cout << "removing endpoint" << source << std::endl;
// _alive.erase(_alive.find(source));
}
}
// send all alive touchpoints
for(ApplicationCursorMap::iterator i = _alive.begin(); i != _alive.end(); ++i)
{
const std::string& source(i->first);
unsigned int source_id = getSourceId(source);
for(CursorMap::iterator k = i->second.begin(); k != i->second.end(); ++k)
{
unsigned int id = k->first;
unsigned int touch_id = (source_id << 16) + id;
Cursor& c(k->second);
float win_x = c.pos.x();
float win_y = c.pos.y();
bool down = c.phase != osgGA::GUIEventAdapter::TOUCH_MOVED && c.phase != osgGA::GUIEventAdapter::TOUCH_STATIONERY;
if(!event)
{
if(down)
event = queue->touchBegan(touch_id, osgGA::GUIEventAdapter::TOUCH_BEGAN, win_x, win_y);
else
event = queue->touchMoved(touch_id, osgGA::GUIEventAdapter::TOUCH_MOVED, win_x, win_y);
}
else
{
event->addTouchPoint(touch_id, down ? osgGA::GUIEventAdapter::TOUCH_BEGAN : osgGA::GUIEventAdapter::TOUCH_MOVED, win_x, win_y);
}
c.phase = osgGA::GUIEventAdapter::TOUCH_MOVED;
}
}
// adjust time + input range
if (event)
{
event->setInputRange(0, 0, 1.0, 1.0);
event->setTime(queue->getTime());
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
}
}
inline void updateSourceIdMap(const std::string& source)
{
if (_sourceIdMap.find(source) == _sourceIdMap.end())
_sourceIdMap[source] = _sourceIdMap.size();
}
inline unsigned int getSourceId(const std::string& source)
{
return _sourceIdMap[source];
}
private:
EndpointDataMap _endpointData;
ApplicationCursorMap _alive;
OpenThreads::Mutex _mutex;
SourceIdMap _sourceIdMap;
};
} // end of namespace
OscReceivingDevice::OscReceivingDevice(const std::string& server_address, int listening_port)
: osgGA::Device()
, OpenThreads::Thread()
, osc::OscPacketListener()
, _listeningAddress(server_address)
, _listeningPort(listening_port)
, _socket(NULL)
, _map()
, _lastMsgId(0)
{
setCapabilities(RECEIVE_EVENTS);
OSG_NOTICE << "OscDevice :: listening on " << server_address << ":" << listening_port << " ";
#ifdef OSC_HOST_LITTLE_ENDIAN
OSG_NOTICE << "(little endian)";
#elif OSC_HOST_BIG_ENDIAN
OSG_NOTICE << "(big endian)";
#endif
OSG_NOTICE << std::endl;
_socket = new UdpListeningReceiveSocket(IpEndpointName( server_address.c_str(), listening_port ), this);
addRequestHandler(new OscDevice::KeyCodeRequestHandler(false));
addRequestHandler(new OscDevice::KeyCodeRequestHandler(true));
addRequestHandler(new OscDevice::KeyPressAndReleaseRequestHandler());
addRequestHandler(new OscDevice::SetMouseInputRangeRequestHandler());
addRequestHandler(new OscDevice::SetMouseOrientationRequestHandler());
OscDevice::MouseMotionRequestHandler* mm_handler = new OscDevice::MouseMotionRequestHandler();
addRequestHandler(mm_handler);
addRequestHandler(new OscDevice::MouseButtonRequestHandler(OscDevice::MouseButtonRequestHandler::PRESS));
addRequestHandler(new OscDevice::MouseButtonRequestHandler(OscDevice::MouseButtonRequestHandler::RELEASE));
addRequestHandler(new OscDevice::MouseButtonRequestHandler(OscDevice::MouseButtonRequestHandler::DOUBLE_PRESS));
addRequestHandler(new OscDevice::MouseScrollRequestHandler());
addRequestHandler(new OscDevice::MouseButtonToggleRequestHandler("1", mm_handler));
addRequestHandler(new OscDevice::MouseButtonToggleRequestHandler("2", mm_handler));
addRequestHandler(new OscDevice::MouseButtonToggleRequestHandler("3", mm_handler));
addRequestHandler(new OscDevice::PenPressureRequestHandler());
addRequestHandler(new OscDevice::PenOrientationRequestHandler());
addRequestHandler(new OscDevice::PenProximityRequestHandler(true));
addRequestHandler(new OscDevice::PenProximityRequestHandler(false));
addRequestHandler(new OscDevice::TUIO2DCursorRequestHandler());
addRequestHandler(new OscDevice::StandardRequestHandler("/osg/set_user_value", true));
addRequestHandler(new OscDevice::StandardRequestHandler("", false));
// getEventQueue()->setFirstTouchEmulatesMouse(false);
setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_LOW);
start();
}
OscReceivingDevice::~OscReceivingDevice()
{
_socket->AsynchronousBreak();
join();
delete _socket;
}
void OscReceivingDevice::run()
{
_socket->Run();
}
void OscReceivingDevice::ProcessMessage( const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint )
{
std::string in_request_path(m.AddressPattern());
if (in_request_path == "/osc/msg_id")
return;
std::string request_path = in_request_path + "/";
std::size_t pos(std::string::npos);
bool handled(false);
do {
pos = request_path.find_last_of('/', pos-1);
if (pos != std::string::npos)
{
std::string mangled_path = request_path.substr(0, pos);
std::pair<RequestHandlerMap::iterator,RequestHandlerMap::iterator> range = _map.equal_range(mangled_path);
for(RequestHandlerMap::iterator i = range.first; i != range.second; ++i)
{
// OSG_INFO << "OscDevice :: handling " << mangled_path << " with " << i->second << std::endl;
if (i->second->operator()(mangled_path, in_request_path, m, remoteEndpoint) && !handled)
handled = true;
}
}
} while ((pos != std::string::npos) && (pos > 0) && !handled);
}
void OscReceivingDevice::ProcessBundle( const osc::ReceivedBundle& b,
const IpEndpointName& remoteEndpoint )
{
// find msg-id
MsgIdType msg_id(0);
for( osc::ReceivedBundle::const_iterator i = b.ElementsBegin(); i != b.ElementsEnd(); ++i ){
const osc::ReceivedMessage& m = osc::ReceivedMessage(*i);
std::string address_pattern(m.AddressPattern());
if(address_pattern == "/osc/msg_id")
{
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
args >> msg_id;
break;
}
}
if (msg_id)
{
osg::Timer_t now(osg::Timer::instance()->tick());
if (osg::Timer::instance()->delta_s(_lastMsgTimeStamp, now) > 0.5) {
OSG_INFO << "OscReceiver :: resetting msg_id to 0 " << std::endl;
_lastMsgId = 0;
}
_lastMsgTimeStamp = now;
if (msg_id <= _lastMsgId) {
// already handled
// OSG_WARN << "OscReceiver :: message with lower id received: " << msg_id << std::endl;
return;
}
else {
if ((msg_id > _lastMsgId+1) && (_lastMsgId > 0)) {
OSG_WARN << "OscReceiver :: missed " << (msg_id - _lastMsgId) << " messages, (" << msg_id << "/" << _lastMsgId << ")" << std::endl;
}
_lastMsgId = msg_id;
}
}
for( osc::ReceivedBundle::const_iterator i = b.ElementsBegin(); i != b.ElementsEnd(); ++i ){
if( i->IsBundle() )
ProcessBundle( osc::ReceivedBundle(*i), remoteEndpoint );
else
{
ProcessMessage( osc::ReceivedMessage(*i), remoteEndpoint );
}
}
}
void OscReceivingDevice::ProcessPacket( const char *data, int size, const IpEndpointName& remoteEndpoint )
{
try {
osc::OscPacketListener::ProcessPacket(data, size, remoteEndpoint);
}
catch(const osc::Exception& e) {
OSG_WARN << "OscDevice :: could not process UDP-packet: " << e.what() << std::endl;
}
catch(...) {
OSG_WARN << "OscDevice :: could not process UDP-packet because of an exception!" << std::endl;
}
if (_userDataEvent.valid())
{
char address[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
remoteEndpoint.AddressAndPortAsString(address);
_userDataEvent->setUserValue("osc/remote_end_point", std::string(address));
_userDataEvent->setTime(getEventQueue()->getTime());
getEventQueue()->addEvent(_userDataEvent.get());
_userDataEvent = NULL;
}
}
void OscReceivingDevice::addRequestHandler(RequestHandler* handler)
{
if (handler)
{
_map.insert(std::make_pair(handler->getRequestPath(), handler));
handler->setDevice(this);
}
}
void OscReceivingDevice::describeTo(std::ostream& out) const
{
out << "OscDevice :: listening on " << _listeningAddress << ":" << _listeningPort << std::endl;
out << std::endl;
for(RequestHandlerMap::const_iterator i = _map.begin(); i != _map.end(); ++i)
{
const RequestHandler* handler(i->second.get());
out << "OscDevice :: ";
handler->describeTo(out);
out << std::endl;
}
}