diff options
Diffstat (limited to 'src/player/TUIOInputDevice.cpp')
-rw-r--r-- | src/player/TUIOInputDevice.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/player/TUIOInputDevice.cpp b/src/player/TUIOInputDevice.cpp new file mode 100644 index 0000000..f6f3f08 --- /dev/null +++ b/src/player/TUIOInputDevice.cpp @@ -0,0 +1,216 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// 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 GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "TUIOInputDevice.h" +#include "TouchEvent.h" +#include "Player.h" +#include "AVGNode.h" +#include "TouchStatus.h" + +#include "../base/Logger.h" +#include "../base/StringHelper.h" +#include "../base/OSHelper.h" +#include "../base/ObjectCounter.h" +#include "../base/Exception.h" + +using namespace std; +using namespace osc; + +namespace avg { + +#ifndef WIN32 +void* TUIOInputDevice::threadFunc(void* p) +#else +DWORD WINAPI TUIOInputDevice::threadFunc(LPVOID p) +#endif +{ + TUIOInputDevice* pThis = (TUIOInputDevice*)p; + pThis->m_pSocket->Run(); + return 0; +}; + +TUIOInputDevice::TUIOInputDevice() + : m_pSocket(0), + m_LastID(0) +{ +} + +TUIOInputDevice::~TUIOInputDevice() +{ + if (m_pSocket) { + m_pSocket->Break(); + } +} + +void TUIOInputDevice::start() +{ + string sPort("3333"); + getEnv("AVG_TUIO_PORT", sPort); + int port; + try { + port = stringToInt(sPort); + } catch (Exception&) { + throw Exception(AVG_ERR_TYPE, + string("TUIO event source: AVG_TUIO_PORT set to invalid value '") + + sPort + "'"); + } + MultitouchInputDevice::start(); + try { + m_pSocket = new UdpListeningReceiveSocket(IpEndpointName( + IpEndpointName::ANY_ADDRESS, port), this); + } catch (std::exception &e) { + throw Exception(AVG_ERR_MT_INIT, + string("TUIO event source: Can't initialize networking. ") + e.what()); + } + if (!m_pSocket->IsBound()) { + throw Exception(AVG_ERR_MT_INIT, "TUIO event source: Socket not bound."); + } + AVG_TRACE(Logger::category::CONFIG,Logger::severity::INFO, + "TUIO multitouch event source created, listening on port " << port); + +#ifndef WIN32 + pthread_create(&m_Thread, NULL, threadFunc, this); +#else + DWORD threadId; + m_Thread = CreateThread(0, 0, threadFunc, this, 0, &threadId); +#endif +} + +void TUIOInputDevice::ProcessPacket(const char* pData, int size, + const IpEndpointName& remoteEndpoint) +{ + lock_guard lock(getMutex()); + try { + ReceivedPacket packet(pData, size); + if (packet.IsBundle()) { + processBundle(ReceivedBundle(packet), remoteEndpoint); + } else { + processMessage(ReceivedMessage(packet), remoteEndpoint); + } + } catch (osc::Exception& e) { + AVG_LOG_WARNING("OSC exception: " << e.what()); + } +} + +void TUIOInputDevice::processBundle(const ReceivedBundle& bundle, + const IpEndpointName& remoteEndpoint) +{ + try { + for (ReceivedBundle::const_iterator it = bundle.ElementsBegin(); + it != bundle.ElementsEnd(); ++it) + { + if (it->IsBundle()) { + processBundle(ReceivedBundle(*it), remoteEndpoint); + } else { + processMessage(ReceivedMessage(*it), remoteEndpoint); + } + } + } catch (osc::Exception& e) { + AVG_LOG_WARNING("OSC exception: " << e.what()); + } +} + +void TUIOInputDevice::processMessage(const ReceivedMessage& msg, + const IpEndpointName& remoteEndpoint) +{ +// cerr << msg << endl; + try { + ReceivedMessageArgumentStream args = msg.ArgumentStream(); + + if (strcmp(msg.AddressPattern(), "/tuio/2Dcur") == 0) { + const char* cmd; + args >> cmd; + + if (strcmp(cmd,"set")==0) { + processSet(args); + } else if (strcmp(cmd,"alive")==0) { + processAlive(args); + } else if (strcmp(cmd, "fseq") == 0 ) { + int32 fseq; + args >> fseq; + } + } + } catch (osc::Exception& e) { + AVG_LOG_WARNING("Error parsing TUIO message: " << e.what() + << ". Message was " << msg); + } +} + +void TUIOInputDevice::processSet(ReceivedMessageArgumentStream& args) +{ + osc::int32 tuioID; + float xpos, ypos; + float xspeed, yspeed; + float accel; + args >> tuioID >> xpos >> ypos >> xspeed >> yspeed >> accel; + glm::vec2 pos(xpos, ypos); + glm::vec2 speed(xspeed, yspeed); +// cerr << "Set: ID: " << tuioID << ", pos: " << pos << ", speed: " << speed +// << ", accel: " << accel << endl; + TouchStatusPtr pTouchStatus = getTouchStatus(tuioID); + if (!pTouchStatus) { + // Down + m_LastID++; + TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSOR_DOWN, pos, speed); + addTouchStatus((long)tuioID, pEvent); + } else { + // Move + TouchEventPtr pEvent = createEvent(0, Event::CURSOR_MOTION, pos, speed); + pTouchStatus->pushEvent(pEvent); + } +} + +void TUIOInputDevice::processAlive(ReceivedMessageArgumentStream& args) +{ + m_LiveTUIOIDs.clear(); + int32 tuioID; + while (!args.Eos()) { + args >> tuioID; + m_LiveTUIOIDs.insert(tuioID); + } + + // Create up events for all ids not in live list. + set<int> deadTUIOIDs; + getDeadIDs(m_LiveTUIOIDs, deadTUIOIDs); + set<int>::iterator it; + for (it = deadTUIOIDs.begin(); it != deadTUIOIDs.end(); ++it) { + int id = *it; + TouchStatusPtr pTouchStatus = getTouchStatus(id); + TouchEventPtr pOldEvent = pTouchStatus->getLastEvent(); + TouchEventPtr pUpEvent = boost::dynamic_pointer_cast<TouchEvent>( + pOldEvent->cloneAs(Event::CURSOR_UP)); + pTouchStatus->pushEvent(pUpEvent); + removeTouchStatus(id); + } +} + +TouchEventPtr TUIOInputDevice::createEvent(int id, Event::Type type, glm::vec2 pos, + glm::vec2 speed) +{ + const glm::vec2 size = getTouchArea(); + IntPoint screenPos = getScreenPos(pos); + glm::vec2 screenSpeed(int(speed.x*size.x+0.5), int(speed.y*size.y+0.5)); + TouchEventPtr pEvent(new TouchEvent(id, type, screenPos, Event::TOUCH)); + pEvent->setSpeed(screenSpeed/1000.f); + return pEvent; +} + +} |