summaryrefslogtreecommitdiff
path: root/touchthread.c
diff options
context:
space:
mode:
authorhorchi <vdr@jwendel.de>2017-03-05 16:47:41 +0100
committerhorchi <vdr@jwendel.de>2017-03-05 16:47:41 +0100
commit22ffee20bbacbc3378e4ba0df5b7f0c3daaeffc0 (patch)
treede46c945c62d43d1febb027b5bfa075e58c5b69a /touchthread.c
downloadvdr-plugin-graphtftng-22ffee20bbacbc3378e4ba0df5b7f0c3daaeffc0.tar.gz
vdr-plugin-graphtftng-22ffee20bbacbc3378e4ba0df5b7f0c3daaeffc0.tar.bz2
Diffstat (limited to 'touchthread.c')
-rw-r--r--touchthread.c322
1 files changed, 322 insertions, 0 deletions
diff --git a/touchthread.c b/touchthread.c
new file mode 100644
index 0000000..179e4a6
--- /dev/null
+++ b/touchthread.c
@@ -0,0 +1,322 @@
+/*
+ * touchthread.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ * (c) 2007-2008 Jörg Wendel
+ *
+ * Date: 14.11.2008
+ *
+ * The touch device driver is taken from the
+ * touchTFT plugin written by (c) Frank Simon
+ *
+ */
+
+//***************************************************************************
+// Includes
+//***************************************************************************
+
+#include <linux/input.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+
+#include <unistd.h>
+
+#include <vdr/remote.h>
+#include <vdr/tools.h>
+
+#include "touchthread.h"
+#include "setup.h"
+#include "display.h"
+
+//***************************************************************************
+// Class Touch Thread
+//***************************************************************************
+
+cTouchThread::cTouchThread(void* aDisplay)
+ : cThread("TouchTFT-Thread")
+{
+ display = aDisplay;
+ handle = na;
+ calibrate = no;
+ touchDevice = 0;
+};
+
+cTouchThread::~cTouchThread()
+{
+ Stop();
+ close();
+
+ if (touchDevice) free(touchDevice);
+}
+
+//***************************************************************************
+// Reset Settings
+//***************************************************************************
+
+void cTouchThread::resetSetting(int swap)
+{
+ settings.offsetX = 0;
+ settings.offsetY = 0;
+ settings.scaleX = 1.0;
+ settings.scaleY = 1.0;
+ settings.swapXY = swap;
+ settings.scaleWidth = Thms::theTheme->getWidth();
+ settings.scaleHeight = Thms::theTheme->getHeight();
+}
+
+//***************************************************************************
+// Stop the Thread
+//***************************************************************************
+
+void cTouchThread::Stop()
+{
+ Cancel(3);
+}
+
+//***************************************************************************
+// Device
+//***************************************************************************
+
+void cTouchThread::setDevice(const char* aDevice, int doOpen)
+{
+ if (Str::isEmpty(aDevice))
+ return ;
+
+ if (!touchDevice || strcmp(touchDevice, GraphTFTSetup.touchDevice) != 0)
+ {
+ if (touchDevice) free(touchDevice);
+
+ touchDevice = strdup(GraphTFTSetup.touchDevice);
+
+ if (doOpen)
+ {
+ Cancel(3);
+ close();
+
+ if (open() == success)
+ Start();
+ }
+ }
+}
+
+//***************************************************************************
+// Open / Close
+//***************************************************************************
+
+int cTouchThread::open()
+{
+ if (Str::isEmpty(touchDevice))
+ {
+ tell(0, "Can't open touch device, now device configured");
+ return fail;
+ }
+
+ // open the device ..
+
+ handle = ::open(touchDevice, O_RDWR);
+
+ if (handle < 0)
+ {
+ tell(0, "Error: Opening device '%s' failed, errno was (%d) '%s'",
+ touchDevice, errno, strerror(errno));
+
+ handle = na;
+
+ return fail;
+ }
+
+ tell(0, "Open touch device '%s'", touchDevice);
+
+ return success;
+}
+
+int cTouchThread::close()
+{
+ // wait for Thread exit
+
+ if (isOpen())
+ ::close(handle);
+
+ handle = na;
+ tell(0, "Device '%s' closed", touchDevice);
+
+ return done;
+}
+
+//***************************************************************************
+// Action
+//***************************************************************************
+
+void cTouchThread::Action(void)
+{
+ struct input_event touchdata[sizeBuffer];
+
+ int x = 0;
+ int y = 0;
+ int r = 0;
+ int num = 0;
+ bool touched = no;
+
+ open();
+
+ while (Running())
+ {
+ if (!cFile::FileReady(handle, 100))
+ continue ;
+
+ // read
+
+ r = safe_read(handle, touchdata, sizeof(input_event) * sizeBuffer);
+
+ if (r < 0)
+ {
+ tell(0, "Fatal: Touch device read failed, errno (%d) '%s'",
+ errno, strerror(errno));
+
+ sleep(10);
+ continue ;
+ }
+
+ num = r / sizeof(input_event);
+
+ for (int i = 0; i < num; i++)
+ {
+ switch (touchdata[i].type)
+ {
+ case EV_ABS:
+ {
+ // received a coordinate
+
+ if ((touchdata[i].code == 0 && !settings.swapXY)
+ || (touchdata[i].code != 0 && settings.swapXY))
+ y = touchdata[i].value;
+ else
+ x = touchdata[i].value;
+
+ tell(3, "ABS: (%d/%d)", x, y);
+
+ break;
+ }
+ case EV_KEY:
+ {
+ if (touchdata[i].code == BTN_TOUCH // BTN_TOUCHED
+ || touchdata[i].code == BTN_LEFT) // BTN_LEFT
+ {
+ tell(3, "KEY: value (%d) code (%d)",
+ touchdata[i].value, touchdata[i].code);
+
+ touched = touchdata[i].value != 0;
+ }
+
+ break;
+ }
+
+ case EV_SYN:
+ {
+ // data complete
+
+ if (touched)
+ tell(3, "SYN: (%d/%d) touched (%d)", x, y, touched);
+ else
+ tell(0, "SYN: (%d/%d) released (%d)", x, y, touched);
+
+ processEvent(touched, x, y);
+
+ break;
+ }
+ }
+ }
+ }
+
+ close();
+
+ isyslog("GraphTFT plugin touch-thread thread ended (pid=%d)", getpid());
+ tell(0, "Touch thread ended");
+}
+
+//***************************************************************************
+// Rescale to actual theme size
+//***************************************************************************
+
+void cTouchThread::rescale()
+{
+ if (settings.scaleWidth == Thms::theTheme->getWidth())
+ return ;
+
+ settings.scaleX = (settings.scaleX * (double)Thms::theTheme->getWidth())
+ / settings.scaleWidth;
+ settings.scaleY = (settings.scaleY * (double)Thms::theTheme->getHeight())
+ / settings.scaleHeight;
+
+ settings.scaleWidth = Thms::theTheme->getWidth();
+ settings.scaleHeight = Thms::theTheme->getHeight();
+
+ tell(0, "Rescaled touch calibration to scale values (%f/%f)",
+ settings.scaleX, settings.scaleY);
+
+ ((cGraphTFTDisplay*)display)->calibration.settings = settings;
+ GraphTFTSetup.touchSettings = settings;
+ GraphTFTSetup.Store();
+}
+
+//***************************************************************************
+// Process Event
+//***************************************************************************
+
+void cTouchThread::processEvent(bool touch, int x, int y)
+{
+ static int lastX = 0;
+ static int lastY = 0;
+ static uint64_t lastTouchRelease = 0;
+
+ int flag = 0;
+
+ // check if rescale is required ...
+
+ if (!calibrate && settings.scaleWidth != Thms::theTheme->getWidth())
+ rescale();
+
+ // ignore 'press' events, we triggerd only on 'release' events
+ // -> touch is 0 on release
+
+ if (!touch)
+ {
+ // bounce check
+
+ if (lastTouchRelease + bounceTime <= cTimeMs::Now())
+ {
+ // scale only if not in calibration mode !
+
+ if (!calibrate)
+ {
+ int _x = x;
+ int _y = y;
+
+ x = (int)(((double)(_x + settings.offsetX)) * settings.scaleX);
+ y = (int)(((double)(_y + settings.offsetY)) * settings.scaleY);
+
+ tell(2, "Touch scaled from (%d/%d) to (%d/%d)",
+ _x, _y, x, y);
+ }
+
+ if (cTimeMs::Now() - lastTouchRelease < doubleClickTime
+ && abs(lastX-x) < 20
+ && abs(lastY-y) < 20)
+ {
+ tell(0, "Assuming double-click");
+ flag |= cGraphTftComService::efDoubleClick;
+ }
+
+ ((cGraphTFTDisplay*)display)->mouseEvent(x, y,
+ cGraphTftComService::mbLeft,
+ flag);
+
+ // notice last values
+
+ lastX = x;
+ lastY = y;
+ lastTouchRelease = cTimeMs::Now();
+ }
+ }
+}