Mercurial > mplayer.hg
comparison input/input.c @ 4418:8141d2c399e4
A new configurable input system and joystick support for this system
author | albeu |
---|---|
date | Wed, 30 Jan 2002 12:46:03 +0000 |
parents | |
children | 5105f5da01d6 |
comparison
equal
deleted
inserted
replaced
4417:4f507d28716d | 4418:8141d2c399e4 |
---|---|
1 #include "../config.h" | |
2 | |
3 #ifdef HAVE_NEW_INPUT | |
4 | |
5 #include <stdlib.h> | |
6 #include <string.h> | |
7 #include <stdio.h> | |
8 #include <unistd.h> | |
9 #include <errno.h> | |
10 #include <signal.h> | |
11 #include <sys/types.h> | |
12 #include <fcntl.h> | |
13 | |
14 | |
15 | |
16 #include "input.h" | |
17 #ifdef MP_DEBUG | |
18 #include <assert.h> | |
19 #endif | |
20 #include "../linux/getch2.h" | |
21 #include "../linux/keycodes.h" | |
22 #include "../linux/timer.h" | |
23 | |
24 #ifdef HAVE_JOYSTICK | |
25 #include "joystick.h" | |
26 #endif | |
27 | |
28 // If the args field is not NULL, the command will only be passed if | |
29 // an argument exist. | |
30 | |
31 static mp_cmd_t mp_cmds[] = { | |
32 { MP_CMD_SEEK, "seek", 1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
33 { MP_CMD_AUDIO_DELAY, "audio_delay", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } }, | |
34 { MP_CMD_QUIT, "quit", 0, { {-1,{0}} } }, | |
35 { MP_CMD_PAUSE, "pause", 0, { {-1,{0}} } }, | |
36 { MP_CMD_GRAB_FRAMES, "grap_frames",0, { {-1,{0}} } }, | |
37 { MP_CMD_PLAY_TREE_STEP, "pt_step",1, { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} } }, | |
38 { MP_CMD_PLAY_TREE_UP_STEP, "pt_up_step",1, { { MP_CMD_ARG_INT,{0} }, {-1,{0}} } }, | |
39 { MP_CMD_PLAY_ALT_SRC_STEP, "alt_src_step",1, { { MP_CMD_ARG_INT,{0} }, {-1,{0}} } }, | |
40 { MP_CMD_SUB_DELAY, "sub_delay",1, { {MP_CMD_ARG_FLOAT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
41 { MP_CMD_OSD, "osd",0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } }, | |
42 { MP_CMD_VOLUME, "volume", 1, { { MP_CMD_ARG_INT,{0} }, {-1,{0}} } }, | |
43 { MP_CMD_MIXER_USEMASTER, "use_master", 0, { {-1,{0}} } }, | |
44 { MP_CMD_CONTRAST, "contrast",1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
45 { MP_CMD_BRIGHTNESS, "brightness",1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
46 { MP_CMD_HUE, "hue",1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
47 { MP_CMD_SATURATION, "saturation",1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, | |
48 { MP_CMD_FRAMEDROPPING, "frame_drop",0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, | |
49 #ifdef USE_TV | |
50 { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", 1, { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} }}, | |
51 { MP_CMD_TV_STEP_NORM, "tv_step_norm",0, { {-1,{0}} } }, | |
52 { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", 0, { {-1,{0}} } }, | |
53 #endif | |
54 { 0, NULL, 0, {} } | |
55 }; | |
56 | |
57 static mp_cmd_bind_t key_names[] = { | |
58 { ' ', "SPACE" }, | |
59 { KEY_ENTER, "ENTER" }, | |
60 { KEY_TAB, "TAB" }, | |
61 { KEY_CTRL, "CTRL" }, | |
62 { KEY_BACKSPACE, "BS" }, | |
63 { KEY_DELETE, "DEL" }, | |
64 { KEY_INSERT, "INS" }, | |
65 { KEY_HOME, "HOME" }, | |
66 { KEY_END, "END" }, | |
67 { KEY_PAGE_UP, "PGUP" }, | |
68 { KEY_PAGE_DOWN, "PGDWN" }, | |
69 { KEY_ESC, "ESC" }, | |
70 { KEY_RIGHT, "RIGHT" }, | |
71 { KEY_LEFT, "LEFT" }, | |
72 { KEY_DOWN, "DOWN" }, | |
73 { KEY_UP, "UP" }, | |
74 #ifdef HAVE_JOYSTICK | |
75 { JOY_UP, "JOY_UP" }, | |
76 { JOY_DOWN, "JOY_DOWN" }, | |
77 { JOY_LEFT, "JOY_LEFT" }, | |
78 { JOY_RIGHT, "JOY_RIGHT" }, | |
79 { JOY_BTN0, "JOY_BTN0" }, | |
80 { JOY_BTN1, "JOY_BTN1" }, | |
81 { JOY_BTN2, "JOY_BTN2" }, | |
82 { JOY_BTN3, "JOY_BTN3" }, | |
83 { JOY_BTN4, "JOY_BTN4" }, | |
84 { JOY_BTN5, "JOY_BTN5" }, | |
85 { JOY_BTN6, "JOY_BTN6" }, | |
86 { JOY_BTN7, "JOY_BTN7" }, | |
87 { JOY_BTN8, "JOY_BTN8" }, | |
88 { JOY_BTN9, "JOY_BTN9" }, | |
89 #endif | |
90 { 0, NULL } | |
91 }; | |
92 | |
93 // This is the default binding we use when no config file is here | |
94 | |
95 static mp_cmd_bind_t def_cmd_binds[] = { | |
96 { KEY_RIGHT, "seek 10" }, | |
97 { KEY_LEFT, "seek -10" }, | |
98 { KEY_UP, "seek 60" }, | |
99 { KEY_DOWN, "seek -60" }, | |
100 { KEY_PAGE_UP, "seek 600" }, | |
101 { KEY_PAGE_DOWN, "seek -600" }, | |
102 { '+', "audio_delay 0.100" }, | |
103 { '-', "audio_delay -0.100" }, | |
104 { 'q', "quit" }, | |
105 { KEY_ESC, "quit" }, | |
106 { 'p', "pause" }, | |
107 { ' ', "pause" }, | |
108 { KEY_HOME, "pt_up_step 1" }, | |
109 { KEY_END, "pt_up_step -1" }, | |
110 { '>', "pt_step 1" }, | |
111 { '<', "pt_step -1" }, | |
112 { KEY_INS, "alt_src_step 1" }, | |
113 { KEY_DEL, "alt_src_step -1" }, | |
114 { 'o', "osd" }, | |
115 { 'z', "sub_delay -0.1" }, | |
116 { 'x', "sub_delay +0.1" }, | |
117 { '9', "volume -1" }, | |
118 { '/', "volume -1" }, | |
119 { '0', "volume 1" }, | |
120 { '*', "volume 1" }, | |
121 { 'm', "use_master" }, | |
122 { '1', "contrast -1" }, | |
123 { '2', "contrast 1" }, | |
124 { '3', "brightness -1" }, | |
125 { '4', "brightness 1" }, | |
126 { '5', "hue -1" }, | |
127 { '6', "hue 1" }, | |
128 { '7', "saturation -1" }, | |
129 { '8', "saturation 1" }, | |
130 { 'd', "frame_drop" }, | |
131 #ifdef USE_TV | |
132 { 'h', "tv_step_channel 1" }, | |
133 { 'l', "tv_step_channel -1" }, | |
134 { 'n', "tv_step_norm" }, | |
135 { 'b', "tv_step_chanlist" }, | |
136 #endif | |
137 { 0, NULL } | |
138 }; | |
139 | |
140 #ifndef MP_MAX_KEY_FD | |
141 #define MP_MAX_KEY_FD 10 | |
142 #endif | |
143 | |
144 #ifndef MP_MAX_CMD_FD | |
145 #define MP_MAX_CMD_FD 10 | |
146 #endif | |
147 | |
148 #define MP_FD_EOF (1<<0) | |
149 #define MP_FD_DROP (1<<1) | |
150 #define MP_FD_DEAD (1<<2) | |
151 #define MP_FD_GOT_CMD (1<<3) | |
152 #define MP_FD_NO_SELECT (1<<4) | |
153 | |
154 typedef struct mp_input_fd { | |
155 int fd; | |
156 void* read_func; | |
157 mp_close_func_t close_func; | |
158 int flags; | |
159 // This fields are for the cmd fds | |
160 char* buffer; | |
161 int pos,size; | |
162 } mp_input_fd_t; | |
163 | |
164 | |
165 static mp_cmd_bind_t* cmd_binds = def_cmd_binds; | |
166 | |
167 static mp_input_fd_t key_fds[MP_MAX_KEY_FD]; | |
168 static unsigned int num_key_fd = 0; | |
169 static mp_input_fd_t cmd_fds[MP_MAX_CMD_FD]; | |
170 static unsigned int num_cmd_fd = 0; | |
171 | |
172 static int key_max_fd = -1, cmd_max_fd = -1; | |
173 | |
174 static int | |
175 mp_input_default_key_func(int fd); | |
176 | |
177 | |
178 int | |
179 mp_input_add_cmd_fd(int fd, int select, mp_cmd_func_t read_func, mp_close_func_t close_func) { | |
180 if(num_cmd_fd == MP_MAX_CMD_FD) { | |
181 printf("Too much command fd, unable to register fd %d\n",fd); | |
182 return 0; | |
183 } | |
184 | |
185 memset(&cmd_fds[num_cmd_fd],0,sizeof(mp_input_fd_t)); | |
186 cmd_fds[num_cmd_fd].fd = fd; | |
187 cmd_fds[num_cmd_fd].read_func = read_func ? read_func : (mp_cmd_func_t)read; | |
188 cmd_fds[num_cmd_fd].close_func = close_func; | |
189 if(!select) | |
190 cmd_fds[num_cmd_fd].flags = MP_FD_NO_SELECT; | |
191 num_cmd_fd++; | |
192 if(fd > cmd_max_fd) | |
193 cmd_max_fd = fd; | |
194 | |
195 return 1; | |
196 } | |
197 | |
198 void | |
199 mp_input_rm_cmd_fd(int fd) { | |
200 unsigned int i; | |
201 | |
202 for(i = 0; i < num_cmd_fd; i++) { | |
203 if(cmd_fds[i].fd == fd) | |
204 break; | |
205 } | |
206 if(i == num_cmd_fd) | |
207 return; | |
208 if(cmd_fds[i].close_func) | |
209 cmd_fds[i].close_func(cmd_fds[i].fd); | |
210 | |
211 if(i + 1 < num_cmd_fd) | |
212 memmove(&cmd_fds[i],&cmd_fds[i+1],(num_cmd_fd - i - 1)*sizeof(mp_input_fd_t)); | |
213 num_cmd_fd--; | |
214 } | |
215 | |
216 void | |
217 mp_input_rm_key_fd(int fd) { | |
218 unsigned int i; | |
219 | |
220 for(i = 0; i < num_key_fd; i++) { | |
221 if(key_fds[i].fd == fd) | |
222 break; | |
223 } | |
224 if(i == num_key_fd) | |
225 return; | |
226 if(key_fds[i].close_func) | |
227 key_fds[i].close_func(key_fds[i].fd); | |
228 | |
229 if(i + 1 < num_key_fd) | |
230 memmove(&key_fds[i],&key_fds[i+1],(num_key_fd - i - 1)*sizeof(mp_input_fd_t)); | |
231 num_key_fd--; | |
232 } | |
233 | |
234 int | |
235 mp_input_add_key_fd(int fd, int select, mp_key_func_t read_func, mp_close_func_t close_func) { | |
236 if(num_key_fd == MP_MAX_KEY_FD) { | |
237 printf("Too much key fd, unable to register fd %d\n",fd); | |
238 return 0; | |
239 } | |
240 | |
241 memset(&key_fds[num_key_fd],0,sizeof(mp_input_fd_t)); | |
242 key_fds[num_key_fd].fd = fd; | |
243 key_fds[num_key_fd].read_func = read_func ? read_func : mp_input_default_key_func; | |
244 key_fds[num_key_fd].close_func = close_func; | |
245 if(!select) | |
246 key_fds[num_key_fd].flags |= MP_FD_NO_SELECT; | |
247 num_key_fd++; | |
248 if(fd > key_max_fd) | |
249 key_max_fd = fd; | |
250 | |
251 return 1; | |
252 } | |
253 | |
254 | |
255 | |
256 static mp_cmd_t* | |
257 mp_input_parse_cmd(char* str) { | |
258 int i,l; | |
259 char *ptr,*e; | |
260 mp_cmd_t *cmd, *cmd_def; | |
261 | |
262 #ifdef MP_DEBUG | |
263 assert(str != NULL); | |
264 #endif | |
265 | |
266 ptr = strchr(str,' '); | |
267 if(ptr) | |
268 l = ptr-str; | |
269 else | |
270 l = strlen(str); | |
271 | |
272 if(l == 0) | |
273 return NULL; | |
274 | |
275 for(i=0; mp_cmds[i].name != NULL; i++) { | |
276 if(strncasecmp(mp_cmds[i].name,str,l) == 0) | |
277 break; | |
278 } | |
279 | |
280 if(mp_cmds[i].name == NULL) | |
281 return NULL; | |
282 | |
283 cmd_def = &mp_cmds[i]; | |
284 | |
285 cmd = (mp_cmd_t*)malloc(sizeof(mp_cmd_t)); | |
286 cmd->id = cmd_def->id; | |
287 cmd->name = strdup(cmd_def->name); | |
288 | |
289 ptr = str; | |
290 | |
291 for(i=0; ptr && i < MP_CMD_MAX_ARGS; i++) { | |
292 ptr = strchr(ptr,' '); | |
293 if(!ptr) break; | |
294 while(ptr[0] == ' ') ptr++; | |
295 if(ptr[0] == '\0') break; | |
296 switch(cmd_def->args[i].type) { | |
297 case MP_CMD_ARG_INT: | |
298 errno = 0; | |
299 cmd->args[i].v.i = atoi(ptr); | |
300 if(errno != 0) { | |
301 printf("Command %s : argument %d isn't an integer\n",cmd_def->name,i+1); | |
302 ptr = NULL; | |
303 } | |
304 break; | |
305 case MP_CMD_ARG_FLOAT: | |
306 errno = 0; | |
307 cmd->args[i].v.f = atof(ptr); | |
308 if(errno != 0) { | |
309 printf("Command %s : argument %d isn't a float\n",cmd_def->name,i+1); | |
310 ptr = NULL; | |
311 } | |
312 break; | |
313 case MP_CMD_ARG_STRING: | |
314 e = strchr(ptr,' '); | |
315 if(!e) e = ptr+strlen(ptr); | |
316 l = e-ptr; | |
317 cmd->args[i].v.s = (char*)malloc((l+1)*sizeof(char)); | |
318 strncpy(cmd->args[i].v.s,ptr,l); | |
319 cmd->args[i].v.s[l] = '\0'; | |
320 break; | |
321 case -1: | |
322 ptr = NULL; | |
323 default : | |
324 printf("Unknow argument %d\n",i); | |
325 } | |
326 } | |
327 cmd->nargs = i; | |
328 | |
329 if(cmd_def->nargs > cmd->nargs) { | |
330 printf("Got [%s] but\n",str); | |
331 printf("Command %s require at least %d arguments, we found only %d so far\n",cmd_def->name,cmd_def->nargs,cmd->nargs); | |
332 mp_cmd_free(cmd); | |
333 return NULL; | |
334 } | |
335 | |
336 for( ; i < MP_CMD_MAX_ARGS && cmd_def->args[i].type != -1 ; i++) | |
337 memcpy(&cmd->args[i].v,&cmd_def->args[i].v,sizeof(mp_cmd_arg_value_t)); | |
338 | |
339 return cmd; | |
340 } | |
341 | |
342 static int | |
343 mp_input_default_key_func(int fd) { | |
344 int r,code=0; | |
345 unsigned int l; | |
346 l = 0; | |
347 while(l < sizeof(int)) { | |
348 r = read(fd,(&code)+l,sizeof(int)-l); | |
349 if(r <= 0) | |
350 break; | |
351 l +=r; | |
352 } | |
353 return code; | |
354 } | |
355 | |
356 #define MP_CMD_MAX_SIZE 256 | |
357 | |
358 static int | |
359 mp_input_read_cmd(mp_input_fd_t* mp_fd, char** ret) { | |
360 char* end; | |
361 (*ret) = NULL; | |
362 | |
363 if(!mp_fd->buffer) { | |
364 mp_fd->buffer = (char*)malloc(MP_CMD_MAX_SIZE*sizeof(char)); | |
365 mp_fd->pos = 0; | |
366 mp_fd->size = MP_CMD_MAX_SIZE; | |
367 } | |
368 | |
369 if(mp_fd->size - mp_fd->pos == 0) { | |
370 printf("Cmd buffer of fd %d is full : dropping content\n",mp_fd->fd); | |
371 mp_fd->pos = 0; | |
372 mp_fd->flags |= MP_FD_DROP; | |
373 } | |
374 | |
375 while( !(mp_fd->flags & MP_FD_EOF) && (mp_fd->size - mp_fd->pos > 1) ) { | |
376 int r = ((mp_cmd_func_t)mp_fd->read_func)(mp_fd->fd,mp_fd->buffer+mp_fd->pos,mp_fd->size - 1 - mp_fd->pos); | |
377 if(r < 0) { | |
378 if(errno == EINTR) | |
379 continue; | |
380 else if(errno == EAGAIN) | |
381 break; | |
382 printf("Error while reading cmd fd %d : %s\n",mp_fd->fd,strerror(errno)); | |
383 return MP_INPUT_ERROR; | |
384 } else if(r == 0) { | |
385 mp_fd->flags |= MP_FD_EOF; | |
386 break; | |
387 } | |
388 mp_fd->pos += r; | |
389 break; | |
390 } | |
391 | |
392 | |
393 while(1) { | |
394 int l = 0; | |
395 mp_fd->buffer[mp_fd->pos] = '\0'; | |
396 end = strchr(mp_fd->buffer,'\n'); | |
397 if(!end) | |
398 break; | |
399 else if((*ret)) { | |
400 mp_fd->flags |= MP_FD_GOT_CMD; | |
401 break; | |
402 } | |
403 | |
404 l = end - mp_fd->buffer; | |
405 | |
406 if( ! (mp_fd->flags & MP_FD_DROP)) { | |
407 (*ret) = (char*)malloc((l+1)*sizeof(char)); | |
408 strncpy((*ret),mp_fd->buffer,l); | |
409 (*ret)[l] = '\0'; | |
410 } else { | |
411 mp_fd->flags &= ~MP_FD_DROP; | |
412 } | |
413 if( mp_fd->pos - (l+1) > 0) | |
414 memmove(mp_fd->buffer,end,mp_fd->pos-(l+1)); | |
415 mp_fd->pos -= l+1; | |
416 } | |
417 | |
418 if(*ret) | |
419 return 1; | |
420 else | |
421 return MP_INPUT_NOTHING; | |
422 } | |
423 | |
424 static mp_cmd_t* | |
425 mp_input_read_keys(int time,int paused) { | |
426 fd_set fds; | |
427 struct timeval tv; | |
428 int i,n=0; | |
429 static int last_loop = 0; | |
430 | |
431 if(num_key_fd == 0) | |
432 return NULL; | |
433 | |
434 FD_ZERO(&fds); | |
435 for(i = 0; (unsigned int)i < num_key_fd; i++) { | |
436 if( (key_fds[i].flags & MP_FD_DEAD) ) { | |
437 mp_input_rm_key_fd(key_fds[i].fd); | |
438 i--; | |
439 continue; | |
440 } else if(key_fds[i].flags & MP_FD_NO_SELECT) | |
441 continue; | |
442 | |
443 FD_SET(key_fds[i].fd,&fds); | |
444 n++; | |
445 } | |
446 | |
447 if(n > 0 ) { | |
448 | |
449 tv.tv_sec=time/1000; | |
450 tv.tv_usec = (time%1000)*1000; | |
451 | |
452 while(1) { | |
453 if(select(key_max_fd+1,&fds,NULL,NULL,&tv) < 0) { | |
454 if(errno == EINTR) | |
455 continue; | |
456 printf("Select error : %s\n",strerror(errno)); | |
457 } | |
458 break; | |
459 } | |
460 } else { | |
461 FD_ZERO(&fds); | |
462 } | |
463 | |
464 for(i = last_loop + 1 ; i != last_loop ; i++) { | |
465 int code = -1,j; | |
466 | |
467 if((unsigned int)i >= num_key_fd) { | |
468 i = -1; | |
469 last_loop++; | |
470 continue; | |
471 } | |
472 if(! (key_fds[i].flags & MP_FD_NO_SELECT) && ! FD_ISSET(key_fds[i].fd,&fds)) | |
473 continue; | |
474 if(key_fds[i].fd == 0) { // stdin is handled by getch2 | |
475 code = getch2(time); | |
476 if(code < 0) | |
477 code = MP_INPUT_NOTHING; | |
478 } | |
479 else | |
480 code = ((mp_key_func_t)key_fds[i].read_func)(key_fds[i].fd); | |
481 | |
482 if(code < 0) { | |
483 if(code == MP_INPUT_ERROR) | |
484 printf("Error on key input fd %d\n",key_fds[i].fd); | |
485 else if(code == MP_INPUT_DEAD) { | |
486 printf("Dead key input on fd %d\n",key_fds[i].fd); | |
487 key_fds[i].flags |= MP_FD_DEAD; | |
488 } | |
489 continue; | |
490 } | |
491 if(paused) | |
492 return mp_input_parse_cmd("pause"); | |
493 for(j = 0; cmd_binds[j].cmd != NULL; j++) { | |
494 if(cmd_binds[j].input == code) | |
495 break; | |
496 } | |
497 if(cmd_binds[j].cmd == NULL) | |
498 continue; | |
499 last_loop = i; | |
500 return mp_input_parse_cmd(cmd_binds[j].cmd); | |
501 } | |
502 | |
503 last_loop = 0; | |
504 return NULL; | |
505 } | |
506 | |
507 static mp_cmd_t* | |
508 mp_input_read_cmds(int time) { | |
509 fd_set fds; | |
510 struct timeval tv; | |
511 int i,n = 0; | |
512 mp_cmd_t* ret; | |
513 static int last_loop = 0; | |
514 | |
515 if(num_cmd_fd == 0) | |
516 return NULL; | |
517 | |
518 FD_ZERO(&fds); | |
519 for(i = 0; (unsigned int)i < num_cmd_fd ; i++) { | |
520 if( (cmd_fds[i].flags & MP_FD_DEAD) || (cmd_fds[i].flags & MP_FD_EOF) ) { | |
521 mp_input_rm_cmd_fd(cmd_fds[i].fd); | |
522 i--; | |
523 continue; | |
524 } else if(cmd_fds[i].flags & MP_FD_NO_SELECT) | |
525 continue; | |
526 FD_SET(cmd_fds[i].fd,&fds); | |
527 n++; | |
528 } | |
529 | |
530 if(n > 0) { | |
531 | |
532 tv.tv_sec=time/1000; | |
533 tv.tv_usec = (time%1000)*1000; | |
534 | |
535 while(1) { | |
536 if((i = select(cmd_max_fd+1,&fds,NULL,NULL,&tv)) <= 0) { | |
537 if(i < 0) { | |
538 if(errno == EINTR) | |
539 continue; | |
540 printf("Select error : %s\n",strerror(errno)); | |
541 } | |
542 return NULL; | |
543 } | |
544 break; | |
545 } | |
546 } else { | |
547 FD_ZERO(&fds); | |
548 } | |
549 | |
550 for(i = last_loop + 1; i != last_loop ; i++) { | |
551 int r = 0; | |
552 char* cmd; | |
553 if((unsigned int)i >= num_cmd_fd) { | |
554 i = -1; | |
555 last_loop++; | |
556 continue; | |
557 } | |
558 if( ! (cmd_fds[i].flags & MP_FD_NO_SELECT) && ! FD_ISSET(cmd_fds[i].fd,&fds) && ! (cmd_fds[i].flags & MP_FD_GOT_CMD) ) | |
559 continue; | |
560 | |
561 r = mp_input_read_cmd(&cmd_fds[i],&cmd); | |
562 if(r < 0) { | |
563 if(r == MP_INPUT_ERROR) | |
564 printf("Error on cmd fd %d\n",cmd_fds[i].fd); | |
565 else if(r == MP_INPUT_DEAD) | |
566 cmd_fds[i].flags |= MP_FD_DEAD; | |
567 continue; | |
568 } | |
569 ret = mp_input_parse_cmd(cmd); | |
570 free(cmd); | |
571 if(!ret) | |
572 continue; | |
573 last_loop = i; | |
574 return ret; | |
575 } | |
576 | |
577 last_loop = 0; | |
578 return NULL; | |
579 } | |
580 | |
581 mp_cmd_t* | |
582 mp_input_get_cmd(int time, int paused) { | |
583 mp_cmd_t* ret; | |
584 | |
585 ret = mp_input_read_keys(time,paused); | |
586 if(ret) | |
587 return ret; | |
588 | |
589 return mp_input_read_cmds(time); | |
590 } | |
591 | |
592 void | |
593 mp_cmd_free(mp_cmd_t* cmd) { | |
594 int i; | |
595 #ifdef MP_DEBUG | |
596 assert(cmd != NULL); | |
597 #endif | |
598 | |
599 if(cmd->name) | |
600 free(cmd->name); | |
601 | |
602 for(i=0; i < MP_CMD_MAX_ARGS && cmd->args[i].type != -1; i++) { | |
603 if(cmd->args[i].type == MP_CMD_ARG_STRING) | |
604 free(cmd->args[i].v.s); | |
605 } | |
606 free(cmd); | |
607 } | |
608 | |
609 static int | |
610 mp_input_get_key_from_name(char* name) { | |
611 int i,ret = 0; | |
612 | |
613 if(strlen(name) == 1) { // Direct key code | |
614 (char)ret = name[0]; | |
615 return ret; | |
616 } | |
617 | |
618 for(i = 0; key_names[i].cmd != NULL; i++) { | |
619 if(strcasecmp(key_names[i].cmd,name) == 0) | |
620 return key_names[i].input; | |
621 } | |
622 | |
623 return -1; | |
624 } | |
625 | |
626 static void | |
627 mp_input_free_binds(mp_cmd_bind_t* binds) { | |
628 int i; | |
629 | |
630 if(!binds) | |
631 return; | |
632 | |
633 for(i = 0; binds[i].cmd != NULL; i++) | |
634 free(binds[i].cmd); | |
635 | |
636 free(binds); | |
637 | |
638 } | |
639 | |
640 | |
641 #define BS_MAX 256 | |
642 #define SPACE_CHAR " \n\r\t" | |
643 | |
644 static void | |
645 mp_input_parse_config(char *file) { | |
646 int fd,code=-1; | |
647 int bs = 0,r,eof = 0; | |
648 char *iter,*end; | |
649 char buffer[BS_MAX]; | |
650 int n_binds = 0; | |
651 mp_cmd_bind_t* binds = NULL; | |
652 | |
653 fd = open(file,O_RDONLY); | |
654 | |
655 if(fd < 0) { | |
656 printf("Can't open input config file %s : %s\n",file,strerror(errno)); | |
657 return; | |
658 } | |
659 | |
660 printf("Parsing input config file %s\n",file); | |
661 | |
662 while(1) { | |
663 if(! eof && bs < BS_MAX-1) { | |
664 if(bs > 0) bs--; | |
665 r = read(fd,buffer+bs,BS_MAX-1-bs); | |
666 if(r < 0) { | |
667 if(errno == EINTR) | |
668 continue; | |
669 printf("Error while reading input config file %s : %s\n",file,strerror(errno)); | |
670 mp_input_free_binds(binds); | |
671 return; | |
672 } else if(r == 0) | |
673 eof = 1; | |
674 else { | |
675 bs += r+1; | |
676 buffer[bs-1] = '\0'; | |
677 } | |
678 } | |
679 // Empty buffer : return | |
680 if(bs <= 1) { | |
681 printf("Input config file %s parsed : %d binds\n",file,n_binds); | |
682 if(binds) | |
683 cmd_binds = binds; | |
684 return; | |
685 } | |
686 | |
687 iter = buffer; | |
688 | |
689 // Find the wanted key | |
690 if(code < 0) { | |
691 // Jump beginnig space | |
692 for( ; iter[0] != '\0' && strchr(SPACE_CHAR,iter[0]) != NULL ; iter++) | |
693 /* NOTHING */; | |
694 if(iter[0] == '\0') { // Buffer was full of space char | |
695 bs = 0; | |
696 continue; | |
697 } | |
698 // Find the end of the key code name | |
699 for(end = iter; end[0] != '\0' && strchr(SPACE_CHAR,end[0]) == NULL ; end++) | |
700 /*NOTHING */; | |
701 if(end[0] == '\0') { // Key name don't fit in the buffer | |
702 if(buffer == iter) { | |
703 if(eof && (buffer-iter) == bs) | |
704 printf("Unfinished binding %s\n",iter); | |
705 else | |
706 printf("Buffer is too small for this key name : %s\n",iter); | |
707 mp_input_free_binds(binds); | |
708 return; | |
709 } | |
710 memmove(buffer,iter,end-iter); | |
711 bs = end-iter; | |
712 continue; | |
713 } | |
714 { | |
715 char name[end-iter+1]; | |
716 strncpy(name,iter,end-iter); | |
717 name[end-iter] = '\0'; | |
718 code = mp_input_get_key_from_name(name); | |
719 if(code < 0) { | |
720 printf("Unknow key %s\n",name); | |
721 mp_input_free_binds(binds); | |
722 return; | |
723 } | |
724 } | |
725 if( bs > (end-buffer)) | |
726 memmove(buffer,end,bs - (end-buffer)); | |
727 bs -= end-buffer; | |
728 continue; | |
729 } else { // Get the command | |
730 while(iter[0] == ' ' || iter[0] == '\t') iter++; | |
731 // Found new line | |
732 if(iter[0] == '\n' || iter[0] == '\r') { | |
733 printf("No command found for key (TODO)\n" /*mp_input_get_key_name(code)*/); | |
734 code = -1; | |
735 if(iter > buffer) { | |
736 memmove(buffer,iter,bs- (iter-buffer)); | |
737 bs -= (iter-buffer); | |
738 } | |
739 continue; | |
740 } | |
741 for(end = iter ; end[0] != '\n' && end[0] != '\r' && end[0] != '\0' ; end++) | |
742 /* NOTHING */; | |
743 if(end[0] == '\0' && ! (eof && (end - buffer) == bs)) { | |
744 if(iter == buffer) { | |
745 printf("Buffer is too small for command %s\n",buffer); | |
746 mp_input_free_binds(binds); | |
747 return; | |
748 } | |
749 memmove(buffer,iter,end - iter); | |
750 bs = end - iter; | |
751 continue; | |
752 } | |
753 { | |
754 char cmd[end-iter+1]; | |
755 strncpy(cmd,iter,end-iter); | |
756 cmd[end-iter] = '\0'; | |
757 //printf("Set bind %d => %s\n",code,cmd); | |
758 binds = (mp_cmd_bind_t*)realloc(binds,(n_binds+2)*sizeof(mp_cmd_bind_t)); | |
759 binds[n_binds].input = code; | |
760 binds[n_binds].cmd = strdup(cmd); | |
761 n_binds++; | |
762 memset(&binds[n_binds],0,sizeof(mp_cmd_bind_t)); | |
763 } | |
764 code = -1; | |
765 if(bs > (end-buffer)) | |
766 memmove(buffer,end,bs-(end-buffer)); | |
767 bs -= (end-buffer); | |
768 continue; | |
769 } | |
770 } | |
771 printf("What are we doing here ?\n"); | |
772 } | |
773 | |
774 extern char *get_path(char *filename); | |
775 | |
776 void | |
777 mp_input_init(void) { | |
778 char* file; | |
779 | |
780 file = get_path("input.conf"); | |
781 if(!file) | |
782 return; | |
783 | |
784 mp_input_parse_config(file); | |
785 | |
786 #ifdef HAVE_JOYSTICK | |
787 { | |
788 int fd = mp_input_joystick_init(NULL); | |
789 if(fd < 0) | |
790 printf("Can't init input joystick\n"); | |
791 else | |
792 mp_input_add_key_fd(fd,1,mp_input_joystick_read,(mp_close_func_t)close); | |
793 } | |
794 #endif | |
795 | |
796 } | |
797 | |
798 #endif /* HAVE_NEW_INPUT */ |