1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 
15 
16 #include "OscSendingDevice.hpp"
17 #include "osc/OscHostEndianness.h"
18 #include <osg/UserDataContainer>
19 #include <osg/ValueObject>
20 #include <osg/Math>
21 #include <osg/Version>
22 
23 static const unsigned long BUFFER_SIZE = 2048;
24 
OscSendingDevice(const std::string & address,int port,unsigned int num_messages_per_event,unsigned int delay_between_sends_in_millisecs)25 OscSendingDevice::OscSendingDevice(const std::string& address, int port, unsigned int num_messages_per_event, unsigned int delay_between_sends_in_millisecs)
26     : osgGA::Device()
27     , _transmitSocket(IpEndpointName(address.c_str(), port))
28     , _buffer(new  char[BUFFER_SIZE])
29     , _oscStream(_buffer, BUFFER_SIZE)
30     , _numMessagesPerEvent(osg::maximum(1u,num_messages_per_event))
31     , _delayBetweenSendsInMilliSecs( (_numMessagesPerEvent > 1) ? delay_between_sends_in_millisecs : 0)
32     , _msgId(0)
33     , _lastEvent(NULL)
34     , _finishMultiTouchSequence(false)
35 {
36     setCapabilities(SEND_EVENTS);
37 
38     OSG_NOTICE << "OscDevice :: sending events to " << address << ":" << port << " ";
39     #ifdef OSC_HOST_LITTLE_ENDIAN
40         OSG_NOTICE << "(little endian)";
41     #elif OSC_HOST_BIG_ENDIAN
42         OSG_NOTICE << "(big endian)";
43     #endif
44     OSG_NOTICE << " (" << _numMessagesPerEvent << "msgs/event, " << _delayBetweenSendsInMilliSecs << "ms delay between msgs)";
45     OSG_NOTICE << std::endl;
46 
47 }
48 
49 
~OscSendingDevice()50 OscSendingDevice::~OscSendingDevice()
51 {
52     delete[] (_buffer);
53 }
54 
sendEvent(const osgGA::Event & ea)55 void OscSendingDevice::sendEvent(const osgGA::Event &ea)
56 {
57     bool msg_sent(false);
58     unsigned int num_messages = _numMessagesPerEvent;
59 
60     const osgGA::GUIEventAdapter* ui_event(ea.asGUIEventAdapter());
61 
62     if(ui_event && ((ui_event->getEventType() == osgGA::GUIEventAdapter::DRAG) || (ui_event->getEventType() == osgGA::GUIEventAdapter::MOVE)))
63         num_messages = 1;
64 
65     for(unsigned int i = 0; i < num_messages; ++i) {
66         msg_sent = ui_event ? sendUIEventImpl(*ui_event, _msgId) : sendEventImpl(ea, _msgId);
67         if ((_delayBetweenSendsInMilliSecs > 0) && (i < num_messages-1))
68             OpenThreads::Thread::microSleep(1000 * _delayBetweenSendsInMilliSecs);
69     }
70     if (_finishMultiTouchSequence)
71     {
72         // if the last touch-point ended we'll need to send an empty tuio-bundle, so the receiver gets a chance to clean up
73 
74         _msgId++;
75         for(unsigned int i = 0; i < num_messages; ++i) {
76             beginBundle(_msgId);
77             beginMultiTouchSequence();
78             _oscStream << osc::EndBundle;
79             _transmitSocket.Send( _oscStream.Data(), _oscStream.Size() );
80             _oscStream.Clear();
81         }
82         _finishMultiTouchSequence = false;
83     }
84 
85     if (msg_sent)
86         _msgId++;
87 }
88 
89 
sendEventImpl(const osgGA::Event & ea,MsgIdType msg_id)90 bool OscSendingDevice::sendEventImpl(const osgGA::Event &ea, MsgIdType msg_id)
91 {
92     bool do_send(false);
93     if (ea.getUserDataContainer())
94     {
95         std::string key = ea.getUserDataContainer()->getName();
96         if (key.empty()) key = ea.getName();
97         if (key.empty()) key = "user_data";
98 
99         sendUserDataContainer(transliterateKey(key), ea.getUserDataContainer(), true, msg_id);
100 
101         do_send = true;
102     }
103 
104     if (do_send)
105     {
106         OSG_INFO << "OscDevice :: sending event per OSC " << std::endl;
107 
108         _transmitSocket.Send( _oscStream.Data(), _oscStream.Size() );
109         _oscStream.Clear();
110     }
111 
112     return do_send;
113 }
114 
115 
116 
sendUIEventImpl(const osgGA::GUIEventAdapter & ea,MsgIdType msg_id)117 bool OscSendingDevice::sendUIEventImpl(const osgGA::GUIEventAdapter &ea, MsgIdType msg_id)
118 {
119     bool do_send(false);
120     switch(ea.getEventType())
121     {
122         case osgGA::GUIEventAdapter::RESIZE:
123             beginBundle(msg_id);
124             _oscStream << osc::BeginMessage("/osgga/resize") << ea.getWindowX() << ea.getWindowY() << ea.getWindowWidth() << ea.getWindowHeight() << osc::EndMessage;
125             _oscStream << osc::EndBundle;
126             do_send = true;
127             break;
128 
129         case osgGA::GUIEventAdapter::SCROLL:
130             beginSendInputRange(ea, msg_id);
131             _oscStream << osc::BeginMessage("/osgga/mouse/scroll") << ea.getScrollingMotion() << ea.getScrollingDeltaX() << ea.getScrollingDeltaY() << osc::EndMessage;
132             _oscStream << osc::EndBundle;
133             do_send = true;
134             break;
135 
136         case osgGA::GUIEventAdapter::PEN_PRESSURE:
137             beginBundle(msg_id);
138             _oscStream
139                 << osc::BeginMessage("/osgga/pen/pressure")
140                 << ea.getPenPressure()
141                 << osc::EndMessage;
142             _oscStream << osc::EndBundle;
143 
144             do_send = true;
145             break;
146 
147         case osgGA::GUIEventAdapter::PEN_ORIENTATION:
148             beginBundle(msg_id);
149             _oscStream
150                 << osc::BeginMessage("/osgga/pen/orientation")
151                 << ea.getPenRotation()
152                 << ea.getPenTiltX()
153                 << ea.getPenTiltY()
154                 << osc::EndMessage;
155             do_send = true;
156             _oscStream << osc::EndBundle;
157             break;
158 
159         case osgGA::GUIEventAdapter::PEN_PROXIMITY_ENTER:
160             beginBundle(msg_id);
161             _oscStream
162                 << osc::BeginMessage("/osgga/pen/proximity/enter")
163                 << ea.getTabletPointerType()
164                 << osc::EndMessage;
165             do_send = true;
166             break;
167 
168         case osgGA::GUIEventAdapter::PEN_PROXIMITY_LEAVE:
169             beginBundle(msg_id);
170             _oscStream
171                 << osc::BeginMessage("/osgga/pen/proximity/leave")
172                 << ea.getTabletPointerType()
173                 << osc::EndMessage;
174             _oscStream << osc::EndBundle;
175             do_send = true;
176             break;
177 
178         case osgGA::GUIEventAdapter::PUSH:
179             beginSendInputRange(ea, msg_id);
180             if (!sendMultiTouchData(ea))
181                 _oscStream << osc::BeginMessage("/osgga/mouse/press") << ea.getX() << ea.getY() << getButtonNum(ea)  << osc::EndMessage;
182             _oscStream << osc::EndBundle;
183             do_send = true;
184             break;
185 
186         case osgGA::GUIEventAdapter::RELEASE:
187             beginSendInputRange(ea, msg_id);
188             if (!sendMultiTouchData(ea))
189                 _oscStream << osc::BeginMessage("/osgga/mouse/release") << ea.getX() << ea.getY() << getButtonNum(ea)  << osc::EndMessage;
190             _oscStream << osc::EndBundle;
191             do_send = true;
192             break;
193 
194         case osgGA::GUIEventAdapter::DOUBLECLICK:
195             beginSendInputRange(ea, msg_id);
196             if (!sendMultiTouchData(ea))
197                 _oscStream << osc::BeginMessage("/osgga/mouse/doublepress") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage;
198             _oscStream << osc::EndBundle;
199             do_send = true;
200             break;
201 
202         case osgGA::GUIEventAdapter::MOVE:
203         case osgGA::GUIEventAdapter::DRAG:
204             beginSendInputRange(ea, msg_id);
205             if (!sendMultiTouchData(ea))
206                 _oscStream << osc::BeginMessage("/osgga/mouse/motion") << ea.getX() << ea.getY() << osc::EndMessage;
207             _oscStream << osc::EndBundle;
208             do_send = true;
209             break;
210 
211         case osgGA::GUIEventAdapter::KEYDOWN:
212             beginBundle(msg_id);
213             _oscStream << osc::BeginMessage("/osgga/key/press") << ea.getKey() << osc::EndMessage;
214             _oscStream << osc::EndBundle;
215             do_send = true;
216             break;
217 
218         case osgGA::GUIEventAdapter::KEYUP:
219             beginBundle(msg_id);
220             _oscStream << osc::BeginMessage("/osgga/key/release") << ea.getKey() << osc::EndMessage;
221             _oscStream << osc::EndBundle;
222             do_send = true;
223             break;
224 
225         case osgGA::GUIEventAdapter::USER:
226             if (ea.getUserDataContainer())
227             {
228                 std::string key = ea.getUserDataContainer()->getName();
229                 if (key.empty()) key = ea.getName();
230                 if (key.empty()) key = "user_data";
231 
232                 sendUserDataContainer(transliterateKey(key), ea.getUserDataContainer(), true, msg_id);
233 
234                 do_send = true;
235             }
236 
237         default:
238             break;
239 
240     }
241 
242     if (do_send)
243     {
244         _transmitSocket.Send( _oscStream.Data(), _oscStream.Size() );
245         _oscStream.Clear();
246     }
247 
248     return do_send;
249 }
250 
getButtonNum(const osgGA::GUIEventAdapter & ea)251 int OscSendingDevice::getButtonNum(const osgGA::GUIEventAdapter& ea)
252 {
253     switch(ea.getButton())
254     {
255         case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
256             return 1;
257             break;
258         case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
259             return 2;
260             break;
261         case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
262             return 3;
263             break;
264         default:
265             return -1;
266     }
267     return -1;
268 }
269 
270 
271 
beginBundle(MsgIdType msg_id)272 void OscSendingDevice::beginBundle(MsgIdType msg_id)
273 {
274     _oscStream << osc::BeginBundle();
275     _oscStream << osc::BeginMessage("/osc/msg_id") << msg_id << osc::EndMessage;
276 }
277 
278 
279 
beginSendInputRange(const osgGA::GUIEventAdapter & ea,MsgIdType msg_id)280 void OscSendingDevice::beginSendInputRange(const osgGA::GUIEventAdapter &ea, MsgIdType msg_id)
281 {
282     beginBundle(msg_id);
283     _oscStream << osc::BeginMessage("/osgga/mouse/set_input_range") << ea.getXmin() << ea.getYmin() << ea.getXmax() << ea.getYmax() << osc::EndMessage;
284     _oscStream << osc::BeginMessage("/osgga/mouse/y_orientation_increasing_upwards") << (bool)(ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)  << osc::EndMessage;
285 }
286 
287 
beginMultiTouchSequence()288 void OscSendingDevice::beginMultiTouchSequence() {
289 
290     std::string application_name;
291     getUserValue("tuio_application_name", application_name);
292 
293     if (application_name.empty())
294         application_name = std::string("OpenSceneGraph ") + osgGetVersion() + "@127.0.0.1";
295 
296     _oscStream << osc::BeginMessage("/tuio/2Dcur") << "source" << application_name.c_str() << osc::EndMessage;
297     _oscStream << osc::BeginMessage("/tuio/2Dcur") << "fseq" << static_cast<osc::int32>(_msgId) << osc::EndMessage;
298 
299 }
300 
301 
sendMultiTouchData(const osgGA::GUIEventAdapter & ea)302 bool OscSendingDevice::sendMultiTouchData(const osgGA::GUIEventAdapter &ea)
303 {
304     if(!ea.isMultiTouchEvent())
305         return false;
306 
307     beginMultiTouchSequence();
308 
309     osgGA::GUIEventAdapter::TouchData* touch_data = ea.getTouchData();
310 
311     _oscStream << osc::BeginMessage("/tuio/2Dcur") << "alive";
312     for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i)
313         _oscStream << static_cast<osc::int32>(i->id);
314     _oscStream << osc::EndMessage;
315 
316     unsigned int j(0);
317     unsigned int num_ended(0);
318     for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i, ++j)
319     {
320         float x = (ea.getTouchPointNormalizedX(j) + 1.0) / 2.0;
321         float y =(ea.getTouchPointNormalizedY(j) + 1.0) / 2.0;
322 
323         // flip y if origin is not top/left
324         if(ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
325             y *= -1;
326 
327         float vel_x(0), vel_y(0), accel(0);
328         if (_lastEvent.valid())
329         {
330             // TODO: add velocity + acceleration
331         }
332 
333         _oscStream << osc::BeginMessage("/tuio/2Dcur") << "set" << static_cast<osc::int32>(i->id) << x << y << vel_x << vel_y << accel << osc::EndMessage;
334         if(i->phase == osgGA::GUIEventAdapter::TOUCH_ENDED)
335             num_ended++;
336     }
337 
338     _lastEvent = new osgGA::GUIEventAdapter(ea);
339 
340     _finishMultiTouchSequence = (num_ended == touch_data->getNumTouchPoints());
341 
342 
343     return true;
344 }
345 
346 
347 class OscSendingDeviceGetValueVisitor : public osg::ValueObject::GetValueVisitor {
348 public:
OscSendingDeviceGetValueVisitor(osc::OutboundPacketStream & stream)349     OscSendingDeviceGetValueVisitor(osc::OutboundPacketStream& stream)
350         : osg::ValueObject::GetValueVisitor()
351         , _stream(stream)
352     {
353     }
354 
apply(bool value)355     virtual void apply(bool value)                  { _stream << value; }
apply(char value)356     virtual void apply(char value)                  { _stream << value; }
apply(unsigned char value)357     virtual void apply(unsigned char value)         { _stream << value; }
apply(short value)358     virtual void apply(short value)                 { _stream << value; }
apply(unsigned short value)359     virtual void apply(unsigned short value)        { _stream << value; }
apply(int value)360     virtual void apply(int value)                   { _stream << value; }
apply(unsigned int value)361     virtual void apply(unsigned int value)          { _stream << static_cast<osc::int32>(value); }
apply(float value)362     virtual void apply(float value)                 { _stream << value; }
apply(double value)363     virtual void apply(double value)                { _stream << value; }
apply(const std::string & value)364     virtual void apply(const std::string& value)    { _stream << value.c_str(); }
apply(const osg::Vec2f & value)365     virtual void apply(const osg::Vec2f& value)     { _stream << value[0] << value[1]; }
apply(const osg::Vec3f & value)366     virtual void apply(const osg::Vec3f& value)     { _stream << value[0] << value[1] << value[2]; }
apply(const osg::Vec4f & value)367     virtual void apply(const osg::Vec4f& value)     { _stream << value[0] << value[1] << value[2] << value[3]; }
apply(const osg::Vec2d & value)368     virtual void apply(const osg::Vec2d& value)     { _stream << value[0] << value[1]; }
apply(const osg::Vec3d & value)369     virtual void apply(const osg::Vec3d& value)     { _stream << value[0] << value[1] << value[2]; }
apply(const osg::Vec4d & value)370     virtual void apply(const osg::Vec4d& value)     { _stream << value[0] << value[1] << value[2] << value[3]; }
apply(const osg::Quat & value)371     virtual void apply(const osg::Quat& value)      { _stream << value[0] << value[1] << value[2] << value[3]; }
apply(const osg::Plane & value)372     virtual void apply(const osg::Plane& value)     { _stream << value[0] << value[1] << value[2] << value[3]; }
apply(const osg::Matrixf & value)373     virtual void apply(const osg::Matrixf& value)   { for(unsigned int i=0; i<16; ++i) _stream << (value.ptr())[i]; }
apply(const osg::Matrixd & value)374     virtual void apply(const osg::Matrixd& value)   { for(unsigned int i=0; i<16; ++i) _stream << (value.ptr())[i]; }
375 
~OscSendingDeviceGetValueVisitor()376     virtual ~OscSendingDeviceGetValueVisitor() {}
377 
378 private:
379     osc::OutboundPacketStream& _stream;
380 
381 };
382 
transliterateKey(const std::string & key) const383 std::string OscSendingDevice::transliterateKey(const std::string& key) const
384 {
385     std::string result;
386     result.reserve(key.size());
387     for(std::string::const_iterator itr=key.begin();
388         itr!=key.end();
389         ++itr)
390     {
391         if ((*itr == ' ') || (*itr == 9))
392             result += "-";
393         else if ((*itr >= 'A') && (*itr <= 'Z'))
394             result += tolower(*itr);
395         else if (((*itr >= '0') && (*itr <= '9'))  || ((*itr >= 'a') && (*itr <= 'z')) || (*itr == '-') || (*itr == '/') || (*itr == '_'))
396             result += *itr;
397     }
398     return result;
399 }
400 
sendUserDataContainer(const std::string & key,const osg::UserDataContainer * udc,bool asBundle,MsgIdType msg_id)401 void OscSendingDevice::sendUserDataContainer(const std::string& key, const osg::UserDataContainer* udc, bool asBundle, MsgIdType msg_id)
402 {
403     if (asBundle) {
404         beginBundle(msg_id);
405     }
406 
407     OscSendingDeviceGetValueVisitor gvv(_oscStream);
408 
409     unsigned int num_objects = udc->getNumUserObjects();
410     for(unsigned int i = 0; i < num_objects; ++i)
411     {
412         const osg::Object* o = udc->getUserObject(i);
413         const osg::UserDataContainer* child_udc = dynamic_cast<const osg::UserDataContainer*>(o);
414         if (child_udc)
415         {
416             std::string new_key = key + "/" + (child_udc->getName().empty() ? "user_data" : child_udc->getName());
417             sendUserDataContainer(transliterateKey(key), child_udc, false, msg_id);
418         }
419         else if (const osg::ValueObject* vo = dynamic_cast<const osg::ValueObject*>(o))
420         {
421             _oscStream << osc::BeginMessage(std::string("/" + key + "/" + transliterateKey(vo->getName())).c_str());
422             vo->get(gvv);
423             _oscStream << osc::EndMessage;
424         }
425     }
426 
427     if (asBundle)
428         _oscStream << osc::EndBundle;
429 
430 }
431