📄 input.c
字号:
if (strncmp(str, "pausing ", 8) == 0) { pausing = 1; str = &str[8]; } for(ptr = str ; ptr[0] != '\0' && ptr[0] != '\t' && ptr[0] != ' ' ; ptr++) /* NOTHING */; if(ptr[0] != '\0') l = ptr-str; else l = strlen(str); if(l == 0) return NULL; for(i=0; mp_cmds[i].name != NULL; i++) { if(strncasecmp(mp_cmds[i].name,str,l) == 0) break; } if(mp_cmds[i].name == NULL) return NULL; cmd_def = &mp_cmds[i]; cmd = (mp_cmd_t*)malloc(sizeof(mp_cmd_t)); cmd->id = cmd_def->id; cmd->name = strdup(cmd_def->name); cmd->pausing = pausing; ptr = str; for(i=0; ptr && i < MP_CMD_MAX_ARGS; i++) { ptr = strchr(ptr,' '); if(!ptr) break; while(ptr[0] == ' ' || ptr[0] == '\t') ptr++; if(ptr[0] == '\0') break; cmd->args[i].type = cmd_def->args[i].type; switch(cmd_def->args[i].type) { case MP_CMD_ARG_INT: errno = 0; cmd->args[i].v.i = atoi(ptr); if(errno != 0) { mp_msg(MSGT_INPUT,MSGL_ERR,"Command %s: argument %d isn't an integer.\n",cmd_def->name,i+1); ptr = NULL; } break; case MP_CMD_ARG_FLOAT: errno = 0; cmd->args[i].v.f = atof(ptr); if(errno != 0) { mp_msg(MSGT_INPUT,MSGL_ERR,"Command %s: argument %d isn't a float.\n",cmd_def->name,i+1); ptr = NULL; } break; case MP_CMD_ARG_STRING: { char term; char* ptr2 = ptr, *start; if(ptr[0] == '\'' || ptr[0] == '"') { term = ptr[0]; ptr2++; } else term = ' '; start = ptr2; while(1) { e = strchr(ptr2,term); if(!e) break; if(e <= ptr2 || *(e - 1) != '\\') break; ptr2 = e + 1; } if(term != ' ' && (!e || e[0] == '\0')) { mp_msg(MSGT_INPUT,MSGL_ERR,"Command %s: argument %d is unterminated.\n",cmd_def->name,i+1); ptr = NULL; break; } else if(!e) e = ptr+strlen(ptr); l = e-start; ptr2 = start; for(e = strchr(ptr2,'\\') ; e && e<start+l ; e = strchr(ptr2,'\\')) { memmove(e,e+1,strlen(e)); ptr2 = e + 1; l--; } cmd->args[i].v.s = (char*)malloc((l+1)*sizeof(char)); strncpy(cmd->args[i].v.s,start,l); cmd->args[i].v.s[l] = '\0'; if(term != ' ') ptr += l+2; } break; case -1: ptr = NULL; break; default : mp_msg(MSGT_INPUT,MSGL_ERR,"Unknown argument %d\n",i); } } cmd->nargs = i; if(cmd_def->nargs > cmd->nargs) { mp_msg(MSGT_INPUT,MSGL_ERR,"Got command '%s' but\n",str); mp_msg(MSGT_INPUT,MSGL_ERR,"command %s requires at least %d arguments, we found only %d so far.\n",cmd_def->name,cmd_def->nargs,cmd->nargs); mp_cmd_free(cmd); return NULL; } for( ; i < MP_CMD_MAX_ARGS && cmd_def->args[i].type != -1 ; i++) { memcpy(&cmd->args[i],&cmd_def->args[i],sizeof(mp_cmd_arg_t)); if(cmd_def->args[i].type == MP_CMD_ARG_STRING && cmd_def->args[i].v.s != NULL) cmd->args[i].v.s = strdup(cmd_def->args[i].v.s); } if(i < MP_CMD_MAX_ARGS) cmd->args[i].type = -1; return cmd;}static intmp_input_default_key_func(int fd) { int r,code=0; unsigned int l; l = 0; while(l < sizeof(int)) { r = read(fd,((char *)&code)+l,sizeof(int)-l); if(r <= 0) break; l +=r; } return code;}#define MP_CMD_MAX_SIZE 256static intmp_input_read_cmd(mp_input_fd_t* mp_fd, char** ret) { char* end; (*ret) = NULL; // Allocate the buffer if it doesn't exist if(!mp_fd->buffer) { mp_fd->buffer = (char*)malloc(MP_CMD_MAX_SIZE*sizeof(char)); mp_fd->pos = 0; mp_fd->size = MP_CMD_MAX_SIZE; } // Get some data if needed/possible while( !(mp_fd->flags & MP_FD_GOT_CMD) && !(mp_fd->flags & MP_FD_EOF) && (mp_fd->size - mp_fd->pos > 1) ) { 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); // Error ? if(r < 0) { switch(r) { case MP_INPUT_ERROR: case MP_INPUT_DEAD: mp_msg(MSGT_INPUT,MSGL_ERR,"Error while reading cmd fd %d: %s\n",mp_fd->fd,strerror(errno)); case MP_INPUT_NOTHING: return r; } // EOF ? } else if(r == 0) { mp_fd->flags |= MP_FD_EOF; break; } mp_fd->pos += r; break; } // Reset the got_cmd flag mp_fd->flags &= ~MP_FD_GOT_CMD; while(1) { int l = 0; // Find the cmd end mp_fd->buffer[mp_fd->pos] = '\0'; end = strchr(mp_fd->buffer,'\n'); // No cmd end ? if(!end) { // If buffer is full we must drop all until the next \n if(mp_fd->size - mp_fd->pos <= 1) { mp_msg(MSGT_INPUT,MSGL_ERR,"Cmd buffer of fd %d is full: dropping content\n",mp_fd->fd); mp_fd->pos = 0; mp_fd->flags |= MP_FD_DROP; } break; } // We already have a cmd : set the got_cmd flag else if((*ret)) { mp_fd->flags |= MP_FD_GOT_CMD; break; } l = end - mp_fd->buffer; // Not dropping : put the cmd in ret if( ! (mp_fd->flags & MP_FD_DROP)) { (*ret) = (char*)malloc((l+1)*sizeof(char)); strncpy((*ret),mp_fd->buffer,l); (*ret)[l] = '\0'; } else { // Remove the dropping flag mp_fd->flags &= ~MP_FD_DROP; } if( mp_fd->pos - (l+1) > 0) memmove(mp_fd->buffer,end+1,mp_fd->pos-(l+1)); mp_fd->pos -= l+1; } if(*ret) return 1; else return MP_INPUT_NOTHING;}static intmp_input_default_cmd_func(int fd,char* buf, int l) { while(1) { int r = read(fd,buf,l); // Error ? if(r < 0) { if(errno == EINTR) continue; else if(errno == EAGAIN) return MP_INPUT_NOTHING; return MP_INPUT_ERROR; // EOF ? } return r; }}voidmp_input_add_cmd_filter(mp_input_cmd_filter func, void* ctx) { mp_cmd_filter_t* filter = malloc(sizeof(mp_cmd_filter_t))/*, *prev*/; filter->filter = func; filter->ctx = ctx; filter->next = cmd_filters; cmd_filters = filter;} static char*mp_input_find_bind_for_key(mp_cmd_bind_t* binds, int n,int* keys) { int j; for(j = 0; binds[j].cmd != NULL; j++) { if(n > 0) { int found = 1,s; for(s = 0; s < n && binds[j].input[s] != 0; s++) { if(binds[j].input[s] != keys[s]) { found = 0; break; } } if(found && binds[j].input[s] == 0 && s == n) break; else continue; } else if(n == 1){ if(binds[j].input[0] == keys[0] && binds[j].input[1] == 0) break; } } return binds[j].cmd;}static mp_cmd_t*mp_input_get_cmd_from_keys(int n,int* keys, int paused) { char* cmd = NULL; mp_cmd_t* ret; if(cmd_binds) cmd = mp_input_find_bind_for_key(cmd_binds,n,keys); if(cmd == NULL) cmd = mp_input_find_bind_for_key(def_cmd_binds,n,keys); if(cmd == NULL) { mp_msg(MSGT_INPUT,MSGL_WARN,"No bind found for key %s",mp_input_get_key_name(keys[0])); if(n > 1) { int s; for(s=1; s < n; s++) mp_msg(MSGT_INPUT,MSGL_WARN,"-%s",mp_input_get_key_name(keys[s])); } mp_msg(MSGT_INPUT,MSGL_WARN," \n"); return NULL; } ret = mp_input_parse_cmd(cmd); if(!ret) { mp_msg(MSGT_INPUT,MSGL_ERR,"Invalid command for bound key %s",mp_input_get_key_name(key_down[0])); if( num_key_down > 1) { unsigned int s; for(s=1; s < num_key_down; s++) mp_msg(MSGT_INPUT,MSGL_ERR,"-%s",mp_input_get_key_name(key_down[s])); } mp_msg(MSGT_INPUT,MSGL_ERR," : %s \n",cmd); } return ret;}intmp_input_read_key_code(int time) {#ifndef HAVE_NO_POSIX_SELECT fd_set fds; struct timeval tv,*time_val;#endif int i,n=0,max_fd = 0; static int last_loop = 0; if(num_key_fd == 0) return MP_INPUT_NOTHING;#ifndef HAVE_NO_POSIX_SELECT FD_ZERO(&fds);#endif // Remove fd marked as dead and build the fd_set // n == number of fd's to be select() checked for(i = 0; (unsigned int)i < num_key_fd; i++) { if( (key_fds[i].flags & MP_FD_DEAD) ) { mp_input_rm_key_fd(key_fds[i].fd); i--; continue; } else if(key_fds[i].flags & MP_FD_NO_SELECT) continue; if(key_fds[i].fd > max_fd) max_fd = key_fds[i].fd;#ifndef HAVE_NO_POSIX_SELECT FD_SET(key_fds[i].fd,&fds);#endif n++; } if(num_key_fd == 0) return MP_INPUT_NOTHING;#ifndef HAVE_NO_POSIX_SELECT// if we have fd's without MP_FD_NO_SELECT flag, call select():if(n>0){ if(time >= 0 ) { tv.tv_sec=time/1000; tv.tv_usec = (time%1000)*1000; time_val = &tv; } else time_val = NULL; while(1) { if(select(max_fd+1,&fds,NULL,NULL,time_val) < 0) { if(errno == EINTR) continue; mp_msg(MSGT_INPUT,MSGL_ERR,"Select error: %s\n",strerror(errno)); } break; }}#endif for(i = last_loop + 1 ; i != last_loop ; i++) { int code = -1; // This is to check all fds in turn if((unsigned int)i >= num_key_fd) { i = -1; last_loop++; last_loop %= (num_key_fd+1); continue; }#ifndef HAVE_NO_POSIX_SELECT // No input from this fd if(! (key_fds[i].flags & MP_FD_NO_SELECT) && ! FD_ISSET(key_fds[i].fd,&fds) && key_fds[i].fd != 0) continue;#endif if(key_fds[i].fd == 0) { // stdin is handled by getch2 code = getch2(time); if(code < 0) code = MP_INPUT_NOTHING; } else code = ((mp_key_func_t)key_fds[i].read_func)(key_fds[i].fd); if(code >= 0) return code; if(code == MP_INPUT_ERROR) mp_msg(MSGT_INPUT,MSGL_ERR,"Error on key input fd %d\n",key_fds[i].fd); else if(code == MP_INPUT_DEAD) { mp_msg(MSGT_INPUT,MSGL_ERR,"Dead key input on fd %d\n",key_fds[i].fd); key_fds[i].flags |= MP_FD_DEAD; } } return MP_INPUT_NOTHING;} static mp_cmd_t*mp_input_read_keys(int time,int paused) { int code = mp_input_read_key_code(time); unsigned int j; mp_cmd_t* ret; if(mp_input_key_cb) { for( ; code >= 0 ; code = mp_input_read_key_code(0) ) { if(code & MP_KEY_DOWN) continue; code &= ~(MP_KEY_DOWN|MP_NO_REPEAT_KEY); mp_input_key_cb(code); } return NULL; } for( ; code >= 0 ; code = mp_input_read_key_code(0) ) { // key pushed if(code & MP_KEY_DOWN) { if(num_key_down > MP_MAX_KEY_DOWN) { mp_msg(MSGT_INPUT,MSGL_ERR,"Too many key down events at the same time\n"); continue; } code &= ~MP_KEY_DOWN; // Check if we don't already have this key as pushed for(j = 0; j < num_key_down; j++) { if(key_down[j] == code) break; } if(j != num_key_down) continue; key_down[num_key_down] = code; num_key_down++; last_key_down = GetTimer(); ar_state = 0; continue; } // key released // Check if the key is in the down key, driver which can't send push event // send only release event for(j = 0; j < num_key_down; j++) { if(key_down[j] == code) break; } if(j == num_key_down) { // key was not in the down keys : add it if(num_key_down > MP_MAX_KEY_DOWN) { mp_msg(MSGT_INPUT,MSGL_ERR,"Too many key down events at the same time\n"); continue; } key_down[num_key_down] = code; num_key_down++; last_key_down = 1; } // We ignore key from last combination ret = last_key_down ? mp_input_get_cmd_from_keys(num_key_down,key_down,paused) : NULL; // Remove the key if(j+1 < num_key_down) memmove(&key_down[j],&key_down[j+1],(num_key_down-(j+1))*sizeof(int)); num_key_down--; last_key_down = 0; ar_state = -1; if(ar_cmd) { mp_cmd_free(ar_cmd); ar_cmd = NULL; } if(ret) return ret; } // No input : autorepeat ? if(ar_rate > 0 && ar_state >=0 && num_key_down > 0 && ! (key_down[num_key_down-1] & MP_NO_REPEAT_KEY)) { unsigned int t = GetTimer(); // First time : wait delay if(ar_state == 0 && (t - last_key_down) >= ar_delay*1000) { ar_cmd = mp_input_get_cmd_from_keys(num_key_down,key_down,paused); if(!ar_cmd) { ar_state = -1; return NULL; } ar_state = 1; last_ar = t; return mp_cmd_clone(ar_cmd); // Then send rate / sec event } else if(ar_state == 1 && (t -last_ar) >= 1000000/ar_rate) { last_ar = t; return mp_cmd_clone(ar_cmd); } } return NULL;}static mp_cmd_t*mp_input_read_cmds(int time) {#ifndef HAVE_NO_POSIX_SELECT fd_set fds; struct timeval tv,*time_val;#endif int i,n = 0,max_fd = 0,got_cmd = 0; mp_cmd_t* ret; static int last_loop = 0; if(num_cmd_fd == 0) return NULL;#ifndef HAVE_NO_POSIX_SELECT FD_ZERO(&fds);#endif for(i = 0; (unsigned int)i < num_cmd_fd ; i++) { if( (cmd_fds[i].flags & MP_FD_DEAD) || (cmd_fds[i].flags & MP_FD_EOF) ) { mp_input_rm_cmd_fd(cmd_fds[i].fd); i--; continue; } else if(cmd_fds[i].flags & MP_FD_NO_SELECT) continue; if(cmd_fds[i].flags & MP_FD_GOT_CMD) got_cmd = 1; if(cmd_fds[i].fd > max_fd) max_fd = cmd_fds[i].fd;#ifndef HAVE_NO_POSIX_SELECT FD_SET(cmd_fds[i].fd,&fds);#endif n++; } if(num_cmd_fd == 0) return NULL;#ifndef HAVE_NO_POSIX_SELECT if(time >= 0) { tv.tv_sec=time/1000; tv.tv_usec = (time%1000)*1000; time_val = &tv; } else time_val = NULL; while(n > 0) { if((i = select(max_fd+1,&fds,NULL,NULL,time_val)) <= 0) { if(i < 0) { if(errno == EINTR) continue; mp_msg(MSGT_INPUT,MSGL_ERR,"Select error: %s\n",strerror(errno)); } if(!got_cmd) return NULL; } break; }#endif for(i = last_loop + 1; i != last_loop ; i++) { int r = 0; char* cmd; if((unsigned int)i >= num_cmd_fd) { i = -1; last_loop++; last_loop %= (num_cmd_fd+1); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -