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