]> git.sesse.net Git - kdenlive/blob - src/lib/external/media_ctrl/mediactrl.c
0421b9a287de4f56ae98408d8728f1943f58f34c
[kdenlive] / src / lib / external / media_ctrl / mediactrl.c
1 /*
2 * mediactrl.c -- Jog Shuttle device support
3 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <asm/types.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include <linux/input.h>
33 #include "mediactrl.h"
34
35
36 static char *_shuttle_name = (char*)"Shuttle";
37 static char *_jog_name = (char*)"Jog";
38
39 /*
40         ShuttlePro keys
41 */
42 static struct  media_ctrl_key mc_shuttle_pro_keys[] = {
43         { 0x100, "Button 1", MEDIA_CTRL_F1 },
44         { 0x101, "Button 2", MEDIA_CTRL_F2 },
45         { 0x102, "Button 3", MEDIA_CTRL_F3 },
46         { 0x103, "Button 4", MEDIA_CTRL_F4 },
47         { 0x104, "Button 5", MEDIA_CTRL_B4 },
48         { 0x105, "Button 6", MEDIA_CTRL_B2 },
49         { 0x106, "Button 7", MEDIA_CTRL_B1 },
50         { 0x107, "Button 8", MEDIA_CTRL_B3 },
51         { 0x108, "Button 9", MEDIA_CTRL_B5 },
52         { 0x109, "Button 10", MEDIA_CTRL_B6 },
53         { 0x10a, "Button 11", MEDIA_CTRL_B7 },
54         { 0x10b, "Button 12", MEDIA_CTRL_B8 },
55         { 0x10c, "Button 13", MEDIA_CTRL_B9 },
56         { 0, NULL, 0 }
57 };
58
59
60 /*
61         ShuttleXPress keys
62 */
63 static struct  media_ctrl_key mc_shuttle_xpress_keys[] = {
64     { 0x104, "Button B1", MEDIA_CTRL_B1},
65     { 0x105, "Button B2", MEDIA_CTRL_B2 },
66     { 0x106, "Button B3", MEDIA_CTRL_B3 },
67     { 0x107, "Button B4", MEDIA_CTRL_B4 },
68     { 0x108, "Button B5", MEDIA_CTRL_B5 },
69     { 0, NULL, 0 }
70 };
71
72
73
74 /*
75         JLCooper MCS3 Keys
76 */
77 static struct  media_ctrl_key mc_jlcooper_mcs3_keys[] = {
78         { 0x107, "F1", MEDIA_CTRL_F1 },
79         { 0x101, "F2", MEDIA_CTRL_F2 },
80         { 0x105, "F3", MEDIA_CTRL_F3 },
81         { 0x102, "F4", MEDIA_CTRL_F4 },
82         { 0x103, "F5", MEDIA_CTRL_F5 },
83         { 0x104, "F6", MEDIA_CTRL_F6 },
84         { 0x10d, "W1", MEDIA_CTRL_B6 },
85         { 0x10e, "W2", MEDIA_CTRL_B4 },
86         { 0x100, "W3", MEDIA_CTRL_B2 },
87         { 0x106, "W4", MEDIA_CTRL_B1 },
88         { 0x110, "W5", MEDIA_CTRL_B3 },
89         { 0x111, "W6", MEDIA_CTRL_B5 },
90         { 0x115, "W7", MEDIA_CTRL_B7 },
91         { 0x116, "STICK_LEFT", MEDIA_CTRL_STICK_LEFT },
92         { 0x113, "STICK_RIGHT", MEDIA_CTRL_STICK_RIGHT },
93         { 0x114, "STICK_UP", MEDIA_CTRL_STICK_UP },
94         { 0x112, "STICK_DOWN", MEDIA_CTRL_STICK_DOWN },
95         { 0x10f, "Rewind", MEDIA_CTRL_REWIND },
96         { 0x108, "Fast Forward", MEDIA_CTRL_FAST_FORWARD },
97         { 0x109, "Stop", MEDIA_CTRL_STOP },
98         { 0x10a, "Play", MEDIA_CTRL_PLAY },
99         { 0x10b, "Record", MEDIA_CTRL_RECORD },
100         { 0, NULL, 0 }
101 };
102
103
104 /*
105         Griffin PowerMate
106 */
107 static struct media_ctrl_key mc_powermate_keys[] = {
108         { BTN_0, "Button", MEDIA_CTRL_B1 },
109         { 0, NULL, 0 }
110 };
111
112
113 /*
114         X-Keys Jog/Shuttle
115 */
116 static struct  media_ctrl_key mc_x_keys[] = {
117         { 0x102, "Button L1", MEDIA_CTRL_F1 },
118         { 0x103, "Button L2", MEDIA_CTRL_F9 },
119         { 0x104, "Button L3", MEDIA_CTRL_B1 },
120         { 0x105, "Button L4", MEDIA_CTRL_B3 },
121         { 0x106, "Button L5", MEDIA_CTRL_B5 },
122         { 0x10a, "Button L6", MEDIA_CTRL_F2 },
123         { 0x10b, "Button L7", MEDIA_CTRL_F10 },
124         { 0x10c, "Button L8", MEDIA_CTRL_B2 },
125         { 0x10d, "Button L9", MEDIA_CTRL_B4 },
126         { 0x10e, "Button L10", MEDIA_CTRL_B6 },
127         { 0x112, "Button C1", MEDIA_CTRL_F3 },
128         { 0x11a, "Button C2", MEDIA_CTRL_F4 },
129         { 0x122, "Button C3", MEDIA_CTRL_F5 },
130         { 0x12a, "Button C4", MEDIA_CTRL_F6 },
131         { 0x113, "Button C5", MEDIA_CTRL_F11 },
132         { 0x11b, "Button C6", MEDIA_CTRL_F12 },
133         { 0x123, "Button C7", MEDIA_CTRL_F13 },
134         { 0x12b, "Button C8", MEDIA_CTRL_F14 },
135         { 0x132, "Button R1", MEDIA_CTRL_F7 },
136         { 0x133, "Button R2", MEDIA_CTRL_F15 },
137         { 0x134, "Button R3", MEDIA_CTRL_B7 },
138         { 0x135, "Button R4", MEDIA_CTRL_B9 },
139         { 0x136, "Button R5", MEDIA_CTRL_B11 },
140         { 0x13a, "Button R6", MEDIA_CTRL_F8 },
141         { 0x13b, "Button R7", MEDIA_CTRL_F16 },
142         { 0x13c, "Button R8", MEDIA_CTRL_B8 },
143         { 0x13d, "Button R9", MEDIA_CTRL_B10 },
144         { 0x13e, "Button R10", MEDIA_CTRL_B12 },
145         { 0, NULL, 0 }
146 };
147
148 struct  media_ctrl_key *media_ctrl_get_key(struct media_ctrl *ctrl, int code, int *index)
149 {
150         int i = 0;
151         struct media_ctrl_key *keys = ctrl->device->keys;
152         
153         while ( keys[i].key != 0 ) {
154                 if (keys[i].key == code) {
155                         if (index != NULL)
156                                 *index = i;
157                         return &keys[i];
158                 }
159                 i++;
160         }
161         
162         return NULL;
163 }
164
165 int media_ctrl_get_keys_count(struct media_ctrl *ctrl)
166 {
167     int i = 0;
168     struct media_ctrl_key *keys = ctrl->device->keys;
169
170     while ( keys[i].key != 0 ) {
171         i++;
172     }
173
174     return i;
175 }
176
177 void translate_contour_hid_event(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
178 {
179         
180         int lv, cv;
181         
182         me->type = 0;
183         
184         if (ev->type == EV_REL) {
185                 /* First check the outer dial */
186                 if (ev->code == REL_WHEEL) {
187                         
188                         cv = (signed int)ev->value;
189                         if (cv == 1 || cv == -1 ) cv = 0;
190                         
191                                 
192                         if ( cv == ctrl->lastshu ) return;
193             ctrl->lastshu = cv;
194
195             if ( cv > 0 ) cv -= 1;
196             if ( cv < 0) cv += 1;
197
198                         //printf("Shuttle: %d\n", cv);
199                         me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
200                         me->value = cv*2;
201                         me->name = _shuttle_name;
202                         
203                 } else if  (ev->code == REL_DIAL) {
204                         
205                         if ( ctrl->lastval == -1 ) ctrl->lastval = ev->value;
206                         lv = ctrl->lastval;
207                         cv = ev->value;
208
209                         if ( lv == cv ) return;
210                                 
211                         ctrl->lastval = cv;
212                         
213                         if (cv < 10 && lv > 0xF0) cv +=0x100;
214                         if (lv < 10 && cv > 0xF0) lv +=0x100;
215                         
216                         me->type  = MEDIA_CTRL_EVENT_JOG;
217                         me->value = cv-lv;
218                         me->name = _jog_name;
219                         
220                         ctrl->jogpos += me->value;
221                         //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
222                 }
223                 return;
224         } else if (ev->type == EV_KEY) {
225                 int index;
226                 struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
227                 if ( key == NULL ) return;
228                 
229                 me->type  = MEDIA_CTRL_EVENT_KEY;
230                 me->code = key->code;
231                 me->value = ev->value;
232                 me->name = ( char* )key->name;
233                 me->index = index;
234                  
235                 //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
236                 
237         }
238         
239 }
240
241 void translate_compliant(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
242 {
243         me->type = 0;
244         
245         // printf("Translate %02x %02x\n", ev->type, ev->code );
246         
247         if (ev->type == EV_REL) {
248                 if  (ev->code == REL_DIAL) {
249                         
250                         me->type  = MEDIA_CTRL_EVENT_JOG;
251                         me->value = (signed int)ev->value;
252                         me->name = _jog_name;
253                         
254                         ctrl->jogpos += me->value;
255                         //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
256         }
257                 return;
258         } else if (ev->type == EV_ABS) {
259                 // printf("ABS\n" );
260                 if  ( ev->code == 0x1c || ev->code == ABS_THROTTLE ) {
261                         //printf("ABS_MISC\n" );
262                         me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
263                         me->value = (signed int)ev->value;
264                         me->name = _shuttle_name;
265                         
266                         ctrl->shuttlepos = me->value;
267                         //printf("Shuttle: %06d (%d)\n", ctrl->shuttlepos, me->value);
268                 }
269         } else if (ev->type == EV_KEY) {
270                 int index;
271                 struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
272                 if ( key == NULL ) return;
273                 
274                 me->type  = MEDIA_CTRL_EVENT_KEY;
275                 me->code = key->code;
276                 me->value = ev->value;
277                 me->name = ( char* )key->name;
278                 me->index = index;
279                  
280                 //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
281                 
282         }
283 }
284
285 struct media_ctrl_device supported_devices[] = {
286         { 0x0b33, 0x0030, "Contour ShuttlePRO v2", mc_shuttle_pro_keys, translate_contour_hid_event },
287         { 0x0b33, 0x0020, "Contour Design ShuttleXpress", mc_shuttle_xpress_keys, translate_contour_hid_event },
288         { 0x0b33, 0x0010, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
289         { 0x0b33, 0x0011, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event }, /* Hercules OEM */
290         { 0x05f3, 0x0240, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
291         { 0x0760, 0x0001, "JLCooper MCS3", mc_jlcooper_mcs3_keys, translate_compliant },
292         { 0x077d, 0x0410, "Griffin PowerMate", mc_powermate_keys, translate_compliant },
293         { 0x05f3, 0x0241, "X-Keys Editor", mc_x_keys, translate_contour_hid_event },
294         { 0, 0, 0, 0, 0 }
295 };
296
297
298 void media_ctrl_translate(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
299 {
300         if ( ctrl->device ) ctrl->device->translate(ctrl, ev, me);
301 }
302
303
304 void media_ctrl_read_event(struct media_ctrl *ctrl, struct media_ctrl_event *me) 
305 {
306         ssize_t n;
307         struct input_event ev;
308                 
309         // struct media_ctrl_event me;
310         
311         if ( ctrl->fd > 0 ) {
312                 n = read(ctrl->fd, &ev, sizeof(ev));
313         } else {
314                 return;
315         }
316         
317         if (n != sizeof(ev)) {
318                 //printf("JogShuttle::inputCallback: read: (%d) %s\n", errno, strerror(errno));
319                 close(ctrl->fd);
320                 ctrl->fd = 0;
321                 return;
322         }
323         
324         if ( ctrl->device && ctrl->device->translate)
325                 ctrl->device->translate(ctrl, &ev, me);
326         else
327                 me->type = 0;
328         
329         if ( me->type  == MEDIA_CTRL_EVENT_JOG ) {
330                 struct timeval timev;
331                 gettimeofday(&timev, NULL);
332                 unsigned long now = (unsigned long)timev.tv_usec + (1000000*(unsigned long)timev.tv_sec);
333                 if ( now < ctrl->last_jog_time + 40000 ) {
334                         //printf("*** Fast Jog %02d %05d ***\n", me->value, now - ctrl->last_jog_time);
335                         ctrl->jogrel = me->value;
336                         me->type = MEDIA_CTRL_EVENT_NONE;
337                 } else {
338                         me->value += ctrl->jogrel;
339                         ctrl->jogrel = 0;
340                         ctrl->last_jog_time = now;
341                         // printf("*** Jog %02d ***\n", me->value);
342                 }
343         }
344         
345         return;
346         
347 }
348
349
350 int probe_device(struct media_ctrl *mc)
351 {
352         short devinfo[4];
353         int i = 0;
354           
355         if ( ioctl(mc->fd, EVIOCGID, &devinfo) ) {
356                 perror("evdev ioctl");
357                 return 0;
358         }
359         
360         do {
361                 if ( supported_devices[i].vendor == devinfo[1] 
362                         && supported_devices[i].product == devinfo[2] ) {
363                                 
364                         mc->device = &supported_devices[i];
365                         //printf("Success on /dev/input/event%d: %s\n", mc->eventno, mc->device->name);
366                         // mc->fd = fd;
367                         // mc->translate = mc->device.translate_function;
368                         // mc = malloc(sizeof(struct media_ctrl));
369                         mc->jogpos  = 0;
370                         mc->lastval = -1;
371                         mc->last_jog_time = 0;
372                         return 1;
373                 } else {
374                         //mc->device = NULL;
375                 }
376         
377         } while ( supported_devices[++i].vendor != 0 );
378                         
379         return 0;
380 }
381
382
383 void media_ctrl_get_device_list() 
384 {
385         // TBD
386 }
387
388
389
390 void find_first_device(struct media_ctrl *mc) 
391 {
392         char buf[256];
393         int fd, i;
394         
395         for ( i = 0; i < 32; i++ ) {
396                 sprintf(buf, "/dev/input/event%d", i); 
397                 fd = open( buf, O_RDONLY );
398                 if ( fd < 0 ) {
399                         perror(buf);
400                 } else {
401                         mc->fd = fd;
402                         mc->eventno = i;
403                         if( probe_device(mc) ) {
404                                 return;
405                         } else {                
406                                 close(fd);
407                                 mc->fd = -1;
408                         }
409                 }
410         }
411         return;
412 }
413
414
415 void media_ctrl_close(struct media_ctrl *mc)
416 {
417         if (mc->fd > 0)
418                 close( mc->fd );
419         memset( mc, 0, sizeof( struct media_ctrl ) );
420 }
421
422
423 void media_ctrl_open(struct media_ctrl *mc) 
424 {
425         find_first_device(mc);
426 }
427
428 void media_ctrl_open2(struct media_ctrl *mc, const char *devname)
429 {
430     int fd;
431
432     fd = open( devname, O_RDONLY );
433     if ( fd < 0 ) {
434         perror(devname);
435         mc->fd = -1;
436     } else {
437         mc->fd = fd;
438         //mc->eventno = i;
439         if( probe_device(mc) ) {
440             return;
441         } else {
442             close(fd);
443             mc->fd = -1;
444         }
445     }
446 }
447