summaryrefslogtreecommitdiff
path: root/src/player/LibMTDevInputDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/LibMTDevInputDevice.cpp')
-rw-r--r--src/player/LibMTDevInputDevice.cpp190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/player/LibMTDevInputDevice.cpp b/src/player/LibMTDevInputDevice.cpp
new file mode 100644
index 0000000..edfd061
--- /dev/null
+++ b/src/player/LibMTDevInputDevice.cpp
@@ -0,0 +1,190 @@
+//
+// 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 "LibMTDevInputDevice.h"
+
+#include "TouchEvent.h"
+#include "Player.h"
+#include "AVGNode.h"
+#include "TouchStatus.h"
+
+#include "../base/Logger.h"
+#include "../base/ObjectCounter.h"
+#include "../base/Exception.h"
+#include "../base/OSHelper.h"
+
+#include <linux/input.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern "C" {
+#include <mtdev.h>
+#include <mtdev-mapping.h>
+}
+
+using namespace std;
+
+namespace avg {
+
+LibMTDevInputDevice::LibMTDevInputDevice()
+ : m_LastID(0),
+ m_pMTDevice(0)
+{
+}
+
+LibMTDevInputDevice::~LibMTDevInputDevice()
+{
+ if (m_pMTDevice) {
+ mtdev_close(m_pMTDevice);
+ delete m_pMTDevice;
+ }
+}
+
+void LibMTDevInputDevice::start()
+{
+ string sDevice("/dev/input/event3");
+ getEnv("AVG_LINUX_MULTITOUCH_DEVICE", sDevice);
+ m_DeviceFD = ::open(sDevice.c_str(), O_RDONLY | O_NONBLOCK);
+ if (m_DeviceFD == -1) {
+ throw Exception(AVG_ERR_MT_INIT,
+ string("Linux multitouch event source: Could not open device file '")+
+ sDevice+"'. "+strerror(errno)+".");
+ }
+ m_pMTDevice = new mtdev;
+ int err = mtdev_open(m_pMTDevice, m_DeviceFD);
+ if (err == -1) {
+ throw Exception(AVG_ERR_MT_INIT,
+ string("Linux multitouch event source: Could not open mtdev '")+
+ sDevice+"'. "+strerror(errno)+".");
+ }
+ input_absinfo* pAbsInfo;
+ pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_X]);
+ m_Dimensions.tl.x = pAbsInfo->minimum;
+ m_Dimensions.br.x = pAbsInfo->maximum;
+ pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_Y]);
+ m_Dimensions.tl.y = pAbsInfo->minimum;
+ m_Dimensions.br.y = pAbsInfo->maximum;
+
+ MultitouchInputDevice::start();
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO,
+ "Linux MTDev Multitouch event source created.");
+}
+
+std::vector<EventPtr> LibMTDevInputDevice::pollEvents()
+{
+ struct input_event event;
+ static int curSlot = 0;
+
+ set<int> changedIDs;
+ while (mtdev_get(m_pMTDevice, m_DeviceFD, &event, 1) > 0) {
+ if (event.type == EV_SYN && event.code == SYN_REPORT) {
+// cerr << ">> SYN_REPORT" << endl;
+ processEvents(changedIDs);
+ changedIDs.clear();
+ } else if (event.type == EV_ABS && event.code == ABS_MT_SLOT) {
+// cerr << ">> slot " << event.value << endl;
+ curSlot = event.value;
+ } else {
+ TouchData* pTouch;
+ switch (event.code) {
+ case ABS_MT_TRACKING_ID:
+// cerr << ">> ABS_MT_TRACKING_ID: " << event.value << endl;
+ pTouch = &(m_Slots[curSlot]);
+ if (event.value == -1) {
+ TouchStatusPtr pTouchStatus = getTouchStatus(pTouch->id);
+// cerr << "up " << pTouch->id << endl;
+ if (pTouchStatus) {
+// cerr << " --> remove" << endl;
+ TouchEventPtr pOldEvent = pTouchStatus->getLastEvent();
+ TouchEventPtr pUpEvent =
+ boost::dynamic_pointer_cast<TouchEvent>(
+ pOldEvent->cloneAs(Event::CURSOR_UP));
+ pTouchStatus->pushEvent(pUpEvent);
+ removeTouchStatus(pTouch->id);
+ }
+ pTouch->id = -1;
+ } else {
+ pTouch->id = event.value;
+ changedIDs.insert(curSlot);
+ }
+ break;
+ case ABS_MT_POSITION_X:
+// cerr << ">> ABS_MT_POSITION_X: " << event.value << endl;
+ pTouch = &(m_Slots[curSlot]);
+ pTouch->pos.x = event.value;
+ changedIDs.insert(curSlot);
+ break;
+ case ABS_MT_POSITION_Y:
+// cerr << ">> ABS_MT_POSITION_Y: " << event.value << endl;
+ pTouch = &(m_Slots[curSlot]);
+ pTouch->pos.y = event.value;
+ changedIDs.insert(curSlot);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return MultitouchInputDevice::pollEvents();
+}
+
+void LibMTDevInputDevice::processEvents(const set<int>& changedIDs)
+{
+ for (set<int>::iterator it = changedIDs.begin(); it != changedIDs.end(); ++it) {
+ map<int, TouchData>::iterator it2 = m_Slots.find(*it);
+ if (it2 != m_Slots.end()) {
+ const TouchData& touch = it2->second;
+// cerr << "slot: " << *it << ", id: " << touch.id << ", pos: " << touch.pos
+// << endl;
+// AVG_ASSERT(touch.pos.x != 0);
+ if (touch.id != -1) {
+ TouchStatusPtr pTouchStatus = getTouchStatus(touch.id);
+ if (!pTouchStatus) {
+ // Down
+ m_LastID++;
+ TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSOR_DOWN,
+ touch.pos);
+// cerr << "down <" << touch.id << "> --> [" << m_LastID << "]" << endl;
+ addTouchStatus((long)touch.id, pEvent);
+ } else {
+// cerr << "move <" << touch.id << "> --> " << touch.pos << endl;
+ // Move
+ TouchEventPtr pEvent = createEvent(0, Event::CURSOR_MOTION,
+ touch.pos);
+ pTouchStatus->pushEvent(pEvent);
+ }
+ }
+ }
+ }
+}
+
+TouchEventPtr LibMTDevInputDevice::createEvent(int id, Event::Type type, IntPoint pos)
+{
+ glm::vec2 size(Player::get()->getScreenResolution());
+ glm::vec2 normPos(float(pos.x-m_Dimensions.tl.x)/m_Dimensions.width(),
+ float(pos.y-m_Dimensions.tl.y)/m_Dimensions.height());
+ IntPoint screenPos(int(normPos.x*size.x+0.5), int(normPos.y*size.y+0.5));
+ return TouchEventPtr(new TouchEvent(id, type, screenPos, Event::TOUCH));
+}
+
+}