📄 amidi.c
字号:
for (p = send_hex; *p; ++p) { int digit; if (isspace((unsigned char)*p)) { if (value >= 0) { send_data[i++] = value; value = -1; } continue; } digit = hex_value(*p); if (digit < 0) { send_data = NULL; return; } if (value < 0) { value = digit; } else { send_data[i++] = (value << 4) | digit; value = -1; } } if (value >= 0) send_data[i++] = value; send_data_length = i;}/* * prints MIDI commands, formatting them nicely */static void print_byte(unsigned char byte){ static enum { STATE_UNKNOWN, STATE_1PARAM, STATE_1PARAM_CONTINUE, STATE_2PARAM_1, STATE_2PARAM_2, STATE_2PARAM_1_CONTINUE, STATE_SYSEX } state = STATE_UNKNOWN; int newline = 0; if (byte >= 0xf8) newline = 1; else if (byte >= 0xf0) { newline = 1; switch (byte) { case 0xf0: state = STATE_SYSEX; break; case 0xf1: case 0xf3: state = STATE_1PARAM; break; case 0xf2: state = STATE_2PARAM_1; break; case 0xf4: case 0xf5: case 0xf6: state = STATE_UNKNOWN; break; case 0xf7: newline = state != STATE_SYSEX; state = STATE_UNKNOWN; break; } } else if (byte >= 0x80) { newline = 1; if (byte >= 0xc0 && byte <= 0xdf) state = STATE_1PARAM; else state = STATE_2PARAM_1; } else /* b < 0x80 */ { int running_status = 0; newline = state == STATE_UNKNOWN; switch (state) { case STATE_1PARAM: state = STATE_1PARAM_CONTINUE; break; case STATE_1PARAM_CONTINUE: running_status = 1; break; case STATE_2PARAM_1: state = STATE_2PARAM_2; break; case STATE_2PARAM_2: state = STATE_2PARAM_1_CONTINUE; break; case STATE_2PARAM_1_CONTINUE: running_status = 1; state = STATE_2PARAM_2; break; default: break; } if (running_status) fputs("\n ", stdout); } printf("%c%02X", newline ? '\n' : ' ', byte);}static void sig_handler(int dummy){ stop = 1;}static void add_send_hex_data(const char *str){ int length; char *s; length = (send_hex ? strlen(send_hex) + 1 : 0) + strlen(str) + 1; s = my_malloc(length); if (send_hex) { strcpy(s, send_hex); strcat(s, " "); } else { s[0] = '\0'; } strcat(s, str); free(send_hex); send_hex = s;}int main(int argc, char *argv[]){ static const char short_options[] = "hVlLp:s:r:S::dt:a"; static const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'V'}, {"list-devices", 0, NULL, 'l'}, {"list-rawmidis", 0, NULL, 'L'}, {"port", 1, NULL, 'p'}, {"send", 1, NULL, 's'}, {"receive", 1, NULL, 'r'}, {"send-hex", 2, NULL, 'S'}, {"dump", 0, NULL, 'd'}, {"timeout", 1, NULL, 't'}, {"active-sensing", 0, NULL, 'a'}, { } }; int c, err, ok = 0; int ignore_active_sensing = 1; int do_send_hex = 0; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { case 'h': usage(); return 0; case 'V': version(); return 0; case 'l': do_device_list = 1; break; case 'L': do_rawmidi_list = 1; break; case 'p': port_name = optarg; break; case 's': send_file_name = optarg; break; case 'r': receive_file_name = optarg; break; case 'S': do_send_hex = 1; if (optarg) add_send_hex_data(optarg); break; case 'd': dump = 1; break; case 't': timeout = atoi(optarg); break; case 'a': ignore_active_sensing = 0; break; default: error("Try `amidi --help' for more information."); return 1; } } if (do_send_hex) { /* data for -S can be specified as multiple arguments */ if (!send_hex && !argv[optind]) { error("Please specify some data for --send-hex."); return 1; } for (; argv[optind]; ++optind) add_send_hex_data(argv[optind]); } else { if (argv[optind]) { error("%s is not an option.", argv[optind]); return 1; } } if (do_rawmidi_list) rawmidi_list(); if (do_device_list) device_list(); if (do_rawmidi_list || do_device_list) return 0; if (!send_file_name && !receive_file_name && !send_hex && !dump) { error("Please specify at least one of --send, --receive, --send-hex, or --dump."); return 1; } if (send_file_name && send_hex) { error("--send and --send-hex cannot be specified at the same time."); return 1; } if (send_file_name) load_file(); else if (send_hex) parse_data(); if ((send_file_name || send_hex) && !send_data) return 1; if (receive_file_name) { receive_file = creat(receive_file_name, 0666); if (receive_file == -1) { error("cannot create %s: %s", receive_file_name, strerror(errno)); return -1; } } else { receive_file = -1; } if (receive_file_name || dump) inputp = &input; else inputp = NULL; if (send_data) outputp = &output; else outputp = NULL; if ((err = snd_rawmidi_open(inputp, outputp, port_name, SND_RAWMIDI_NONBLOCK)) < 0) { error("cannot open port \"%s\": %s", port_name, snd_strerror(err)); goto _exit2; } if (inputp) snd_rawmidi_read(input, NULL, 0); /* trigger reading */ if (send_data) { if ((err = snd_rawmidi_nonblock(output, 0)) < 0) { error("cannot set blocking mode: %s", snd_strerror(err)); goto _exit; } if ((err = snd_rawmidi_write(output, send_data, send_data_length)) < 0) { error("cannot send data: %s", snd_strerror(err)); goto _exit; } } if (inputp) { int read = 0; int npfds, time = 0; struct pollfd *pfds; timeout *= 1000; npfds = snd_rawmidi_poll_descriptors_count(input); pfds = alloca(npfds * sizeof(struct pollfd)); snd_rawmidi_poll_descriptors(input, pfds, npfds); signal(SIGINT, sig_handler); for (;;) { unsigned char buf[256]; int i, length; unsigned short revents; err = poll(pfds, npfds, 200); if (stop || (err < 0 && errno == EINTR)) break; if (err < 0) { error("poll failed: %s", strerror(errno)); break; } if (err == 0) { time += 200; if (timeout && time >= timeout) break; continue; } if ((err = snd_rawmidi_poll_descriptors_revents(input, pfds, npfds, &revents)) < 0) { error("cannot get poll events: %s", snd_strerror(errno)); break; } if (revents & (POLLERR | POLLHUP)) break; if (!(revents & POLLIN)) continue; err = snd_rawmidi_read(input, buf, sizeof(buf)); if (err == -EAGAIN) continue; if (err < 0) { error("cannot read from port \"%s\": %s", port_name, snd_strerror(err)); break; } length = 0; for (i = 0; i < err; ++i) if (!ignore_active_sensing || buf[i] != 0xfe) buf[length++] = buf[i]; if (length == 0) continue; read += length; time = 0; if (receive_file != -1) write(receive_file, buf, length); if (dump) { for (i = 0; i < length; ++i) print_byte(buf[i]); fflush(stdout); } } if (isatty(fileno(stdout))) printf("\n%d bytes read\n", read); } ok = 1;_exit: if (inputp) snd_rawmidi_close(input); if (outputp) snd_rawmidi_close(output);_exit2: if (receive_file != -1) close(receive_file); return !ok;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -