Warning, file /multimedia/kdenlive/src/lib/external/media_ctrl/mediactrl.c was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     mediactrl.c -- Jog Shuttle device support
0003     SPDX-FileCopyrightText: 2001-2007 Dan Dennedy <dan@dennedy.org>
0004 
0005     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include <asm/types.h>
0009 #include <errno.h>
0010 #include <fcntl.h>
0011 #include <stdint.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <sys/ioctl.h>
0016 #include <sys/stat.h>
0017 #include <sys/time.h>
0018 #if defined(Q_OS_LINUX)
0019 #include <asm/types.h>
0020 #endif
0021 #include <fcntl.h>
0022 #include <unistd.h>
0023 
0024 #include "mediactrl.h"
0025 
0026 static char *_shuttle_name = (char *)"Shuttle";
0027 static char *_jog_name = (char *)"Jog";
0028 
0029 /*
0030         ShuttlePro v2 keys
0031 */
0032 static struct media_ctrl_key mc_shuttle_pro_v2_keys[] = {
0033     {0x100, "Button 1", MEDIA_CTRL_F1},  {0x101, "Button 2", MEDIA_CTRL_F2},   {0x102, "Button 3", MEDIA_CTRL_F3},   {0x103, "Button 4", MEDIA_CTRL_F4},
0034     {0x104, "Button 5", MEDIA_CTRL_B1},  {0x105, "Button 6", MEDIA_CTRL_B2},   {0x106, "Button 7", MEDIA_CTRL_B3},   {0x107, "Button 8", MEDIA_CTRL_B4},
0035     {0x108, "Button 9", MEDIA_CTRL_B5},  {0x109, "Button 10", MEDIA_CTRL_B6},  {0x10a, "Button 11", MEDIA_CTRL_B7},  {0x10b, "Button 12", MEDIA_CTRL_B8},
0036     {0x10c, "Button 13", MEDIA_CTRL_B9}, {0x10d, "Button 14", MEDIA_CTRL_B10}, {0x10e, "Button 15", MEDIA_CTRL_B11}, {0, NULL, 0}};
0037 
0038 /*
0039     ShuttlePro keys
0040 */
0041 static struct media_ctrl_key mc_shuttle_pro_keys[] = {{0x100, "Button 1", MEDIA_CTRL_F1},  {0x101, "Button 2", MEDIA_CTRL_F2},
0042                                                       {0x102, "Button 3", MEDIA_CTRL_F3},  {0x103, "Button 4", MEDIA_CTRL_F4},
0043                                                       {0x104, "Button 5", MEDIA_CTRL_B4},  {0x105, "Button 6", MEDIA_CTRL_B2},
0044                                                       {0x106, "Button 7", MEDIA_CTRL_B1},  {0x107, "Button 8", MEDIA_CTRL_B3},
0045                                                       {0x108, "Button 9", MEDIA_CTRL_B5},  {0x109, "Button 10", MEDIA_CTRL_B6},
0046                                                       {0x10a, "Button 11", MEDIA_CTRL_B7}, {0x10b, "Button 12", MEDIA_CTRL_B8},
0047                                                       {0x10c, "Button 13", MEDIA_CTRL_B9}, {0, NULL, 0}};
0048 
0049 /*
0050         ShuttleXPress keys
0051 */
0052 static struct media_ctrl_key mc_shuttle_xpress_keys[] = {{0x104, "Button B1", MEDIA_CTRL_B1}, {0x105, "Button B2", MEDIA_CTRL_B2},
0053                                                          {0x106, "Button B3", MEDIA_CTRL_B3}, {0x107, "Button B4", MEDIA_CTRL_B4},
0054                                                          {0x108, "Button B5", MEDIA_CTRL_B5}, {0, NULL, 0}};
0055 
0056 /*
0057         JLCooper MCS3 Keys
0058 */
0059 static struct media_ctrl_key mc_jlcooper_mcs3_keys[] = {{0x107, "F1", MEDIA_CTRL_F1},
0060                                                         {0x101, "F2", MEDIA_CTRL_F2},
0061                                                         {0x105, "F3", MEDIA_CTRL_F3},
0062                                                         {0x102, "F4", MEDIA_CTRL_F4},
0063                                                         {0x103, "F5", MEDIA_CTRL_F5},
0064                                                         {0x104, "F6", MEDIA_CTRL_F6},
0065                                                         {0x10d, "W1", MEDIA_CTRL_B6},
0066                                                         {0x10e, "W2", MEDIA_CTRL_B4},
0067                                                         {0x100, "W3", MEDIA_CTRL_B2},
0068                                                         {0x106, "W4", MEDIA_CTRL_B1},
0069                                                         {0x110, "W5", MEDIA_CTRL_B3},
0070                                                         {0x111, "W6", MEDIA_CTRL_B5},
0071                                                         {0x115, "W7", MEDIA_CTRL_B7},
0072                                                         {0x116, "STICK_LEFT", MEDIA_CTRL_STICK_LEFT},
0073                                                         {0x113, "STICK_RIGHT", MEDIA_CTRL_STICK_RIGHT},
0074                                                         {0x114, "STICK_UP", MEDIA_CTRL_STICK_UP},
0075                                                         {0x112, "STICK_DOWN", MEDIA_CTRL_STICK_DOWN},
0076                                                         {0x10f, "Rewind", MEDIA_CTRL_REWIND},
0077                                                         {0x108, "Fast Forward", MEDIA_CTRL_FAST_FORWARD},
0078                                                         {0x109, "Stop", MEDIA_CTRL_STOP},
0079                                                         {0x10a, "Play", MEDIA_CTRL_PLAY},
0080                                                         {0x10b, "Record", MEDIA_CTRL_RECORD},
0081                                                         {0, NULL, 0}};
0082 
0083 /*
0084         Griffin PowerMate
0085 */
0086 static struct media_ctrl_key mc_powermate_keys[] = {{BTN_0, "Button", MEDIA_CTRL_B1}, {0, NULL, 0}};
0087 
0088 /*
0089         X-Keys Jog/Shuttle
0090 */
0091 static struct media_ctrl_key mc_x_keys[] = {{0x102, "Button L1", MEDIA_CTRL_F1},
0092                                             {0x103, "Button L2", MEDIA_CTRL_F9},
0093                                             {0x104, "Button L3", MEDIA_CTRL_B1},
0094                                             {0x105, "Button L4", MEDIA_CTRL_B3},
0095                                             {0x106, "Button L5", MEDIA_CTRL_B5},
0096                                             {0x10a, "Button L6", MEDIA_CTRL_F2},
0097                                             {0x10b, "Button L7", MEDIA_CTRL_F10},
0098                                             {0x10c, "Button L8", MEDIA_CTRL_B2},
0099                                             {0x10d, "Button L9", MEDIA_CTRL_B4},
0100                                             {0x10e, "Button L10", MEDIA_CTRL_B6},
0101                                             {0x112, "Button C1", MEDIA_CTRL_F3},
0102                                             {0x11a, "Button C2", MEDIA_CTRL_F4},
0103                                             {0x122, "Button C3", MEDIA_CTRL_F5},
0104                                             {0x12a, "Button C4", MEDIA_CTRL_F6},
0105                                             {0x113, "Button C5", MEDIA_CTRL_F11},
0106                                             {0x11b, "Button C6", MEDIA_CTRL_F12},
0107                                             {0x123, "Button C7", MEDIA_CTRL_F13},
0108                                             {0x12b, "Button C8", MEDIA_CTRL_F14},
0109                                             {0x132, "Button R1", MEDIA_CTRL_F7},
0110                                             {0x133, "Button R2", MEDIA_CTRL_F15},
0111                                             {0x134, "Button R3", MEDIA_CTRL_B7},
0112                                             {0x135, "Button R4", MEDIA_CTRL_B9},
0113                                             {0x136, "Button R5", MEDIA_CTRL_B11},
0114                                             {0x13a, "Button R6", MEDIA_CTRL_F8},
0115                                             {0x13b, "Button R7", MEDIA_CTRL_F16},
0116                                             {0x13c, "Button R8", MEDIA_CTRL_B8},
0117                                             {0x13d, "Button R9", MEDIA_CTRL_B10},
0118                                             {0x13e, "Button R10", MEDIA_CTRL_B12},
0119                                             {0, NULL, 0}};
0120 
0121 struct media_ctrl_key *media_ctrl_get_key(struct media_ctrl *ctrl, int code, int *index)
0122 {
0123     int i = 0;
0124     struct media_ctrl_key *keys = ctrl->device->keys;
0125 
0126     while (keys[i].key != 0) {
0127         if (keys[i].key == code) {
0128             if (index != NULL) *index = i;
0129             return &keys[i];
0130         }
0131         i++;
0132     }
0133 
0134     return NULL;
0135 }
0136 
0137 int media_ctrl_get_keys_count(struct media_ctrl *ctrl)
0138 {
0139     int i = 0;
0140     struct media_ctrl_key *keys = ctrl->device->keys;
0141 
0142     while (keys[i].key != 0) {
0143         i++;
0144     }
0145 
0146     return i;
0147 }
0148 
0149 void translate_contour_hid_event(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me)
0150 {
0151     me->type = 0;
0152 
0153     if (ev->type == EV_REL) {
0154         int cv;
0155         /* First check the outer dial */
0156         if (ev->code == REL_WHEEL) {
0157 
0158             cv = (signed int)ev->value;
0159             if (cv == 1 || cv == -1) cv = 0;
0160 
0161             if (cv == ctrl->lastshu) return;
0162             ctrl->lastshu = cv;
0163 
0164             /* TODO: review this change */
0165             if (cv > 0) cv -= 1;
0166             if (cv < 0) cv += 1;
0167 
0168             // printf("Shuttle: %d\n", cv);
0169             me->type = MEDIA_CTRL_EVENT_SHUTTLE;
0170             me->value = cv * 2;
0171             me->name = _shuttle_name;
0172 
0173         } else if (ev->code == REL_DIAL) {
0174             int lv;
0175 
0176             if (ctrl->lastval == -1) ctrl->lastval = ev->value;
0177             lv = ctrl->lastval;
0178             cv = ev->value;
0179 
0180             if (lv == cv) return;
0181 
0182             ctrl->lastval = cv;
0183 
0184             if (cv < 10 && lv > 0xF0) cv += 0x100;
0185             if (lv < 10 && cv > 0xF0) lv += 0x100;
0186 
0187             me->type = MEDIA_CTRL_EVENT_JOG;
0188             me->value = cv - lv;
0189             me->name = _jog_name;
0190 
0191             ctrl->jogpos += me->value;
0192             // printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
0193         }
0194         return;
0195     }
0196     if (ev->type == EV_KEY) {
0197         int index;
0198         struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
0199         if (key == NULL) return;
0200 
0201         me->type = MEDIA_CTRL_EVENT_KEY;
0202         me->code = key->code;
0203         me->value = ev->value;
0204         me->name = (char *)key->name;
0205         me->index = index;
0206 
0207         // printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
0208     }
0209 }
0210 
0211 void translate_compliant(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me)
0212 {
0213     me->type = 0;
0214 
0215     // printf("Translate %02x %02x\n", ev->type, ev->code );
0216 
0217     if (ev->type == EV_REL) {
0218         if (ev->code == REL_DIAL) {
0219 
0220             me->type = MEDIA_CTRL_EVENT_JOG;
0221             me->value = (signed int)ev->value;
0222             me->name = _jog_name;
0223 
0224             ctrl->jogpos += me->value;
0225             // printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
0226         }
0227         return;
0228     }
0229     if (ev->type == EV_ABS) {
0230         // printf("ABS\n" );
0231         if (ev->code == 0x1c || ev->code == ABS_THROTTLE) {
0232             // printf("ABS_MISC\n" );
0233             me->type = MEDIA_CTRL_EVENT_SHUTTLE;
0234             me->value = (signed int)ev->value;
0235             me->name = _shuttle_name;
0236 
0237             ctrl->shuttlepos = me->value;
0238             // printf("Shuttle: %06d (%d)\n", ctrl->shuttlepos, me->value);
0239         }
0240     } else if (ev->type == EV_KEY) {
0241         int index;
0242         struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
0243         if (key == NULL) return;
0244 
0245         me->type = MEDIA_CTRL_EVENT_KEY;
0246         me->code = key->code;
0247         me->value = ev->value;
0248         me->name = (char *)key->name;
0249         me->index = index;
0250 
0251         // printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
0252     }
0253 }
0254 
0255 struct media_ctrl_device supported_devices[] = {
0256     {0x0b33, 0x0030, "Contour Design ShuttlePRO v2", mc_shuttle_pro_v2_keys, translate_contour_hid_event},
0257     {0x0b33, 0x0020, "Contour Design ShuttleXpress", mc_shuttle_xpress_keys, translate_contour_hid_event},
0258     {0x0b33, 0x0010, "Contour Design ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event},
0259     {0x0b33, 0x0011, "Contour Design ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event}, /* Hercules OEM */
0260     {0x05f3, 0x0240, "Contour Design ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event},
0261     {0x0760, 0x0001, "JLCooper MCS3", mc_jlcooper_mcs3_keys, translate_compliant},
0262     {0x077d, 0x0410, "Griffin PowerMate", mc_powermate_keys, translate_compliant},
0263     {0x05f3, 0x0241, "X-Keys Editor", mc_x_keys, translate_contour_hid_event},
0264     {0, 0, 0, 0, 0}};
0265 
0266 void media_ctrl_read_event(struct media_ctrl *ctrl, struct media_ctrl_event *me)
0267 {
0268     ssize_t n;
0269     struct input_event ev;
0270 
0271     // struct media_ctrl_event me;
0272 
0273     if (ctrl->fd > 0) {
0274         n = read(ctrl->fd, &ev, sizeof(ev));
0275     } else {
0276         return;
0277     }
0278 
0279     if (n != sizeof(ev)) {
0280         // printf("JogShuttle::inputCallback: read: (%d) %s\n", errno, strerror(errno));
0281         close(ctrl->fd);
0282         ctrl->fd = -1;
0283         return;
0284     }
0285 
0286     if (ctrl->device && ctrl->device->translate)
0287         ctrl->device->translate(ctrl, &ev, me);
0288     else
0289         me->type = 0;
0290 
0291     if (me->type == MEDIA_CTRL_EVENT_JOG) {
0292         struct timeval timev;
0293         gettimeofday(&timev, NULL);
0294         unsigned long now = (unsigned long)timev.tv_usec + (1000000 * (unsigned long)timev.tv_sec);
0295         if (now < ctrl->last_jog_time + 40000) {
0296             // printf("*** Fast Jog %02d %05d ***\n", me->value, now - ctrl->last_jog_time);
0297             ctrl->jogrel = me->value;
0298             me->type = MEDIA_CTRL_EVENT_NONE;
0299         } else {
0300             me->value += ctrl->jogrel;
0301             ctrl->jogrel = 0;
0302             ctrl->last_jog_time = now;
0303             // printf("*** Jog %02d ***\n", me->value);
0304         }
0305     }
0306 }
0307 
0308 int probe_device(struct media_ctrl *mc)
0309 {
0310     short devinfo[4];
0311     int i = 0;
0312 
0313     if (ioctl(mc->fd, EVIOCGID, &devinfo)) {
0314         perror("evdev ioctl");
0315         return 0;
0316     }
0317 
0318     do {
0319         if (supported_devices[i].vendor == devinfo[1] && supported_devices[i].product == devinfo[2]) {
0320 
0321             mc->device = &supported_devices[i];
0322             // printf("Success on /dev/input/event%d: %s\n", mc->eventno, mc->device->name);
0323             // mc->fd = fd;
0324             // mc->translate = mc->device.translate_function;
0325             // mc = malloc(sizeof(struct media_ctrl));
0326             mc->jogpos = 0;
0327             mc->lastval = -1;
0328             mc->last_jog_time = 0;
0329             return 1;
0330         }
0331         // mc->device = NULL;
0332 
0333     } while (supported_devices[++i].vendor != 0);
0334 
0335     return 0;
0336 }
0337 
0338 void find_first_device(struct media_ctrl *mc)
0339 {
0340     char buf[256];
0341     int i;
0342 
0343     for (i = 0; i < 32; i++) {
0344         sprintf(buf, "/dev/input/event%d", i);
0345         int fd = open(buf, O_RDONLY);
0346         if (fd < 0) {
0347             perror(buf);
0348         } else {
0349             mc->fd = fd;
0350             mc->eventno = i;
0351             if (probe_device(mc)) {
0352                 return;
0353             }
0354             close(fd);
0355             mc->fd = -1;
0356         }
0357     }
0358 }
0359 
0360 void media_ctrl_close(struct media_ctrl *mc)
0361 {
0362     if (mc->fd > 0) close(mc->fd);
0363     memset(mc, 0, sizeof(struct media_ctrl));
0364 }
0365 
0366 void media_ctrl_open(struct media_ctrl *mc)
0367 {
0368     find_first_device(mc);
0369 }
0370 
0371 void media_ctrl_open_dev(struct media_ctrl *mc, const char *devname)
0372 {
0373     int fd;
0374 
0375     fd = open(devname, O_RDONLY);
0376     if (fd < 0) {
0377         perror(devname);
0378         mc->fd = -1;
0379     } else {
0380         mc->fd = fd;
0381         // mc->eventno = i;
0382         if (probe_device(mc)) {
0383             return;
0384         }
0385         close(fd);
0386         mc->fd = -1;
0387     }
0388 }