From Stephan Huber, added event sending support into osgGA::Device along with implementation on this into the osc plugin. Added osgoscdevice example to demonstate this in action.
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
using namespace osgGA;
|
||||
|
||||
Device::Device()
|
||||
: osg::Object()
|
||||
, _capabilities(UNKNOWN)
|
||||
{
|
||||
setEventQueue(new EventQueue);
|
||||
}
|
||||
@@ -26,6 +28,21 @@ Device::Device(const Device& es, const osg::CopyOp& copyop):
|
||||
setEventQueue(new EventQueue);
|
||||
}
|
||||
|
||||
void Device::sendEvent(const GUIEventAdapter& event)
|
||||
{
|
||||
OSG_WARN << "Device::sendEvent not implemented!" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void Device::sendEvents(const EventQueue::Events& events)
|
||||
{
|
||||
for(EventQueue::Events::const_iterator i = events.begin(); i != events.end(); i++)
|
||||
{
|
||||
sendEvent(**i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ SET(TARGET_SRC
|
||||
osc/OscPrintReceivedElements.cpp
|
||||
osc/OscReceivedElements.cpp
|
||||
osc/OscTypes.cpp
|
||||
OscDevice.cpp
|
||||
OscProxyEventHandler.cpp
|
||||
OscReceivingDevice.cpp
|
||||
OscSendingDevice.cpp
|
||||
ReaderWriterOscDevice.cpp
|
||||
)
|
||||
|
||||
@@ -25,8 +25,8 @@ SET(TARGET_H
|
||||
osc/OscPrintReceivedElements.h
|
||||
osc/OscReceivedElements.h
|
||||
osc/OscTypes.h
|
||||
OscProxyEventHandler.hpp
|
||||
OscDevice.hpp
|
||||
OscReceivingDevice.hpp
|
||||
OscSendingDevice.hpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
||||
@@ -1,598 +0,0 @@
|
||||
/* -*-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 "OscDevice.hpp"
|
||||
#include <OpenThreads/Thread>
|
||||
#include <osgDB/FileUtils>
|
||||
#include "osc/OscPrintReceivedElements.h"
|
||||
#include "osc/OscHostEndianness.h"
|
||||
|
||||
|
||||
class StandardRequestHandler : public OscDevice::RequestHandler {
|
||||
public:
|
||||
StandardRequestHandler() : OscDevice::RequestHandler("") {}
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
OSG_NOTICE << "OscDevice :: unhandled request: " << full_request_path << std::endl;
|
||||
|
||||
for(osc::ReceivedMessageArgumentIterator itr = m.ArgumentsBegin(); itr != m.ArgumentsEnd(); ++itr)
|
||||
{
|
||||
OSG_NOTICE << " " << (*itr) << std::endl;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void describeTo(std::ostream& out) const
|
||||
{
|
||||
out << getRequestPath() << ": fall-through request-handler, catches all requests w/o registered handler and report them to the console";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SetMouseInputRangeRequestHandler : public OscDevice::RequestHandler {
|
||||
public:
|
||||
SetMouseInputRangeRequestHandler()
|
||||
: OscDevice::RequestHandler("/osgga/mouse/set_input_range")
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
SetMouseOrientationRequestHandler()
|
||||
: OscDevice::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)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
KeyCodeRequestHandler(bool handle_key_press)
|
||||
: OscDevice::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)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
KeyPressAndReleaseRequestHandler()
|
||||
: OscDevice::RequestHandler("/osgga/key/press_and_release")
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
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";
|
||||
}
|
||||
private:
|
||||
bool _handleKeyPress;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class MouseMotionRequestHandler : public OscDevice::RequestHandler {
|
||||
public:
|
||||
MouseMotionRequestHandler()
|
||||
: OscDevice::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)
|
||||
{
|
||||
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
MouseScrollRequestHandler()
|
||||
: OscDevice::RequestHandler("/osgga/mouse/scroll")
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
MouseButtonToggleRequestHandler(const std::string& btn_name, MouseMotionRequestHandler* mm_handler)
|
||||
: OscDevice::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)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
enum Mode { PRESS, RELEASE, DOUBLE_PRESS};
|
||||
|
||||
MouseButtonRequestHandler(Mode mode)
|
||||
: OscDevice::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)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
PenPressureRequestHandler()
|
||||
: OscDevice::RequestHandler("/osgga/pen/pressure")
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
PenProximityRequestHandler(bool handle_enter)
|
||||
: OscDevice::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)
|
||||
{
|
||||
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 OscDevice::RequestHandler {
|
||||
public:
|
||||
PenOrientationRequestHandler()
|
||||
: OscDevice::RequestHandler("/osgga/pen/orientation")
|
||||
, _lastX(0.0f)
|
||||
, _lastY(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m)
|
||||
{
|
||||
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";
|
||||
}
|
||||
float getLastX() const { return _lastX; }
|
||||
float getLastY() const { return _lastY; }
|
||||
private:
|
||||
float _lastX, _lastY;
|
||||
};
|
||||
|
||||
|
||||
|
||||
OscDevice::OscDevice(const std::string& server_address, int listening_port)
|
||||
: osgGA::Device()
|
||||
, OpenThreads::Thread()
|
||||
, osc::OscPacketListener()
|
||||
, _listeningAddress(server_address)
|
||||
, _listeningPort(listening_port)
|
||||
, _socket(NULL)
|
||||
, _map()
|
||||
{
|
||||
|
||||
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 KeyCodeRequestHandler(false));
|
||||
addRequestHandler(new KeyCodeRequestHandler(true));
|
||||
addRequestHandler(new KeyPressAndReleaseRequestHandler());
|
||||
|
||||
addRequestHandler(new SetMouseInputRangeRequestHandler());
|
||||
addRequestHandler(new SetMouseOrientationRequestHandler());
|
||||
|
||||
MouseMotionRequestHandler* mm_handler = new MouseMotionRequestHandler();
|
||||
addRequestHandler(mm_handler);
|
||||
addRequestHandler(new MouseButtonRequestHandler(MouseButtonRequestHandler::PRESS));
|
||||
addRequestHandler(new MouseButtonRequestHandler(MouseButtonRequestHandler::RELEASE));
|
||||
addRequestHandler(new MouseButtonRequestHandler(MouseButtonRequestHandler::DOUBLE_PRESS));
|
||||
addRequestHandler(new MouseScrollRequestHandler());
|
||||
|
||||
addRequestHandler(new MouseButtonToggleRequestHandler("1", mm_handler));
|
||||
addRequestHandler(new MouseButtonToggleRequestHandler("2", mm_handler));
|
||||
addRequestHandler(new MouseButtonToggleRequestHandler("3", mm_handler));
|
||||
|
||||
addRequestHandler(new PenPressureRequestHandler());
|
||||
addRequestHandler(new PenOrientationRequestHandler());
|
||||
addRequestHandler(new PenProximityRequestHandler(true));
|
||||
addRequestHandler(new PenProximityRequestHandler(false));
|
||||
|
||||
addRequestHandler(new StandardRequestHandler());
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
OscDevice::~OscDevice()
|
||||
{
|
||||
_socket->AsynchronousBreak();
|
||||
join();
|
||||
delete _socket;
|
||||
}
|
||||
|
||||
void OscDevice::run()
|
||||
{
|
||||
_socket->Run();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OscDevice::ProcessMessage( const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint )
|
||||
{
|
||||
std::string in_request_path(m.AddressPattern());
|
||||
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) && !handled)
|
||||
handled = true;
|
||||
}
|
||||
|
||||
}
|
||||
} while ((pos != std::string::npos) && (pos > 0) && !handled);
|
||||
|
||||
}
|
||||
|
||||
void OscDevice::ProcessPacket( const char *data, int size, const IpEndpointName& remoteEndpoint )
|
||||
{
|
||||
OSG_INFO << "OscDevice :: receiving " << size << " bytes of data ..." << std::endl;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OscDevice::addRequestHandler(RequestHandler* handler)
|
||||
{
|
||||
if (handler)
|
||||
{
|
||||
_map.insert(std::make_pair(handler->getRequestPath(), handler));
|
||||
handler->setDevice(this);
|
||||
}
|
||||
}
|
||||
|
||||
void OscDevice::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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/* -*-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.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <osg/Referenced>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <osgGA/Device>
|
||||
#include <osc/OscPacketListener.h>
|
||||
#include <ip/UdpSocket.h>
|
||||
|
||||
|
||||
class OscDevice : public osgGA::Device, OpenThreads::Thread, osc::OscPacketListener {
|
||||
|
||||
public:
|
||||
class RequestHandler : public osg::Referenced {
|
||||
public:
|
||||
RequestHandler(const std::string& request_path)
|
||||
: osg::Referenced()
|
||||
, _requestPath(request_path)
|
||||
, _device(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& m) = 0;
|
||||
|
||||
const std::string& getRequestPath() const { return _requestPath; }
|
||||
|
||||
virtual void describeTo(std::ostream& out) const
|
||||
{
|
||||
out << getRequestPath() << ": no description available";
|
||||
}
|
||||
|
||||
protected:
|
||||
void setDevice(OscDevice* device) { _device = device; }
|
||||
OscDevice* getDevice() const { return _device; }
|
||||
|
||||
/// set the request-path, works only from the constructor
|
||||
void setRequestPath(const std::string& request_path) { _requestPath = request_path; }
|
||||
|
||||
void handleException(const osc::Exception& e)
|
||||
{
|
||||
OSG_WARN << "OscDevice :: error while handling " << getRequestPath() << ": " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
double getLocalTime() const { return getDevice()->getEventQueue()->getTime(); }
|
||||
private:
|
||||
std::string _requestPath;
|
||||
OscDevice* _device;
|
||||
friend class OscDevice;
|
||||
};
|
||||
|
||||
typedef std::multimap<std::string, osg::ref_ptr<RequestHandler> > RequestHandlerMap;
|
||||
|
||||
OscDevice(const std::string& server_address, int listening_port);
|
||||
~OscDevice();
|
||||
|
||||
virtual void checkEvents() {}
|
||||
virtual void run();
|
||||
|
||||
virtual void ProcessMessage( const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint );
|
||||
virtual void ProcessPacket( const char *data, int size, const IpEndpointName& remoteEndpoint );
|
||||
|
||||
void addRequestHandler(RequestHandler* handler);
|
||||
|
||||
void describeTo(std::ostream& out) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const OscDevice& device)
|
||||
{
|
||||
device.describeTo(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _listeningAddress;
|
||||
unsigned int _listeningPort;
|
||||
UdpListeningReceiveSocket* _socket;
|
||||
RequestHandlerMap _map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class SendKeystrokeRequestHandler : public OscDevice::RequestHandler {
|
||||
public:
|
||||
SendKeystrokeRequestHandler(const std::string& request_path, int key) : OscDevice::RequestHandler(request_path), _key(key) {}
|
||||
virtual bool operator()(const std::string& request_path, const std::string& full_request_path, const osc::ReceivedMessage& arguments)
|
||||
{
|
||||
getDevice()->getEventQueue()->keyPress(_key);
|
||||
getDevice()->getEventQueue()->keyRelease(_key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void describeTo(std::ostream& out) const
|
||||
{
|
||||
out << getRequestPath() << ": send KEY_DOWN + KEY_UP, code: 0x" << std::hex << _key << std::dec;
|
||||
}
|
||||
private:
|
||||
int _key;
|
||||
};
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/* -*-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 "OscProxyEventHandler.hpp"
|
||||
#include "osc/OscHostEndianness.h"
|
||||
|
||||
static const unsigned long BUFFER_SIZE = 2048;
|
||||
|
||||
OscProxyEventHandler::OscProxyEventHandler(const std::string& address, int port)
|
||||
: osgGA::GUIEventHandler()
|
||||
, _transmitSocket(IpEndpointName(address.c_str(), port))
|
||||
, _buffer(new char[BUFFER_SIZE])
|
||||
, _oscStream(_buffer, BUFFER_SIZE)
|
||||
, _firstRun(true)
|
||||
{
|
||||
OSG_NOTICE << "OscDevice :: sending events to " << address << ":" << port << " ";
|
||||
#ifdef OSC_HOST_LITTLE_ENDIAN
|
||||
OSG_NOTICE << "(little endian)";
|
||||
#elif OSC_HOST_BIG_ENDIAN
|
||||
OSG_NOTICE << "(big endian)";
|
||||
#endif
|
||||
OSG_NOTICE << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
OscProxyEventHandler::~OscProxyEventHandler()
|
||||
{
|
||||
delete[] (_buffer);
|
||||
}
|
||||
|
||||
bool OscProxyEventHandler::handle (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa, osg::Object *, osg::NodeVisitor *)
|
||||
{
|
||||
bool do_send(false);
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case osgGA::GUIEventAdapter::FRAME:
|
||||
if (_firstRun)
|
||||
{
|
||||
_firstRun = false;
|
||||
sendInit(ea);
|
||||
do_send = true;
|
||||
}
|
||||
break;
|
||||
case osgGA::GUIEventAdapter::RESIZE:
|
||||
sendInit(ea);
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::SCROLL:
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/scroll") << ea.getScrollingMotion() << ea.getScrollingDeltaX() << ea.getScrollingDeltaY() << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::PEN_PRESSURE:
|
||||
_oscStream
|
||||
<< osc::BeginMessage("/osgga/pen/pressure")
|
||||
<< ea.getPenPressure()
|
||||
<< osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::PEN_ORIENTATION:
|
||||
|
||||
_oscStream
|
||||
<< osc::BeginMessage("/osgga/pen/orientation")
|
||||
<< ea.getPenRotation()
|
||||
<< ea.getPenTiltX()
|
||||
<< ea.getPenTiltY()
|
||||
<< osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::PEN_PROXIMITY_ENTER:
|
||||
_oscStream
|
||||
<< osc::BeginMessage("/osgga/pen/proximity/enter")
|
||||
<< ea.getTabletPointerType()
|
||||
<< osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::PEN_PROXIMITY_LEAVE:
|
||||
_oscStream
|
||||
<< osc::BeginMessage("/osgga/pen/proximity/leave")
|
||||
<< ea.getTabletPointerType()
|
||||
<< osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::PUSH:
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/press") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::RELEASE:
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/release") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::DOUBLECLICK:
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/doublepress") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::MOVE:
|
||||
case osgGA::GUIEventAdapter::DRAG:
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/motion") << ea.getX() << ea.getY() << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::KEYDOWN:
|
||||
_oscStream << osc::BeginMessage("/osgga/key/press") << ea.getKey() << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
case osgGA::GUIEventAdapter::KEYUP:
|
||||
_oscStream << osc::BeginMessage("/osgga/key/release") << ea.getKey() << osc::EndMessage;
|
||||
do_send = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (do_send)
|
||||
{
|
||||
OSG_INFO << "OscDevice :: sending event per OSC " << std::endl;
|
||||
|
||||
_transmitSocket.Send( _oscStream.Data(), _oscStream.Size() );
|
||||
_oscStream.Clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int OscProxyEventHandler::getButtonNum(const osgGA::GUIEventAdapter& ea)
|
||||
{
|
||||
switch(ea.getButton())
|
||||
{
|
||||
case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
|
||||
return 1;
|
||||
break;
|
||||
case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
|
||||
return 2;
|
||||
break;
|
||||
case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
|
||||
return 3;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void OscProxyEventHandler::sendInit(const osgGA::GUIEventAdapter &ea)
|
||||
{
|
||||
_oscStream << osc::BeginBundle();
|
||||
_oscStream << osc::BeginMessage("/osgga/resize") << ea.getWindowX() << ea.getWindowY() << ea.getWindowWidth() << ea.getWindowHeight() << osc::EndMessage;
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/set_input_range") << ea.getXmin() << ea.getYmin() << ea.getXmax() << ea.getYmax() << osc::EndMessage;
|
||||
_oscStream << osc::BeginMessage("/osgga/mouse/y_orientation_increasing_upwards") << (bool)(ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) << osc::EndMessage;
|
||||
_oscStream << osc::EndBundle;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/* -*-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.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include <osgGA/GUIEventHandler>
|
||||
#include <ip/UdpSocket.h>
|
||||
#include <osc/OscOutboundPacketStream.h>
|
||||
|
||||
class OscProxyEventHandler : public osgGA::GUIEventHandler {
|
||||
public:
|
||||
OscProxyEventHandler(const std::string& address, int port);
|
||||
~OscProxyEventHandler();
|
||||
virtual bool handle (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa, osg::Object *, osg::NodeVisitor *);
|
||||
|
||||
private:
|
||||
void sendInit(const osgGA::GUIEventAdapter& ea);
|
||||
int getButtonNum(const osgGA::GUIEventAdapter& ea);
|
||||
|
||||
UdpTransmitSocket _transmitSocket;
|
||||
char* _buffer;
|
||||
osc::OutboundPacketStream _oscStream;
|
||||
bool _firstRun;
|
||||
|
||||
};
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
*
|
||||
* the osc-plugin can return an osgGA::Device which handles various osc-messages
|
||||
* and puts them into the event-queue of the app
|
||||
* you can set arbitrary values via /osg/set_user_value, these values
|
||||
* are set on the attached UserDataConntainer (see below)
|
||||
*
|
||||
* To open the osc-device for receiving do something like this:
|
||||
*
|
||||
* std::string filename = "<your-port-number-to-listen-on>.receiver.osc";
|
||||
@@ -26,6 +29,12 @@
|
||||
* The plugin supports the following option: documentRegisteredHandlers, which will
|
||||
* dump all registered handlers to the console. The device registers some convenient
|
||||
* handlers to remote control a p3d-presentation.
|
||||
*
|
||||
* you can feed a osgPresentation::PropertyManager into the plugin and set values on it via
|
||||
* "/p3d/set_value key value" or "/p3d/set_value/key value"
|
||||
* Additionally the plugin listens for
|
||||
* "/osg/set_user_value key value" or "/osg/set_user_value/key value" and set the transmitted value on the
|
||||
* UserDataContainer of the device.
|
||||
*
|
||||
*
|
||||
* The plugin supports forwarding most of the events per osc to another host.
|
||||
@@ -48,8 +57,9 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
#include "OscDevice.hpp"
|
||||
#include "OscProxyEventHandler.hpp"
|
||||
#include "OscSendingDevice.hpp"
|
||||
#include "OscReceivingDevice.hpp"
|
||||
#include <osgPresentation/PropertyManager>
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +90,7 @@ class ReaderWriterOsc : public osgDB::ReaderWriter
|
||||
std::string server_address = file_name.substr(0,file_name.find(':'));
|
||||
std::string server_port = file_name.substr(file_name.find(':') + 1);
|
||||
|
||||
return new OscProxyEventHandler(server_address, atoi(server_port.c_str()));
|
||||
return new OscSendingDevice(server_address, atoi(server_port.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,7 +109,7 @@ class ReaderWriterOsc : public osgDB::ReaderWriter
|
||||
}
|
||||
try {
|
||||
|
||||
osg::ref_ptr<OscDevice> device = new OscDevice(server_address, port);
|
||||
osg::ref_ptr<OscReceivingDevice> device = new OscReceivingDevice(server_address, port);
|
||||
|
||||
|
||||
device->addRequestHandler(new SendKeystrokeRequestHandler("/p3d/slide/first", osgGA::GUIEventAdapter::KEY_Home));
|
||||
@@ -120,7 +130,8 @@ class ReaderWriterOsc : public osgDB::ReaderWriter
|
||||
device->addRequestHandler(new SendKeystrokeRequestHandler("/osgviewer/home", ' '));
|
||||
device->addRequestHandler(new SendKeystrokeRequestHandler("/osgviewer/stats", 's'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if ((options && (options->getPluginStringData("documentRegisteredHandlers") == "true")))
|
||||
{
|
||||
|
||||
@@ -195,7 +195,6 @@ public:
|
||||
IpEndpointName temp = IpEndpointNameFromSockaddr(bindSockAddr);
|
||||
char address[30];
|
||||
temp.AddressAndPortAsString(address);
|
||||
printf("UdpSocket::Bind() %s \n", address);
|
||||
}
|
||||
if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
|
||||
throw std::runtime_error("unable to bind udp socket\n");
|
||||
@@ -425,7 +424,6 @@ public:
|
||||
timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000);
|
||||
timeoutPtr = &timeout;
|
||||
}
|
||||
printf("UdpSocket::Run() waiting for select \n");
|
||||
if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){
|
||||
throw std::runtime_error("select failed\n");
|
||||
}
|
||||
@@ -443,7 +441,6 @@ public:
|
||||
i != socketListeners_.end(); ++i ){
|
||||
|
||||
if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
|
||||
printf("UdpSocket::Run() reading from socket \n");
|
||||
int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
|
||||
if( size > 0 ){
|
||||
i->first->ProcessPacket( data, size, remoteEndpoint );
|
||||
|
||||
Reference in New Issue
Block a user