📄 server_c.c
字号:
* (65536.0/500000.0) / (double)curr_timebase, sample_correction = (int32)(a) & 0xFFFF; sample_increment = (int32)(a) >> 16;}static void add_tick(int tick){ int32 samples_to_do; MidiEvent ev; samples_to_do = sample_increment * tick; sample_cum += sample_correction * tick; if(sample_cum & 0xFFFF0000) { samples_to_do += ((sample_cum >> 16) & 0xFFFF); sample_cum &= 0x0000FFFF; } curr_event_samples += samples_to_do; curr_tick += tick; ev.type = ME_NONE; seq_play_event(&ev);}static int tick2sample(int tick){ int32 samples, cum; samples = sample_increment * tick; cum = sample_correction * tick; if(cum & 0xFFFF0000) samples += ((sample_cum >> 16) & 0xFFFF); return samples;}int time2tick(double sec){ return (int)(sec * curr_timebase);}static void stop_playing(void){ if(upper_voices) { MidiEvent ev; ev.type = ME_EOT; ev.a = 0; ev.b = 0; seq_play_event(&ev); aq_flush(0); }}static int do_control_command(void);static int do_control_command_nonblock(void);static int do_sequencer(void);static void do_chn_voice(uint8 *);static void do_chn_common(uint8 *);static void do_timing(uint8 *);static void do_sysex(uint8 *, int len);static void do_extended(uint8 *);static void do_timeout(void);static void server_seq_sync(double tm);static uint8 data_buffer[BUFSIZ];static int data_buffer_len;static void doit(void){ memset(&control_fd_buffer, 0, sizeof(control_fd_buffer)); control_fd_buffer.fd = control_fd; send_status(220, "TiMidity++ v%s ready", timidity_version);/* while(data_fd != -1 && control_fd != -1) */ while(control_fd != -1) { fd_set fds; int n, maxfd; if(data_fd == -1) { if(do_control_command()) break; } else { long usec; FD_ZERO(&fds); FD_SET(control_fd, &fds); FD_SET(data_fd, &fds); if(control_fd > data_fd) maxfd = control_fd; else maxfd = data_fd; if(data_fd != -1) { double wait_time; int32 filled; filled = aq_filled(); if(!tmr_running && filled <= 0) usec = -1; else { wait_time = (double)filled / play_mode->rate - low_time_at; if(wait_time <= 0) usec = 0; else usec = (long)(wait_time * 1000000); } } else usec = -1; if(usec >= 0) { struct timeval timeout; timeout.tv_sec = usec / 1000000; timeout.tv_usec = usec % 1000000; n = select(maxfd + 1, &fds, NULL, NULL, &timeout); } else n = select(maxfd + 1, &fds, NULL, NULL, NULL); if(n < 0) { perror("select"); break; } if(n == 0) { if(ctl.verbosity >= VERB_DEBUG) { putchar(','); fflush(stdout); } do_timeout(); continue; } if(control_fd != -1 && FD_ISSET(control_fd, &fds)) { if(do_control_command()) { close(control_fd); control_fd = -1; } } else if(data_fd != -1 && FD_ISSET(data_fd, &fds)) { if(do_sequencer()) { close(data_fd); data_fd = -1; send_status(403, "Data connection is closed"); } } } } if(data_fd != -1) stop_playing();}static void do_timeout(void){ double fill_time; if(data_fd == -1 || !IS_STREAM_TRACE) return; aq_add(NULL, 0); fill_time = high_time_at - (double)aq_filled() / play_mode->rate; if(fill_time <= 0) return; if(tmr_running) add_tick(time2tick(fill_time)); else { MidiEvent ev; event_time_offset += (int32)(fill_time * play_mode->rate); ev.time = curr_event_samples + event_time_offset; ev.type = ME_NONE; play_event(&ev); }}/* -1=error, 0=success, 1=connection-closed */static int data_flush(int discard){ fd_set fds; char buff[BUFSIZ]; struct timeval timeout; int n; while(1) { FD_ZERO(&fds); FD_SET(data_fd, &fds); timeout.tv_sec = 0; if(discard) timeout.tv_usec = 100000; else timeout.tv_usec = 0; if((n = select(data_fd + 1, &fds, NULL, NULL, &timeout)) < 0) { perror("select"); return -1; } if(n == 0) break; if(discard) { if((n = read(data_fd, buff, sizeof(buff))) < 0) { perror("read"); return -1; } if(n == 0) return 1; } else { int status; if((status = do_sequencer()) != 0) return status; } } return 0;}static void server_seq_sync(double tm){ double t; aq_soft_flush(); t = (double)aq_filled() / play_mode->rate; if(t > tm) usleep((unsigned long)((t - tm) * 1000000));}static void server_reset(void){ playmidi_stream_init(); if(free_instruments_afterwards) free_instruments(0); data_buffer_len = 0; do_sysex(NULL, 0); /* Initialize SysEx buffer */ low_time_at = DEFAULT_LOW_TIMEAT; high_time_at = DEFAULT_HIGH_TIMEAT; reduce_voice_threshold = 0; /* Disable auto reduction voice */ compute_sample_increment(); tmr_reset(); tmr_running = 0; start_time = get_current_calender_time();}/* -1=error, 0=success, 1=connection-closed */static int do_control_command(void){ int status; char *params[MAX_GETCMD_PARAMS]; int nparams; int i; if((status = control_getcmd(params, &nparams)) == -1) return -1; if(status == 1) { send_status(500, "Error"); return 1; } if(nparams == 0 || *params == NULL || **params == '\0') return 0; for(i = 0; cmd_table[i].cmd; i++) if(strcasecmp(params[0], cmd_table[i].cmd) == 0) { if(nparams < cmd_table[i].minarg) return send_status(501, "'%s': Arguments is too few", params[0]); if(nparams > cmd_table[i].maxarg) return send_status(501, "'%s': Arguments is too many", params[0]); return cmd_table[i].proc(nparams, params); } return send_status(500, "'%s': command not understood.", params[0]);}static int cmd_help(int argc, char **argv){ int i; if(send_status(200, "Help ok")) return -1; for(i = 0; cmd_table[i].cmd; i++) { if(fdputs(cmd_table[i].help, control_fd)) return -1; if(fdputs("\n", control_fd)) return -1; } return fdputs(".\n", control_fd);}static int cmd_open(int argc, char **argv){ int sock; struct sockaddr_in in; int addrlen; int port; if(data_fd != -1) return send_status(125, "Data connection is already opened"); if(strcasecmp(argv[1], "lsb") == 0) is_lsb_data = 1; else if(strcasecmp(argv[1], "msb") == 0) is_lsb_data = 0; else return send_status(502, "OPEN: Invalid argument: %s", argv[1]); port = data_port; if((sock = pasv_open(&port)) == -1) return send_status(511, "Can't open data connection"); addrlen = sizeof(in); memset(&in, 0, addrlen); send_status(200, "%d is ready acceptable", port); alarm(SIG_TIMEOUT_SEC); data_fd = accept(sock, (struct sockaddr *)&in, &addrlen); alarm(0); if(data_fd < 0) { send_status(512, "Accept error"); close(sock); return 0; } close(sock); if(control_client.sin_addr.s_addr != in.sin_addr.s_addr) return send_status(513, "Security violation: Address mismatch"); send_status(200, "Ready data connection"); data_buffer_len = 0; do_sysex(NULL, 0); /* Initialize SysEx buffer */ tmr_reset(); return 0;}static int cmd_close(int argc, char **argv){ if(data_fd != -1) { close(data_fd); data_fd = -1; return send_status(302, "Data connection is closed"); } return send_status(302, "Data connection is already closed");}static int cmd_queue(int argc, char **argv){ int32 qsamples; aq_add(NULL, 0); /* Update software queue */ if(!aq_fill_buffer_flag) qsamples = aq_soft_filled() + aq_filled(); else qsamples = 0; return send_status(200, "%f sec", (double)qsamples / play_mode->rate);}static int cmd_maxqueue(int argc, char **argv){ return send_status(200, "%f sec", (double)aq_get_dev_queuesize() / play_mode->rate);}static int cmd_time(int argc, char **argv){ return send_status(200, "%f sec", (double)aq_samples());}static int cmd_quit(int argc, char **argv){ send_status(200, "Bye"); return 1;}static int cmd_timebase(int argc, char **argv){ int i; if(argc == 1) return send_status(200, "%d OK", curr_timebase); i = atoi(argv[1]); if(i < 1) i = 1; else if(i > 1000) i = 1000; if(i != curr_timebase) { curr_timebase = i; compute_sample_increment(); tick_offs = curr_tick; start_time = get_current_calender_time(); } return send_status(200, "OK");}static int cmd_patch(int argc, char **argv){ int dr, bank, prog; if(strcasecmp(argv[1], "drumset") == 0) dr = 1; else if(strcasecmp(argv[1], "bank") == 0) dr = 0; else return send_status(502, "PATCH: Invalid argument: %s", argv[1]); bank = atoi(argv[2]); prog = atoi(argv[3]); if(bank < 0 || bank > 127 || prog < 0 || prog > 127) return send_status(502, "PATCH: Invalid argument"); if(play_midi_load_instrument(dr, bank, prog) == NULL) return send_status(514, "PATCH: Can't load the patch"); return send_status(200, "OK");}static int cmd_reset(int argc, char **argv){ int status; if(data_fd >= 0) { stop_playing(); if((status = data_flush(1)) != 0) return status; } server_reset(); return send_status(200, "OK");}static int cmd_autoreduce(int argc, char **argv){ if(strcasecmp(argv[1], "on") == 0) { if(argc == 3) reduce_voice_threshold = atoi(argv[2]); else reduce_voice_threshold = -1; } else if(strcasecmp(argv[1], "off") == 0) reduce_voice_threshold = 0; else return send_status(502, "AUTOREDUCE: Invalid argument: %s", argv[1]); return send_status(200, "OK");}static int cmd_setbuf(int argc, char **argv){ low_time_at = atof(argv[1]); high_time_at = atof(argv[1]); return send_status(200, "OK");}static int cmd_nop(int argc, char **argv){ return send_status(200, "NOP OK");}static int do_control_command_nonblock(void){ struct timeval timeout; int n; fd_set fds; if(control_fd == -1) return 1; FD_ZERO(&fds); FD_SET(control_fd, &fds); timeout.tv_sec = 0; timeout.tv_usec = 0; n = select(control_fd + 1, &fds, NULL, NULL, &timeout); if(n > 0 && FD_ISSET(control_fd, &fds)) return do_control_command(); return 0;}static int fdgets(char *buff, size_t buff_size, struct fd_read_buffer *p){ int n, len, count, size, fd; char *buff_endp = buff + buff_size - 1, *pbuff, *beg; fd = p->fd; if(buff_size == 0) return 0; else if(buff_size == 1) /* buff == buff_endp */ { *buff = '\0'; return 0; } len = 0; count = p->count; size = p->size; pbuff = p->buff; beg = buff; do { if(count == size) { if((n = read(fd, pbuff, BUFSIZ)) <= 0) { *buff = '\0'; if(n == 0) { p->count = p->size = 0; return buff - beg; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -