1 /* 2 * aplaymidi.c - play Standard MIDI Files to sequencer port(s) 3 * 4 * Copyright (c) 2004-2006 Clemens Ladisch <clemens (at) ladisch.de> 5 * 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 /* TODO: sequencer queue timer selection */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <stdarg.h> 27 #include <string.h> 28 #include <getopt.h> 29 #include <unistd.h> 30 #include <alsa/asoundlib.h> 31 #include "aconfig.h" 32 #include "version.h" 33 34 #define MIDI_BYTES_PER_SEC 3125 35 36 /* 37 * A MIDI event after being parsed/loaded from the file. 38 * There could be made a case for using snd_seq_event_t instead. 39 */ 40 struct event { 41 struct event *next; /* linked list */ 42 43 unsigned char type; /* SND_SEQ_EVENT_xxx */ 44 unsigned char port; /* port index */ 45 unsigned int tick; 46 union { 47 unsigned char d[3]; /* channel and data bytes */ 48 int tempo; 49 unsigned int length; /* length of sysex data */ 50 } data; 51 unsigned char sysex[0]; 52 }; 53 54 struct track { 55 struct event *first_event; /* list of all events in this track */ 56 int end_tick; /* length of this track */ 57 58 struct event *current_event; /* used while loading and playing */ 59 }; 60 61 static snd_seq_t *seq; 62 static int client; 63 static int port_count; 64 static snd_seq_addr_t *ports; 65 static int queue; 66 static int end_delay = 2; 67 static const char *file_name; 68 static FILE *file; 69 static int file_offset; /* current offset in input file */ 70 static int num_tracks; 71 static struct track *tracks; 72 static int smpte_timing; 73 74 /* prints an error message to stderr */ 75 static void errormsg(const char *msg, ...) 76 { 77 va_list ap; 78 79 va_start(ap, msg); 80 vfprintf(stderr, msg, ap); 81 va_end(ap); 82 fputc('\n', stderr); 83 } 84 85 /* prints an error message to stderr, and dies */ 86 static void fatal(const char *msg, ...) 87 { 88 va_list ap; 89 90 va_start(ap, msg); 91 vfprintf(stderr, msg, ap); 92 va_end(ap); 93 fputc('\n', stderr); 94 exit(EXIT_FAILURE); 95 } 96 97 /* memory allocation error handling */ 98 static void check_mem(void *p) 99 { 100 if (!p) 101 fatal("Out of memory"); 102 } 103 104 /* error handling for ALSA functions */ 105 static void check_snd(const char *operation, int err) 106 { 107 if (err < 0) 108 fatal("Cannot %s - %s", operation, snd_strerror(err)); 109 } 110 111 static void init_seq(void) 112 { 113 int err; 114 115 /* open sequencer */ 116 err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); 117 check_snd("open sequencer", err); 118 119 /* set our name (otherwise it's "Client-xxx") */ 120 err = snd_seq_set_client_name(seq, "aplaymidi"); 121 check_snd("set client name", err); 122 123 /* find out who we actually are */ 124 client = snd_seq_client_id(seq); 125 check_snd("get client id", client); 126 } 127 128 /* parses one or more port addresses from the string */ 129 static void parse_ports(const char *arg) 130 { 131 char *buf, *s, *port_name; 132 int err; 133 134 /* make a copy of the string because we're going to modify it */ 135 buf = strdup(arg); 136 check_mem(buf); 137 138 for (port_name = s = buf; s; port_name = s + 1) { 139 /* Assume that ports are separated by commas. We don't use 140 * spaces because those are valid in client names. */ 141 s = strchr(port_name, ','); 142 if (s) 143 *s = '\0'; 144 145 ++port_count; 146 ports = realloc(ports, port_count * sizeof(snd_seq_addr_t)); 147 check_mem(ports); 148 149 err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name); 150 if (err < 0) 151 fatal("Invalid port %s - %s", port_name, snd_strerror(err)); 152 } 153 154 free(buf); 155 } 156 157 static void create_source_port(void) 158 { 159 snd_seq_port_info_t *pinfo; 160 int err; 161 162 snd_seq_port_info_alloca(&pinfo); 163 164 /* the first created port is 0 anyway, but let's make sure ... */ 165 snd_seq_port_info_set_port(pinfo, 0); 166 snd_seq_port_info_set_port_specified(pinfo, 1); 167 168 snd_seq_port_info_set_name(pinfo, "aplaymidi"); 169 170 snd_seq_port_info_set_capability(pinfo, 0); /* sic */ 171 snd_seq_port_info_set_type(pinfo, 172 SND_SEQ_PORT_TYPE_MIDI_GENERIC | 173 SND_SEQ_PORT_TYPE_APPLICATION); 174 175 err = snd_seq_create_port(seq, pinfo); 176 check_snd("create port", err); 177 } 178 179 static void create_queue(void) 180 { 181 queue = snd_seq_alloc_named_queue(seq, "aplaymidi"); 182 check_snd("create queue", queue); 183 /* the queue is now locked, which is just fine */ 184 } 185 186 static void connect_ports(void) 187 { 188 int i, err; 189 190 /* 191 * We send MIDI events with explicit destination addresses, so we don't 192 * need any connections to the playback ports. But we connect to those 193 * anyway to force any underlying RawMIDI ports to remain open while 194 * we're playing - otherwise, ALSA would reset the port after every 195 * event. 196 */ 197 for (i = 0; i < port_count; ++i) { 198 err = snd_seq_connect_to(seq, 0, ports[i].client, ports[i].port); 199 if (err < 0) 200 fatal("Cannot connect to port %d:%d - %s", 201 ports[i].client, ports[i].port, snd_strerror(err)); 202 } 203 } 204 205 static int read_byte(void) 206 { 207 ++file_offset; 208 return getc(file); 209 } 210 211 /* reads a little-endian 32-bit integer */ 212 static int read_32_le(void) 213 { 214 int value; 215 value = read_byte(); 216 value |= read_byte() << 8; 217 value |= read_byte() << 16; 218 value |= read_byte() << 24; 219 return !feof(file) ? value : -1; 220 } 221 222 /* reads a 4-character identifier */ 223 static int read_id(void) 224 { 225 return read_32_le(); 226 } 227 #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24)) 228 229 /* reads a fixed-size big-endian number */ 230 static int read_int(int bytes) 231 { 232 int c, value = 0; 233 234 do { 235 c = read_byte(); 236 if (c == EOF) 237 return -1; 238 value = (value << 8) | c; 239 } while (--bytes); 240 return value; 241 } 242 243 /* reads a variable-length number */ 244 static int read_var(void) 245 { 246 int value, c; 247 248 c = read_byte(); 249 value = c & 0x7f; 250 if (c & 0x80) { 251 c = read_byte(); 252 value = (value << 7) | (c & 0x7f); 253 if (c & 0x80) { 254 c = read_byte(); 255 value = (value << 7) | (c & 0x7f); 256 if (c & 0x80) { 257 c = read_byte(); 258 value = (value << 7) | c; 259 if (c & 0x80) 260 return -1; 261 } 262 } 263 } 264 return !feof(file) ? value : -1; 265 } 266 267 /* allocates a new event */ 268 static struct event *new_event(struct track *track, int sysex_length) 269 { 270 struct event *event; 271 272 event = malloc(sizeof(struct event) + sysex_length); 273 check_mem(event); 274 275 event->next = NULL; 276 277 /* append at the end of the track's linked list */ 278 if (track->current_event) 279 track->current_event->next = event; 280 else 281 track->first_event = event; 282 track->current_event = event; 283 284 return event; 285 } 286 287 static void skip(int bytes) 288 { 289 while (bytes > 0) 290 read_byte(), --bytes; 291 } 292 293 /* reads one complete track from the file */ 294 static int read_track(struct track *track, int track_end) 295 { 296 int tick = 0; 297 unsigned char last_cmd = 0; 298 unsigned char port = 0; 299 300 /* the current file position is after the track ID and length */ 301 while (file_offset < track_end) { 302 unsigned char cmd; 303 struct event *event; 304 int delta_ticks, len, c; 305 306 delta_ticks = read_var(); 307 if (delta_ticks < 0) 308 break; 309 tick += delta_ticks; 310 311 c = read_byte(); 312 if (c < 0) 313 break; 314 315 if (c & 0x80) { 316 /* have command */ 317 cmd = c; 318 if (cmd < 0xf0) 319 last_cmd = cmd; 320 } else { 321 /* running status */ 322 ungetc(c, file); 323 file_offset--; 324 cmd = last_cmd; 325 if (!cmd) 326 goto _error; 327 } 328 329 switch (cmd >> 4) { 330 /* maps SMF events to ALSA sequencer events */ 331 static const unsigned char cmd_type[] = { 332 [0x8] = SND_SEQ_EVENT_NOTEOFF, 333 [0x9] = SND_SEQ_EVENT_NOTEON, 334 [0xa] = SND_SEQ_EVENT_KEYPRESS, 335 [0xb] = SND_SEQ_EVENT_CONTROLLER, 336 [0xc] = SND_SEQ_EVENT_PGMCHANGE, 337 [0xd] = SND_SEQ_EVENT_CHANPRESS, 338 [0xe] = SND_SEQ_EVENT_PITCHBEND 339 }; 340 341 case 0x8: /* channel msg with 2 parameter bytes */ 342 case 0x9: 343 case 0xa: 344 case 0xb: 345 case 0xe: 346 event = new_event(track, 0); 347 event->type = cmd_type[cmd >> 4]; 348 event->port = port; 349 event->tick = tick; 350 event->data.d[0] = cmd & 0x0f; 351 event->data.d[1] = read_byte() & 0x7f; 352 event->data.d[2] = read_byte() & 0x7f; 353 break; 354 355 case 0xc: /* channel msg with 1 parameter byte */ 356 case 0xd: 357 event = new_event(track, 0); 358 event->type = cmd_type[cmd >> 4]; 359 event->port = port; 360 event->tick = tick; 361 event->data.d[0] = cmd & 0x0f; 362 event->data.d[1] = read_byte() & 0x7f; 363 break; 364 365 case 0xf: 366 switch (cmd) { 367 case 0xf0: /* sysex */ 368 case 0xf7: /* continued sysex, or escaped commands */ 369 len = read_var(); 370 if (len < 0) 371 goto _error; 372 if (cmd == 0xf0) 373 ++len; 374 event = new_event(track, len); 375 event->type = SND_SEQ_EVENT_SYSEX; 376 event->port = port; 377 event->tick = tick; 378 event->data.length = len; 379 if (cmd == 0xf0) { 380 event->sysex[0] = 0xf0; 381 c = 1; 382 } else { 383 c = 0; 384 } 385 for (; c < len; ++c) 386 event->sysex[c] = read_byte(); 387 break; 388 389 case 0xff: /* meta event */ 390 c = read_byte(); 391 len = read_var(); 392 if (len < 0) 393 goto _error; 394 395 switch (c) { 396 case 0x21: /* port number */ 397 if (len < 1) 398 goto _error; 399 port = read_byte() % port_count; 400 skip(len - 1); 401 break; 402 403 case 0x2f: /* end of track */ 404 track->end_tick = tick; 405 skip(track_end - file_offset); 406 return 1; 407 408 case 0x51: /* tempo */ 409 if (len < 3) 410 goto _error; 411 if (smpte_timing) { 412 /* SMPTE timing doesn't change */ 413 skip(len); 414 } else { 415 event = new_event(track, 0); 416 event->type = SND_SEQ_EVENT_TEMPO; 417 event->port = port; 418 event->tick = tick; 419 event->data.tempo = read_byte() << 16; 420 event->data.tempo |= read_byte() << 8; 421 event->data.tempo |= read_byte(); 422 skip(len - 3); 423 } 424 break; 425 426 default: /* ignore all other meta events */ 427 skip(len); 428 break; 429 } 430 break; 431 432 default: /* invalid Fx command */ 433 goto _error; 434 } 435 break; 436 437 default: /* cannot happen */ 438 goto _error; 439 } 440 } 441 _error: 442 errormsg("%s: invalid MIDI data (offset %#x)", file_name, file_offset); 443 return 0; 444 } 445 446 /* reads an entire MIDI file */ 447 static int read_smf(void) 448 { 449 int header_len, type, time_division, i, err; 450 snd_seq_queue_tempo_t *queue_tempo; 451 452 /* the curren position is immediately after the "MThd" id */ 453 header_len = read_int(4); 454 if (header_len < 6) { 455 invalid_format: 456 errormsg("%s: invalid file format", file_name); 457 return 0; 458 } 459 460 type = read_int(2); 461 if (type != 0 && type != 1) { 462 errormsg("%s: type %d format is not supported", file_name, type); 463 return 0; 464 } 465 466 num_tracks = read_int(2); 467 if (num_tracks < 1 || num_tracks > 1000) { 468 errormsg("%s: invalid number of tracks (%d)", file_name, num_tracks); 469 num_tracks = 0; 470 return 0; 471 } 472 tracks = calloc(num_tracks, sizeof(struct track)); 473 if (!tracks) { 474 errormsg("out of memory"); 475 num_tracks = 0; 476 return 0; 477 } 478 479 time_division = read_int(2); 480 if (time_division < 0) 481 goto invalid_format; 482 483 /* interpret and set tempo */ 484 snd_seq_queue_tempo_alloca(&queue_tempo); 485 smpte_timing = !!(time_division & 0x8000); 486 if (!smpte_timing) { 487 /* time_division is ticks per quarter */ 488 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); /* default: 120 bpm */ 489 snd_seq_queue_tempo_set_ppq(queue_tempo, time_division); 490 } else { 491 /* upper byte is negative frames per second */ 492 i = 0x80 - ((time_division >> 8) & 0x7f); 493 /* lower byte is ticks per frame */ 494 time_division &= 0xff; 495 /* now pretend that we have quarter-note based timing */ 496 switch (i) { 497 case 24: 498 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); 499 snd_seq_queue_tempo_set_ppq(queue_tempo, 12 * time_division); 500 break; 501 case 25: 502 snd_seq_queue_tempo_set_tempo(queue_tempo, 400000); 503 snd_seq_queue_tempo_set_ppq(queue_tempo, 10 * time_division); 504 break; 505 case 29: /* 30 drop-frame */ 506 snd_seq_queue_tempo_set_tempo(queue_tempo, 100000000); 507 snd_seq_queue_tempo_set_ppq(queue_tempo, 2997 * time_division); 508 break; 509 case 30: 510 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); 511 snd_seq_queue_tempo_set_ppq(queue_tempo, 15 * time_division); 512 break; 513 default: 514 errormsg("%s: invalid number of SMPTE frames per second (%d)", 515 file_name, i); 516 return 0; 517 } 518 } 519 err = snd_seq_set_queue_tempo(seq, queue, queue_tempo); 520 if (err < 0) { 521 errormsg("Cannot set queue tempo (%u/%i)", 522 snd_seq_queue_tempo_get_tempo(queue_tempo), 523 snd_seq_queue_tempo_get_ppq(queue_tempo)); 524 return 0; 525 } 526 527 /* read tracks */ 528 for (i = 0; i < num_tracks; ++i) { 529 int len; 530 531 /* search for MTrk chunk */ 532 for (;;) { 533 int id = read_id(); 534 len = read_int(4); 535 if (feof(file)) { 536 errormsg("%s: unexpected end of file", file_name); 537 return 0; 538 } 539 if (len < 0 || len >= 0x10000000) { 540 errormsg("%s: invalid chunk length %d", file_name, len); 541 return 0; 542 } 543 if (id == MAKE_ID('M', 'T', 'r', 'k')) 544 break; 545 skip(len); 546 } 547 if (!read_track(&tracks[i], file_offset + len)) 548 return 0; 549 } 550 return 1; 551 } 552 553 static int read_riff(void) 554 { 555 /* skip file length */ 556 read_byte(); 557 read_byte(); 558 read_byte(); 559 read_byte(); 560 561 /* check file type ("RMID" = RIFF MIDI) */ 562 if (read_id() != MAKE_ID('R', 'M', 'I', 'D')) { 563 invalid_format: 564 errormsg("%s: invalid file format", file_name); 565 return 0; 566 } 567 /* search for "data" chunk */ 568 for (;;) { 569 int id = read_id(); 570 int len = read_32_le(); 571 if (feof(file)) { 572 data_not_found: 573 errormsg("%s: data chunk not found", file_name); 574 return 0; 575 } 576 if (id == MAKE_ID('d', 'a', 't', 'a')) 577 break; 578 if (len < 0) 579 goto data_not_found; 580 skip((len + 1) & ~1); 581 } 582 /* the "data" chunk must contain data in SMF format */ 583 if (read_id() != MAKE_ID('M', 'T', 'h', 'd')) 584 goto invalid_format; 585 return read_smf(); 586 } 587 588 static void cleanup_file_data(void) 589 { 590 int i; 591 struct event *event; 592 593 for (i = 0; i < num_tracks; ++i) { 594 event = tracks[i].first_event; 595 while (event) { 596 struct event *next = event->next; 597 free(event); 598 event = next; 599 } 600 } 601 num_tracks = 0; 602 free(tracks); 603 tracks = NULL; 604 } 605 606 static void handle_big_sysex(snd_seq_event_t *ev) 607 { 608 unsigned int length; 609 ssize_t event_size; 610 int err; 611 612 length = ev->data.ext.len; 613 if (length > MIDI_BYTES_PER_SEC) 614 ev->data.ext.len = MIDI_BYTES_PER_SEC; 615 event_size = snd_seq_event_length(ev); 616 if (event_size + 1 > snd_seq_get_output_buffer_size(seq)) { 617 err = snd_seq_drain_output(seq); 618 check_snd("drain output", err); 619 err = snd_seq_set_output_buffer_size(seq, event_size + 1); 620 check_snd("set output buffer size", err); 621 } 622 while (length > MIDI_BYTES_PER_SEC) { 623 err = snd_seq_event_output(seq, ev); 624 check_snd("output event", err); 625 err = snd_seq_drain_output(seq); 626 check_snd("drain output", err); 627 err = snd_seq_sync_output_queue(seq); 628 check_snd("sync output", err); 629 if (sleep(1)) 630 fatal("aborted"); 631 ev->data.ext.ptr += MIDI_BYTES_PER_SEC; 632 length -= MIDI_BYTES_PER_SEC; 633 } 634 ev->data.ext.len = length; 635 } 636 637 static void play_midi(void) 638 { 639 snd_seq_event_t ev; 640 int i, max_tick, err; 641 642 /* calculate length of the entire file */ 643 max_tick = -1; 644 for (i = 0; i < num_tracks; ++i) { 645 if (tracks[i].end_tick > max_tick) 646 max_tick = tracks[i].end_tick; 647 } 648 649 /* initialize current position in each track */ 650 for (i = 0; i < num_tracks; ++i) 651 tracks[i].current_event = tracks[i].first_event; 652 653 /* common settings for all our events */ 654 snd_seq_ev_clear(&ev); 655 ev.queue = queue; 656 ev.source.port = 0; 657 ev.flags = SND_SEQ_TIME_STAMP_TICK; 658 659 err = snd_seq_start_queue(seq, queue, NULL); 660 check_snd("start queue", err); 661 /* The queue won't be started until the START_QUEUE event is 662 * actually drained to the kernel, which is exactly what we want. */ 663 664 for (;;) { 665 struct event* event = NULL; 666 struct track* event_track = NULL; 667 int i, min_tick = max_tick + 1; 668 669 /* search next event */ 670 for (i = 0; i < num_tracks; ++i) { 671 struct track *track = &tracks[i]; 672 struct event *e2 = track->current_event; 673 if (e2 && e2->tick < min_tick) { 674 min_tick = e2->tick; 675 event = e2; 676 event_track = track; 677 } 678 } 679 if (!event) 680 break; /* end of song reached */ 681 682 /* advance pointer to next event */ 683 event_track->current_event = event->next; 684 685 /* output the event */ 686 ev.type = event->type; 687 ev.time.tick = event->tick; 688 ev.dest = ports[event->port]; 689 switch (ev.type) { 690 case SND_SEQ_EVENT_NOTEON: 691 case SND_SEQ_EVENT_NOTEOFF: 692 case SND_SEQ_EVENT_KEYPRESS: 693 snd_seq_ev_set_fixed(&ev); 694 ev.data.note.channel = event->data.d[0]; 695 ev.data.note.note = event->data.d[1]; 696 ev.data.note.velocity = event->data.d[2]; 697 break; 698 case SND_SEQ_EVENT_CONTROLLER: 699 snd_seq_ev_set_fixed(&ev); 700 ev.data.control.channel = event->data.d[0]; 701 ev.data.control.param = event->data.d[1]; 702 ev.data.control.value = event->data.d[2]; 703 break; 704 case SND_SEQ_EVENT_PGMCHANGE: 705 case SND_SEQ_EVENT_CHANPRESS: 706 snd_seq_ev_set_fixed(&ev); 707 ev.data.control.channel = event->data.d[0]; 708 ev.data.control.value = event->data.d[1]; 709 break; 710 case SND_SEQ_EVENT_PITCHBEND: 711 snd_seq_ev_set_fixed(&ev); 712 ev.data.control.channel = event->data.d[0]; 713 ev.data.control.value = 714 ((event->data.d[1]) | 715 ((event->data.d[2]) << 7)) - 0x2000; 716 break; 717 case SND_SEQ_EVENT_SYSEX: 718 snd_seq_ev_set_variable(&ev, event->data.length, 719 event->sysex); 720 handle_big_sysex(&ev); 721 break; 722 case SND_SEQ_EVENT_TEMPO: 723 snd_seq_ev_set_fixed(&ev); 724 ev.dest.client = SND_SEQ_CLIENT_SYSTEM; 725 ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; 726 ev.data.queue.queue = queue; 727 ev.data.queue.param.value = event->data.tempo; 728 break; 729 default: 730 fatal("Invalid event type %d!", ev.type); 731 } 732 733 /* this blocks when the output pool has been filled */ 734 err = snd_seq_event_output(seq, &ev); 735 check_snd("output event", err); 736 } 737 738 /* schedule queue stop at end of song */ 739 snd_seq_ev_set_fixed(&ev); 740 ev.type = SND_SEQ_EVENT_STOP; 741 ev.time.tick = max_tick; 742 ev.dest.client = SND_SEQ_CLIENT_SYSTEM; 743 ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; 744 ev.data.queue.queue = queue; 745 err = snd_seq_event_output(seq, &ev); 746 check_snd("output event", err); 747 748 /* make sure that the sequencer sees all our events */ 749 err = snd_seq_drain_output(seq); 750 check_snd("drain output", err); 751 752 /* 753 * There are three possibilities how to wait until all events have 754 * been played: 755 * 1) send an event back to us (like pmidi does), and wait for it; 756 * 2) wait for the EVENT_STOP notification for our queue which is sent 757 * by the system timer port (this would require a subscription); 758 * 3) wait until the output pool is empty. 759 * The last is the simplest. 760 */ 761 err = snd_seq_sync_output_queue(seq); 762 check_snd("sync output", err); 763 764 /* give the last notes time to die away */ 765 if (end_delay > 0) 766 sleep(end_delay); 767 } 768 769 static void play_file(void) 770 { 771 int ok; 772 773 if (!strcmp(file_name, "-")) 774 file = stdin; 775 else 776 file = fopen(file_name, "rb"); 777 if (!file) { 778 errormsg("Cannot open %s - %s", file_name, strerror(errno)); 779 return; 780 } 781 782 file_offset = 0; 783 ok = 0; 784 785 switch (read_id()) { 786 case MAKE_ID('M', 'T', 'h', 'd'): 787 ok = read_smf(); 788 break; 789 case MAKE_ID('R', 'I', 'F', 'F'): 790 ok = read_riff(); 791 break; 792 default: 793 errormsg("%s is not a Standard MIDI File", file_name); 794 break; 795 } 796 797 if (file != stdin) 798 fclose(file); 799 800 if (ok) 801 play_midi(); 802 803 cleanup_file_data(); 804 } 805 806 static void list_ports(void) 807 { 808 snd_seq_client_info_t *cinfo; 809 snd_seq_port_info_t *pinfo; 810 811 snd_seq_client_info_alloca(&cinfo); 812 snd_seq_port_info_alloca(&pinfo); 813 814 puts(" Port Client name Port name"); 815 816 snd_seq_client_info_set_client(cinfo, -1); 817 while (snd_seq_query_next_client(seq, cinfo) >= 0) { 818 int client = snd_seq_client_info_get_client(cinfo); 819 820 snd_seq_port_info_set_client(pinfo, client); 821 snd_seq_port_info_set_port(pinfo, -1); 822 while (snd_seq_query_next_port(seq, pinfo) >= 0) { 823 /* port must understand MIDI messages */ 824 if (!(snd_seq_port_info_get_type(pinfo) 825 & SND_SEQ_PORT_TYPE_MIDI_GENERIC)) 826 continue; 827 /* we need both WRITE and SUBS_WRITE */ 828 if ((snd_seq_port_info_get_capability(pinfo) 829 & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) 830 != (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) 831 continue; 832 printf("%3d:%-3d %-32.32s %s\n", 833 snd_seq_port_info_get_client(pinfo), 834 snd_seq_port_info_get_port(pinfo), 835 snd_seq_client_info_get_name(cinfo), 836 snd_seq_port_info_get_name(pinfo)); 837 } 838 } 839 } 840 841 static void usage(const char *argv0) 842 { 843 printf( 844 "Usage: %s -p client:port[,...] [-d delay] midifile ...\n" 845 "-h, --help this help\n" 846 "-V, --version print current version\n" 847 "-l, --list list all possible output ports\n" 848 "-p, --port=client:port,... set port(s) to play to\n" 849 "-d, --delay=seconds delay after song ends\n", 850 argv0); 851 } 852 853 static void version(void) 854 { 855 puts("aplaymidi version " SND_UTIL_VERSION_STR); 856 } 857 858 int main(int argc, char *argv[]) 859 { 860 static const char short_options[] = "hVlp:d:"; 861 static const struct option long_options[] = { 862 {"help", 0, NULL, 'h'}, 863 {"version", 0, NULL, 'V'}, 864 {"list", 0, NULL, 'l'}, 865 {"port", 1, NULL, 'p'}, 866 {"delay", 1, NULL, 'd'}, 867 {} 868 }; 869 int c; 870 int do_list = 0; 871 872 init_seq(); 873 874 while ((c = getopt_long(argc, argv, short_options, 875 long_options, NULL)) != -1) { 876 switch (c) { 877 case 'h': 878 usage(argv[0]); 879 return 0; 880 case 'V': 881 version(); 882 return 0; 883 case 'l': 884 do_list = 1; 885 break; 886 case 'p': 887 parse_ports(optarg); 888 break; 889 case 'd': 890 end_delay = atoi(optarg); 891 break; 892 default: 893 usage(argv[0]); 894 return 1; 895 } 896 } 897 898 if (do_list) { 899 list_ports(); 900 } else { 901 if (port_count < 1) { 902 /* use env var for compatibility with pmidi */ 903 const char *ports_str = getenv("ALSA_OUTPUT_PORTS"); 904 if (ports_str) 905 parse_ports(ports_str); 906 if (port_count < 1) { 907 errormsg("Please specify at least one port with --port."); 908 return 1; 909 } 910 } 911 if (optind >= argc) { 912 errormsg("Please specify a file to play."); 913 return 1; 914 } 915 916 create_source_port(); 917 create_queue(); 918 connect_ports(); 919 920 for (; optind < argc; ++optind) { 921 file_name = argv[optind]; 922 play_file(); 923 } 924 } 925 snd_seq_close(seq); 926 return 0; 927 } 928