]> git.sesse.net Git - kdenlive/commitdiff
jogshuttle: decode events with mediactrl
authorEd Rogalsky <ed.rogalsky@googlemail.com>
Sun, 2 Mar 2014 16:56:15 +0000 (17:56 +0100)
committerEd Rogalsky <ed.rogalsky@googlemail.com>
Sun, 2 Mar 2014 16:56:15 +0000 (17:56 +0100)
mediactrl: taken from kino project (Dan Dennedys
           jogshuttle decoder)

this is the first playing version. code cleanup
and refactoring has to be done

src/jogshuttle.cpp
src/jogshuttle.h
src/lib/external/CMakeLists.txt
src/lib/external/media_ctrl/CMakeLists.txt [new file with mode: 0644]
src/lib/external/media_ctrl/mediactrl.c [new file with mode: 0644]
src/lib/external/media_ctrl/mediactrl.h [new file with mode: 0644]

index 73985e56e9a5ad9d3b1d5d5c170613346d5ea34c..00b0c797393c3370eb227783e906f6b2e6a29553 100644 (file)
@@ -88,35 +88,38 @@ bool ShuttleThread::isWorking()
 void ShuttleThread::run()
 {
        kDebug() << "-------  STARTING SHUTTLE: " << m_device;
+       struct media_ctrl mc;
+    media_ctrl_open2(&mc, m_device.toUtf8().data());
 
-       /* open file descriptor */
-       const int fd = KDE_open((char *) m_device.toUtf8().data(), O_RDONLY);
-       if (fd < 0) {
+    /* open file descriptor */
+       //const int fd = KDE_open((char *) m_device.toUtf8().data(), O_RDONLY);
+       if (mc.fd < 0) {
                perror("Can't open Jog Shuttle FILE DESCRIPTOR");
                return;
        }
 
        EV ev[64];
-
+#if 0
        if (ioctl(fd, EVIOCGRAB, 1) < 0) {
                fprintf(stderr, "Can't get exclusive access on  Jog Shuttle FILE DESCRIPTOR\n");
                close(fd);
                return;
        }
+#endif
 
        fd_set             readset;
        struct timeval timeout;
 
        int num_warnings = 0, readResult = 0;
        int result, iof = -1;
-
+#if 0
        /* get fd settings */
     if ((iof = fcntl(fd, F_GETFL, 0)) == -1) {
         fprintf(stderr, "Can't get Jog Shuttle file status\n");
         close(fd);
         return;
     }
-
+#endif
 #if 0
     else if (fcntl(fd, F_SETFL, iof | O_NONBLOCK) == -1) {
         fprintf(stderr, "Can't set Jog Shuttle FILE DESCRIPTOR to O_NONBLOCK and stop thread\n");
@@ -124,19 +127,20 @@ void ShuttleThread::run()
         return;
     }
 #endif
+    struct media_ctrl_event mev;
 
        /* enter thread loop */
        while (!stop_me) {
                /* reset the read set */
                FD_ZERO(&readset);
-               FD_SET(fd, &readset);
+               FD_SET(mc.fd, &readset);
 
                /* reinit the timeout structure */
                timeout.tv_sec  = 0;
                timeout.tv_usec = 400000; /* 400 ms */
 
                /* do select in blocked mode and wake up after timeout for eval stop_me */
-               result = select(fd+1, &readset, NULL, NULL, &timeout);
+               result = select(mc.fd+1, &readset, NULL, NULL, &timeout);
 
                /* see if there was an error or timeout else process event */
                if (result < 0 && errno == EINTR) {
@@ -152,9 +156,14 @@ void ShuttleThread::run()
                        /* do nothing. reserved for future purposes */
                } else {
                        /* we have input */
-                       if (FD_ISSET(fd, &readset)) {
+                       if (FD_ISSET(mc.fd, &readset)) {
                                /* read input */
-                               readResult = read(fd, ev, sizeof(EV) * 64);
+                           mev.type = MEDIA_CTRL_EVENT_NONE;
+                               //readResult = read(fd, ev, sizeof(EV) * 64);
+                               media_ctrl_read_event(&mc, &mev);
+                /* process event */
+                handle_event(mev);
+#if 0
                                if (readResult < 0) {
                                        if (num_warnings % 10000 == 0) {
                                                /* if device is not available anymore - dead or disconnected */
@@ -185,13 +194,25 @@ void ShuttleThread::run()
                                                handle_event(ev[i]);
                                        }
                                }
+#endif
                        }
                }
        }
 
     kDebug() << "-------  STOPPING SHUTTLE: ";
        /* close the handle and return thread */
-       close(fd);
+       //close(fd);
+    media_ctrl_close(&mc);
+}
+
+void ShuttleThread::handle_event(struct media_ctrl_event ev)
+{
+    if (ev.type == MEDIA_CTRL_EVENT_KEY)
+        key(ev);
+    else if (ev.type == MEDIA_CTRL_EVENT_JOG)
+        jog(ev);
+    else if (ev.type == MEDIA_CTRL_EVENT_SHUTTLE)
+        shuttle(ev);
 }
 
 void ShuttleThread::handle_event(EV ev)
@@ -209,6 +230,14 @@ void ShuttleThread::handle_event(EV ev)
     }
 }
 
+void ShuttleThread::key(struct media_ctrl_event ev)
+{
+    if (ev.value == KEY_PRESS) {
+        int code = ev.index + 1;
+        QApplication::postEvent(m_parent, new QEvent((QEvent::Type)(KEY_EVENT_OFFSET + code)));
+    }
+}
+
 void ShuttleThread::key(unsigned short code, unsigned int value)
 {
     if (value == 0) {
@@ -226,6 +255,11 @@ void ShuttleThread::key(unsigned short code, unsigned int value)
 
 }
 
+void ShuttleThread::shuttle(struct media_ctrl_event ev)
+{
+    QApplication::postEvent(m_parent, new QEvent((QEvent::Type) (JOG_STOP + (ev.value/2))));
+}
+
 void ShuttleThread::shuttle(int value)
 {
     //gettimeofday( &last_shuttle, 0 );
@@ -245,6 +279,14 @@ void ShuttleThread::shuttle(int value)
     QApplication::postEvent(m_parent, new QEvent((QEvent::Type) (JOG_STOP + value)));
 }
 
+void ShuttleThread::jog(struct media_ctrl_event ev)
+{
+    if (ev.value < 0)
+        QApplication::postEvent(m_parent, new QEvent((QEvent::Type) JOG_BACK1));
+    else if (ev.value > 0)
+        QApplication::postEvent(m_parent, new QEvent((QEvent::Type) JOG_FWD1));
+}
+
 void ShuttleThread::jog(unsigned int value)
 {
     // generate a synthetic event for the shuttle going
index d1cf185b3a22941499e303f74897920ce71a5844..dbcd179ee1999ced0e5d8282ce4e59a8e33b926c 100644 (file)
@@ -26,7 +26,8 @@
 #include <QMap>
 
 #include <linux/input.h>
-
+#include <sys/time.h>
+#include "lib/external/media_ctrl/mediactrl.h"
 
 typedef struct input_event EV;
 
@@ -47,9 +48,13 @@ public:
 private:
     bool m_isWorking;
     void handle_event(EV ev);
+    void handle_event(struct media_ctrl_event ev);
+    void jog(struct media_ctrl_event ev);
     void jog(unsigned int value);
     void shuttle(int value);
+    void shuttle(struct media_ctrl_event ev);
     void key(unsigned short code, unsigned int value);
+    void key(struct media_ctrl_event ev);
 };
 
 typedef QMap<QString, QString> DeviceMap;
index 978e5a69375449280c52a66eb9fb3465f5cfcc38..066bd4dd88e9411c20f22f46add9c1a78c18aa81 100644 (file)
@@ -1,5 +1,6 @@
 
 add_subdirectory(kiss_fft)
+add_subdirectory(media_ctrl)
 
 set(kdenlive_SRCS
   ${kdenlive_SRCS}
diff --git a/src/lib/external/media_ctrl/CMakeLists.txt b/src/lib/external/media_ctrl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6de4a0c
--- /dev/null
@@ -0,0 +1,18 @@
+set(kdenlive_SRCS
+  ${kdenlive_SRCS}
+  lib/external/media_ctrl/mediactrl.h
+  lib/external/media_ctrl/mediactrl.c
+  PARENT_SCOPE
+)
+
+
+# Create a static library from kiss_fft
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --std=c99")
+include_directories(
+  ${CMAKE_BINARY_DIR}
+)
+add_library(media_ctrl STATIC
+  mediactrl.h
+  mediactrl.c
+)
diff --git a/src/lib/external/media_ctrl/mediactrl.c b/src/lib/external/media_ctrl/mediactrl.c
new file mode 100644 (file)
index 0000000..4ca6527
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+* mediactrl.c -- Jog Shuttle device support
+* Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <asm/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <linux/input.h>
+#include "mediactrl.h"
+
+
+static char *_shuttle_name = "Shuttle";
+static char *_jog_name = "Jog";
+
+/*
+       ShuttlePro keys
+*/
+static struct  media_ctrl_key mc_shuttle_pro_keys[] = {
+       { 0x100, "Button 1", MEDIA_CTRL_F1 },
+       { 0x101, "Button 2", MEDIA_CTRL_F2 },
+       { 0x102, "Button 3", MEDIA_CTRL_F3 },
+       { 0x103, "Button 4", MEDIA_CTRL_F4 },
+       { 0x104, "Button 5", MEDIA_CTRL_B4 },
+       { 0x105, "Button 6", MEDIA_CTRL_B2 },
+       { 0x106, "Button 7", MEDIA_CTRL_B1 },
+       { 0x107, "Button 8", MEDIA_CTRL_B3 },
+       { 0x108, "Button 9", MEDIA_CTRL_B5 },
+       { 0x109, "Button 10", MEDIA_CTRL_B6 },
+       { 0x10a, "Button 11", MEDIA_CTRL_B7 },
+       { 0x10b, "Button 12", MEDIA_CTRL_B8 },
+       { 0x10c, "Button 13", MEDIA_CTRL_B9 },
+       { 0, NULL, 0 }
+};
+
+
+/*
+       ShuttleXPress keys
+*/
+static struct  media_ctrl_key _mc_shuttle_xpress_keys[] = {
+    { 0x104, "Button B4", MEDIA_CTRL_B4 },
+    { 0x105, "Button B2", MEDIA_CTRL_B2 },
+    { 0x106, "Button B1", MEDIA_CTRL_B1 },
+    { 0x107, "Button B3", MEDIA_CTRL_B3 },
+    { 0x108, "Button B5", MEDIA_CTRL_B5 },
+    { 0, NULL, 0 }
+};
+
+static struct  media_ctrl_key mc_shuttle_xpress_keys[] = {
+    { 0x104, "Button B1", MEDIA_CTRL_B1},
+    { 0x105, "Button B2", MEDIA_CTRL_B2 },
+    { 0x106, "Button B3", MEDIA_CTRL_B3 },
+    { 0x107, "Button B4", MEDIA_CTRL_B4 },
+    { 0x108, "Button B5", MEDIA_CTRL_B5 },
+    { 0, NULL, 0 }
+};
+
+
+
+/*
+       JLCooper MCS3 Keys
+*/
+static struct  media_ctrl_key mc_jlcooper_mcs3_keys[] = {
+       { 0x107, "F1", MEDIA_CTRL_F1 },
+       { 0x101, "F2", MEDIA_CTRL_F2 },
+       { 0x105, "F3", MEDIA_CTRL_F3 },
+       { 0x102, "F4", MEDIA_CTRL_F4 },
+       { 0x103, "F5", MEDIA_CTRL_F5 },
+       { 0x104, "F6", MEDIA_CTRL_F6 },
+       { 0x10d, "W1", MEDIA_CTRL_B6 },
+       { 0x10e, "W2", MEDIA_CTRL_B4 },
+       { 0x100, "W3", MEDIA_CTRL_B2 },
+       { 0x106, "W4", MEDIA_CTRL_B1 },
+       { 0x110, "W5", MEDIA_CTRL_B3 },
+       { 0x111, "W6", MEDIA_CTRL_B5 },
+       { 0x115, "W7", MEDIA_CTRL_B7 },
+       { 0x116, "STICK_LEFT", MEDIA_CTRL_STICK_LEFT },
+       { 0x113, "STICK_RIGHT", MEDIA_CTRL_STICK_RIGHT },
+       { 0x114, "STICK_UP", MEDIA_CTRL_STICK_UP },
+       { 0x112, "STICK_DOWN", MEDIA_CTRL_STICK_DOWN },
+       { 0x10f, "Rewind", MEDIA_CTRL_REWIND },
+       { 0x108, "Fast Forward", MEDIA_CTRL_FAST_FORWARD },
+       { 0x109, "Stop", MEDIA_CTRL_STOP },
+       { 0x10a, "Play", MEDIA_CTRL_PLAY },
+       { 0x10b, "Record", MEDIA_CTRL_RECORD },
+       { 0, NULL, 0 }
+};
+
+
+/*
+       Griffin PowerMate
+*/
+static struct media_ctrl_key mc_powermate_keys[] = {
+       { BTN_0, "Button", MEDIA_CTRL_B1 },
+       { 0, NULL, 0 }
+};
+
+
+/*
+       X-Keys Jog/Shuttle
+*/
+static struct  media_ctrl_key mc_x_keys[] = {
+       { 0x102, "Button L1", MEDIA_CTRL_F1 },
+       { 0x103, "Button L2", MEDIA_CTRL_F9 },
+       { 0x104, "Button L3", MEDIA_CTRL_B1 },
+       { 0x105, "Button L4", MEDIA_CTRL_B3 },
+       { 0x106, "Button L5", MEDIA_CTRL_B5 },
+       { 0x10a, "Button L6", MEDIA_CTRL_F2 },
+       { 0x10b, "Button L7", MEDIA_CTRL_F10 },
+       { 0x10c, "Button L8", MEDIA_CTRL_B2 },
+       { 0x10d, "Button L9", MEDIA_CTRL_B4 },
+       { 0x10e, "Button L10", MEDIA_CTRL_B6 },
+       { 0x112, "Button C1", MEDIA_CTRL_F3 },
+       { 0x11a, "Button C2", MEDIA_CTRL_F4 },
+       { 0x122, "Button C3", MEDIA_CTRL_F5 },
+       { 0x12a, "Button C4", MEDIA_CTRL_F6 },
+       { 0x113, "Button C5", MEDIA_CTRL_F11 },
+       { 0x11b, "Button C6", MEDIA_CTRL_F12 },
+       { 0x123, "Button C7", MEDIA_CTRL_F13 },
+       { 0x12b, "Button C8", MEDIA_CTRL_F14 },
+       { 0x132, "Button R1", MEDIA_CTRL_F7 },
+       { 0x133, "Button R2", MEDIA_CTRL_F15 },
+       { 0x134, "Button R3", MEDIA_CTRL_B7 },
+       { 0x135, "Button R4", MEDIA_CTRL_B9 },
+       { 0x136, "Button R5", MEDIA_CTRL_B11 },
+       { 0x13a, "Button R6", MEDIA_CTRL_F8 },
+       { 0x13b, "Button R7", MEDIA_CTRL_F16 },
+       { 0x13c, "Button R8", MEDIA_CTRL_B8 },
+       { 0x13d, "Button R9", MEDIA_CTRL_B10 },
+       { 0x13e, "Button R10", MEDIA_CTRL_B12 },
+       { 0, NULL, 0 }
+};
+
+struct  media_ctrl_key *media_ctrl_get_key(struct media_ctrl *ctrl, int code, int *index)
+{
+       int i = 0;
+       struct media_ctrl_key *keys = ctrl->device->keys;
+       
+       while ( keys[i].key != 0 ) {
+               if (keys[i].key == code) {
+                       if (index != NULL)
+                               *index = i;
+                       return &keys[i];
+               }
+               i++;
+       }
+       
+       return NULL;
+}
+
+
+void translate_contour_hid_event(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
+{
+       
+       int lv, cv;
+       
+       me->type = 0;
+       
+       if (ev->type == EV_REL) {
+               /* First check the outer dial */
+               if (ev->code == REL_WHEEL) {
+                       
+                       cv = (signed int)ev->value;
+                       if (cv == 1 || cv == -1 ) cv = 0;
+                       
+                               
+                       if ( cv == ctrl->lastshu ) return;
+            ctrl->lastshu = cv;
+
+            if ( cv > 0 ) cv -= 1;
+            if ( cv < 0) cv += 1;
+
+                       //printf("Shuttle: %d\n", cv);
+                       me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
+                       me->value = cv*2;
+                       me->name = _shuttle_name;
+                       
+               } else if  (ev->code == REL_DIAL) {
+                       
+                       if ( ctrl->lastval == -1 ) ctrl->lastval = ev->value;
+                       lv = ctrl->lastval;
+                       cv = ev->value;
+
+                       if ( lv == cv ) return;
+                               
+                       ctrl->lastval = cv;
+                       
+                       if (cv < 10 && lv > 0xF0) cv +=0x100;
+                       if (lv < 10 && cv > 0xF0) lv +=0x100;
+                       
+                       me->type  = MEDIA_CTRL_EVENT_JOG;
+                       me->value = cv-lv;
+                       me->name = _jog_name;
+                       
+                       ctrl->jogpos += me->value;
+                       //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
+               }
+               return;
+       } else if (ev->type == EV_KEY) {
+               int index;
+               struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
+               if ( key == NULL ) return;
+               
+               me->type  = MEDIA_CTRL_EVENT_KEY;
+               me->code = key->code;
+               me->value = ev->value;
+               me->name = ( char* )key->name;
+               me->index = index;
+                
+               //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
+               
+       }
+       
+}
+
+void translate_compliant(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
+{
+       me->type = 0;
+       
+       // printf("Translate %02x %02x\n", ev->type, ev->code );
+       
+       if (ev->type == EV_REL) {
+               if  (ev->code == REL_DIAL) {
+                       
+                       me->type  = MEDIA_CTRL_EVENT_JOG;
+                       me->value = (signed int)ev->value;
+                       me->name = _jog_name;
+                       
+                       ctrl->jogpos += me->value;
+                       //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
+       }
+               return;
+       } else if (ev->type == EV_ABS) {
+               // printf("ABS\n" );
+               if  ( ev->code == 0x1c || ev->code == ABS_THROTTLE ) {
+                       //printf("ABS_MISC\n" );
+                       me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
+                       me->value = (signed int)ev->value;
+                       me->name = _shuttle_name;
+                       
+                       ctrl->shuttlepos = me->value;
+                       //printf("Shuttle: %06d (%d)\n", ctrl->shuttlepos, me->value);
+               }
+       } else if (ev->type == EV_KEY) {
+               int index;
+               struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
+               if ( key == NULL ) return;
+               
+               me->type  = MEDIA_CTRL_EVENT_KEY;
+               me->code = key->code;
+               me->value = ev->value;
+               me->name = ( char* )key->name;
+               me->index = index;
+                
+               //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
+               
+       }
+}
+
+struct media_ctrl_device supported_devices[] = {
+       { 0x0b33, 0x0030, "Contour ShuttlePRO v2", mc_shuttle_pro_keys, translate_contour_hid_event },
+       { 0x0b33, 0x0020, "Contour ShuttleXPress", mc_shuttle_xpress_keys, translate_contour_hid_event },
+       { 0x0b33, 0x0010, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
+       { 0x0b33, 0x0011, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event }, /* Hercules OEM */
+       { 0x05f3, 0x0240, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
+       { 0x0760, 0x0001, "JLCooper MCS3", mc_jlcooper_mcs3_keys, translate_compliant },
+       { 0x077d, 0x0410, "Griffin PowerMate", mc_powermate_keys, translate_compliant },
+       { 0x05f3, 0x0241, "X-Keys Editor", mc_x_keys, translate_contour_hid_event },
+       { 0, 0, 0 }
+};
+
+
+void media_ctrl_translate(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
+{
+       if ( ctrl->device ) ctrl->device->translate(ctrl, ev, me);
+}
+
+
+void media_ctrl_read_event(struct media_ctrl *ctrl, struct media_ctrl_event *me) 
+{
+       ssize_t n;
+       struct input_event ev;
+               
+       // struct media_ctrl_event me;
+       
+       if ( ctrl->fd > 0 ) {
+               n = read(ctrl->fd, &ev, sizeof(ev));
+       } else {
+               return;
+       }
+       
+       if (n != sizeof(ev)) {
+               //printf("JogShuttle::inputCallback: read: (%d) %s\n", errno, strerror(errno));
+               close(ctrl->fd);
+               ctrl->fd = 0;
+               return;
+       }
+       
+       if ( ctrl->device && ctrl->device->translate)
+               ctrl->device->translate(ctrl, &ev, me);
+       else
+               me->type = 0;
+       
+       if ( me->type  == MEDIA_CTRL_EVENT_JOG ) {
+               struct timeval timev;
+               gettimeofday(&timev, NULL);
+               unsigned long now = (unsigned long)timev.tv_usec + (1000000*(unsigned long)timev.tv_sec);
+               if ( now < ctrl->last_jog_time + 40000 ) {
+                       //printf("*** Fast Jog %02d %05d ***\n", me->value, now - ctrl->last_jog_time);
+                       ctrl->jogrel = me->value;
+                       me->type = MEDIA_CTRL_EVENT_NONE;
+               } else {
+                       me->value += ctrl->jogrel;
+                       ctrl->jogrel = 0;
+                       ctrl->last_jog_time = now;
+                       // printf("*** Jog %02d ***\n", me->value);
+               }
+       }
+       
+       return;
+       
+}
+
+
+int probe_device(struct media_ctrl *mc)
+{
+       short devinfo[4];
+       int i = 0;
+         
+       if ( ioctl(mc->fd, EVIOCGID, &devinfo) ) {
+               perror("evdev ioctl");
+               return 0;
+       }
+       
+       do {
+               if ( supported_devices[i].vendor == devinfo[1] 
+                       && supported_devices[i].product == devinfo[2] ) {
+                               
+                       mc->device = &supported_devices[i];
+                       //printf("Success on /dev/input/event%d: %s\n", mc->eventno, mc->device->name);
+                       // mc->fd = fd;
+                       // mc->translate = mc->device.translate_function;
+                       // mc = malloc(sizeof(struct media_ctrl));
+                       mc->jogpos  = 0;
+                       mc->lastval = -1;
+                       mc->last_jog_time = 0;
+                       return 1;
+               } else {
+                       //mc->device = NULL;
+               }
+       
+       } while ( supported_devices[++i].vendor != 0 );
+                       
+       return 0;
+}
+
+
+void media_ctrl_get_device_list() 
+{
+       // TBD
+}
+
+
+
+void find_first_device(struct media_ctrl *mc) 
+{
+       char buf[256];
+       int fd, i;
+       
+       for ( i = 0; i < 32; i++ ) {
+               sprintf(buf, "/dev/input/event%d", i); 
+               fd = open( buf, O_RDONLY );
+               if ( fd < 0 ) {
+                       perror(buf);
+               } else {
+                       mc->fd = fd;
+                       mc->eventno = i;
+                       if( probe_device(mc) ) {
+                               return;
+                       } else {                
+                               close(fd);
+                               mc->fd = -1;
+                       }
+               }
+       }
+       return;
+}
+
+
+void media_ctrl_close(struct media_ctrl *mc)
+{
+       if (mc->fd > 0)
+               close( mc->fd );
+       memset( mc, 0, sizeof( struct media_ctrl ) );
+}
+
+
+void media_ctrl_open(struct media_ctrl *mc) 
+{
+       find_first_device(mc);
+}
+
+void media_ctrl_open2(struct media_ctrl *mc, const char *devname)
+{
+    int fd;
+
+    fd = open( devname, O_RDONLY );
+    if ( fd < 0 ) {
+        perror(devname);
+    } else {
+        mc->fd = fd;
+        //mc->eventno = i;
+        if( probe_device(mc) ) {
+            return;
+        } else {
+            close(fd);
+            mc->fd = -1;
+        }
+    }
+}
+
diff --git a/src/lib/external/media_ctrl/mediactrl.h b/src/lib/external/media_ctrl/mediactrl.h
new file mode 100644 (file)
index 0000000..652b4ff
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+* mediactrl.c -- Jog Shuttle device support
+* Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _MEDIA_CTRL_H
+#define _MEDIA_CTRL_H
+
+
+// just to make the code more readable
+#define KEY_RELEASE                    0x00
+#define KEY_PRESS                      0x01
+
+// not used yet
+#define MEDIA_ST_ACTIVE                        0x02
+#define MEDIA_ST_INACTIVE              0x01
+
+// media ctrl event types
+#define MEDIA_CTRL_EVENT_NONE          0x00
+#define MEDIA_CTRL_EVENT_KEY           0x01
+#define MEDIA_CTRL_EVENT_JOG           0x02
+#define MEDIA_CTRL_EVENT_SHUTTLE       0x03
+#define MEDIA_CTRL_EVENT_STICK         0x04
+
+// the disconnect event - not used yet
+#define MEDIA_CTRL_DISCONNECT          0x01
+
+#define MEDIA_CTRL_SHIFT               0x01
+
+#define MEDIA_CTRL_PLAY                        0x10
+#define MEDIA_CTRL_PLAY_FWD            0x10
+#define MEDIA_CTRL_REVERSE             0x11
+#define MEDIA_CTRL_PLAY_REV            0x11
+#define MEDIA_CTRL_STOP                0x12
+#define MEDIA_CTRL_PAUSE               0x13
+#define MEDIA_CTRL_NEXT                0x14
+#define MEDIA_CTRL_PREV                0x15
+#define MEDIA_CTRL_RECORD              0x16
+#define MEDIA_CTRL_FAST_FORWARD                0x17
+#define MEDIA_CTRL_REWIND              0x18
+
+#define MEDIA_CTRL_STICK_LEFT          0x20
+#define MEDIA_CTRL_STICK_RIGHT         0x21
+#define MEDIA_CTRL_STICK_UP            0x22
+#define MEDIA_CTRL_STICK_DOWN          0x23
+
+/* function keys, usually at top of device */
+#define MEDIA_CTRL_F1                  0x100
+#define MEDIA_CTRL_F2                  0x101
+#define MEDIA_CTRL_F3                  0x102
+#define MEDIA_CTRL_F4                  0x103
+#define MEDIA_CTRL_F5                  0x104
+#define MEDIA_CTRL_F6                  0x105
+#define MEDIA_CTRL_F7                  0x106
+#define MEDIA_CTRL_F8                  0x107
+#define MEDIA_CTRL_F9                  0x108
+#define MEDIA_CTRL_F10                 0x109
+#define MEDIA_CTRL_F11                 0x10a
+#define MEDIA_CTRL_F12                 0x10b
+#define MEDIA_CTRL_F13                 0x10c
+#define MEDIA_CTRL_F14                 0x10d
+#define MEDIA_CTRL_F15                 0x10e
+#define MEDIA_CTRL_F16                 0x10f
+
+#define MEDIA_CTRL_B1                  0x110
+#define MEDIA_CTRL_B2                  0x111
+#define MEDIA_CTRL_B3                  0x112
+#define MEDIA_CTRL_B4                  0x113
+#define MEDIA_CTRL_B5                  0x114
+#define MEDIA_CTRL_B6                  0x115
+#define MEDIA_CTRL_B7                  0x116
+#define MEDIA_CTRL_B8                  0x117
+#define MEDIA_CTRL_B9                  0x118
+#define MEDIA_CTRL_B10                 0x119
+#define MEDIA_CTRL_B11                 0x11a
+#define MEDIA_CTRL_B12                 0x11b
+#define MEDIA_CTRL_B13                 0x11c
+#define MEDIA_CTRL_B14                 0x11d
+#define MEDIA_CTRL_B15                 0x11e
+#define MEDIA_CTRL_B16                 0x11f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct media_ctrl_device;
+
+struct media_ctrl_key {
+       int key;  // internal keycode - do not use
+       const char *name;
+       int code; // eventcode
+       int action;
+};
+
+struct media_ctrl_event {
+       struct timeval time;
+       unsigned short type;
+       unsigned short code;
+       char *name;
+       int value;
+       unsigned short index;
+};
+
+struct media_ctrl {
+       
+       int fd;
+       int eventno;
+       
+       int status;
+
+       struct media_ctrl_device *device;
+
+       long jogpos;
+       int  shuttlepos;
+       
+       int lastval;
+       int lastshu;
+       
+       int jogrel; // accumulate relative values if events come too fast
+       unsigned long last_jog_time; // last jog event
+
+};
+
+struct media_ctrl_device {
+       int vendor;
+       int product;
+       const char *name;
+       struct media_ctrl_key *keys;
+       void (*translate)(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me);
+};
+
+void media_ctrl_open(struct media_ctrl *);
+void media_ctrl_open2(struct media_ctrl *, const char *devname);
+void media_ctrl_close(struct media_ctrl *);
+void media_ctrl_read_event(struct media_ctrl *, struct media_ctrl_event *);
+
+struct  media_ctrl_key *media_ctrl_get_keys(struct media_ctrl *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif