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