2 * aplaymidi.c - play Standard MIDI Files to sequencer port(s)
4 * Copyright (c) 2004-2006 Clemens Ladisch <clemens@ladisch.de>
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.
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.
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
22 /* TODO: sequencer queue timer selection */
31 #include <alsa/asoundlib.h>
33 #include <alsa/ump_msg.h>
36 * 31.25 kbaud, one start bit, eight data bits, two stop bits.
37 * (The MIDI spec says one stop bit, but every transmitter uses two, just to be
38 * sure, so we better not exceed that to avoid overflowing the output buffer.)
40 #define MIDI_BYTES_PER_SEC (31250 / (1 + 8 + 2))
43 * A MIDI event after being parsed/loaded from the file.
44 * There could be made a case for using snd_seq_event_t instead.
47 struct event *next; /* linked list */
49 unsigned char type; /* SND_SEQ_EVENT_xxx */
50 unsigned char port; /* port index */
53 unsigned char d[3]; /* channel and data bytes */
55 unsigned int length; /* length of sysex data */
57 unsigned char sysex[0];
61 struct event *first_event; /* list of all events in this track */
62 int end_tick; /* length of this track */
64 struct event *current_event; /* used while loading and playing */
67 static snd_seq_t *seq;
69 static int port_count;
70 static snd_seq_addr_t *ports;
72 static int end_delay = 2;
73 static const char *file_name;
75 static int file_offset; /* current offset in input file */
76 static int num_tracks;
77 static struct track *tracks;
78 static int smpte_timing;
81 /* prints an error message to stderr */
82 static void errormsg(const char *msg, ...)
87 vfprintf(stderr, msg, ap);
92 /* prints an error message to stderr, and dies */
93 static void fatal(const char *msg, ...)
98 vfprintf(stderr, msg, ap);
104 /* memory allocation error handling */
105 static void check_mem(void *p)
108 fatal("Out of memory");
111 /* error handling for ALSA functions */
112 static void check_snd(const char *operation, int err)
115 fatal("Cannot %s - %s", operation, snd_strerror(err));
118 static void init_seq(void)
123 err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0);
124 check_snd("open sequencer", err);
126 /* set our name (otherwise it's "Client-xxx") */
127 err = snd_seq_set_client_name(seq, "aplaymidi");
128 check_snd("set client name", err);
130 /* find out who we actually are */
131 client = snd_seq_client_id(seq);
132 check_snd("get client id", client);
135 /* parses one or more port addresses from the string */
136 static void parse_ports(const char *arg)
138 char *buf, *s, *port_name;
141 /* make a copy of the string because we're going to modify it */
145 for (port_name = s = buf; s; port_name = s + 1) {
146 /* Assume that ports are separated by commas. We don't use
147 * spaces because those are valid in client names. */
148 s = strchr(port_name, ',');
153 ports = realloc(ports, port_count * sizeof(snd_seq_addr_t));
156 err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name);
158 fatal("Invalid port %s - %s", port_name, snd_strerror(err));
164 static void create_source_port(void)
166 snd_seq_port_info_t *pinfo;
169 snd_seq_port_info_alloca(&pinfo);
171 /* the first created port is 0 anyway, but let's make sure ... */
172 snd_seq_port_info_set_port(pinfo, 0);
173 snd_seq_port_info_set_port_specified(pinfo, 1);
175 snd_seq_port_info_set_name(pinfo, "aplaymidi");
177 snd_seq_port_info_set_capability(pinfo, 0); /* sic */
178 snd_seq_port_info_set_type(pinfo,
179 SND_SEQ_PORT_TYPE_MIDI_GENERIC |
180 SND_SEQ_PORT_TYPE_APPLICATION);
182 err = snd_seq_create_port(seq, pinfo);
183 check_snd("create port", err);
186 static void create_queue(void)
188 queue = snd_seq_alloc_named_queue(seq, "aplaymidi");
189 check_snd("create queue", queue);
190 /* the queue is now locked, which is just fine */
193 static void connect_ports(void)
198 * We send MIDI events with explicit destination addresses, so we don't
199 * need any connections to the playback ports. But we connect to those
200 * anyway to force any underlying RawMIDI ports to remain open while
201 * we're playing - otherwise, ALSA would reset the port after every
204 for (i = 0; i < port_count; ++i) {
205 err = snd_seq_connect_to(seq, 0, ports[i].client, ports[i].port);
207 fatal("Cannot connect to port %d:%d - %s",
208 ports[i].client, ports[i].port, snd_strerror(err));
212 static int read_byte(void)
218 /* reads a little-endian 32-bit integer */
219 static int read_32_le(void)
223 value |= read_byte() << 8;
224 value |= read_byte() << 16;
225 value |= read_byte() << 24;
226 return !feof(file) ? value : -1;
229 /* reads a 4-character identifier */
230 static int read_id(void)
234 #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
236 /* reads a fixed-size big-endian number */
237 static int read_int(int bytes)
245 value = (value << 8) | c;
250 /* reads a variable-length number */
251 static int read_var(void)
259 value = (value << 7) | (c & 0x7f);
262 value = (value << 7) | (c & 0x7f);
265 value = (value << 7) | c;
271 return !feof(file) ? value : -1;
274 /* allocates a new event */
275 static struct event *new_event(struct track *track, int sysex_length)
279 event = malloc(sizeof(struct event) + sysex_length);
284 /* append at the end of the track's linked list */
285 if (track->current_event)
286 track->current_event->next = event;
288 track->first_event = event;
289 track->current_event = event;
294 static void skip(int bytes)
297 read_byte(), --bytes;
300 /* reads one complete track from the file */
301 static int read_track(struct track *track, int track_end)
304 unsigned char last_cmd = 0;
305 unsigned char port = 0;
307 /* the current file position is after the track ID and length */
308 while (file_offset < track_end) {
311 int delta_ticks, len, c;
313 delta_ticks = read_var();
337 /* maps SMF events to ALSA sequencer events */
338 static const unsigned char cmd_type[] = {
339 [0x8] = SND_SEQ_EVENT_NOTEOFF,
340 [0x9] = SND_SEQ_EVENT_NOTEON,
341 [0xa] = SND_SEQ_EVENT_KEYPRESS,
342 [0xb] = SND_SEQ_EVENT_CONTROLLER,
343 [0xc] = SND_SEQ_EVENT_PGMCHANGE,
344 [0xd] = SND_SEQ_EVENT_CHANPRESS,
345 [0xe] = SND_SEQ_EVENT_PITCHBEND
348 case 0x8: /* channel msg with 2 parameter bytes */
353 event = new_event(track, 0);
354 event->type = cmd_type[cmd >> 4];
357 event->data.d[0] = cmd & 0x0f;
358 event->data.d[1] = read_byte() & 0x7f;
359 event->data.d[2] = read_byte() & 0x7f;
362 case 0xc: /* channel msg with 1 parameter byte */
364 event = new_event(track, 0);
365 event->type = cmd_type[cmd >> 4];
368 event->data.d[0] = cmd & 0x0f;
369 event->data.d[1] = read_byte() & 0x7f;
374 case 0xf0: /* sysex */
375 case 0xf7: /* continued sysex, or escaped commands */
381 event = new_event(track, len);
382 event->type = SND_SEQ_EVENT_SYSEX;
385 event->data.length = len;
387 event->sysex[0] = 0xf0;
393 event->sysex[c] = read_byte();
396 case 0xff: /* meta event */
403 case 0x21: /* port number */
406 port = read_byte() % port_count;
410 case 0x2f: /* end of track */
411 track->end_tick = tick;
412 skip(track_end - file_offset);
415 case 0x51: /* tempo */
419 /* SMPTE timing doesn't change */
422 event = new_event(track, 0);
423 event->type = SND_SEQ_EVENT_TEMPO;
426 event->data.tempo = read_byte() << 16;
427 event->data.tempo |= read_byte() << 8;
428 event->data.tempo |= read_byte();
433 default: /* ignore all other meta events */
439 default: /* invalid Fx command */
444 default: /* cannot happen */
449 errormsg("%s: invalid MIDI data (offset %#x)", file_name, file_offset);
453 /* reads an entire MIDI file */
454 static int read_smf(void)
456 int header_len, type, time_division, i, err;
457 snd_seq_queue_tempo_t *queue_tempo;
459 /* the curren position is immediately after the "MThd" id */
460 header_len = read_int(4);
461 if (header_len < 6) {
463 errormsg("%s: invalid file format", file_name);
468 if (type != 0 && type != 1) {
469 errormsg("%s: type %d format is not supported", file_name, type);
473 num_tracks = read_int(2);
474 if (num_tracks < 1 || num_tracks > 1000) {
475 errormsg("%s: invalid number of tracks (%d)", file_name, num_tracks);
479 tracks = calloc(num_tracks, sizeof(struct track));
481 errormsg("out of memory");
486 time_division = read_int(2);
487 if (time_division < 0)
490 /* interpret and set tempo */
491 snd_seq_queue_tempo_alloca(&queue_tempo);
492 smpte_timing = !!(time_division & 0x8000);
494 /* time_division is ticks per quarter */
495 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); /* default: 120 bpm */
496 snd_seq_queue_tempo_set_ppq(queue_tempo, time_division);
498 /* upper byte is negative frames per second */
499 i = 0x80 - ((time_division >> 8) & 0x7f);
500 /* lower byte is ticks per frame */
501 time_division &= 0xff;
502 /* now pretend that we have quarter-note based timing */
505 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000);
506 snd_seq_queue_tempo_set_ppq(queue_tempo, 12 * time_division);
509 snd_seq_queue_tempo_set_tempo(queue_tempo, 400000);
510 snd_seq_queue_tempo_set_ppq(queue_tempo, 10 * time_division);
512 case 29: /* 30 drop-frame */
513 snd_seq_queue_tempo_set_tempo(queue_tempo, 100000000);
514 snd_seq_queue_tempo_set_ppq(queue_tempo, 2997 * time_division);
517 snd_seq_queue_tempo_set_tempo(queue_tempo, 500000);
518 snd_seq_queue_tempo_set_ppq(queue_tempo, 15 * time_division);
521 errormsg("%s: invalid number of SMPTE frames per second (%d)",
526 err = snd_seq_set_queue_tempo(seq, queue, queue_tempo);
528 errormsg("Cannot set queue tempo (%u/%i)",
529 snd_seq_queue_tempo_get_tempo(queue_tempo),
530 snd_seq_queue_tempo_get_ppq(queue_tempo));
535 for (i = 0; i < num_tracks; ++i) {
538 /* search for MTrk chunk */
543 errormsg("%s: unexpected end of file", file_name);
546 if (len < 0 || len >= 0x10000000) {
547 errormsg("%s: invalid chunk length %d", file_name, len);
550 if (id == MAKE_ID('M', 'T', 'r', 'k'))
554 if (!read_track(&tracks[i], file_offset + len))
560 static int read_riff(void)
562 /* skip file length */
568 /* check file type ("RMID" = RIFF MIDI) */
569 if (read_id() != MAKE_ID('R', 'M', 'I', 'D')) {
571 errormsg("%s: invalid file format", file_name);
574 /* search for "data" chunk */
577 int len = read_32_le();
580 errormsg("%s: data chunk not found", file_name);
583 if (id == MAKE_ID('d', 'a', 't', 'a'))
587 skip((len + 1) & ~1);
589 /* the "data" chunk must contain data in SMF format */
590 if (read_id() != MAKE_ID('M', 'T', 'h', 'd'))
595 static void cleanup_file_data(void)
600 for (i = 0; i < num_tracks; ++i) {
601 event = tracks[i].first_event;
603 struct event *next = event->next;
613 static void handle_big_sysex(snd_seq_event_t *ev)
619 length = ev->data.ext.len;
620 if (length > MIDI_BYTES_PER_SEC)
621 ev->data.ext.len = MIDI_BYTES_PER_SEC;
622 event_size = snd_seq_event_length(ev);
623 if (event_size + 1 > (ssize_t)snd_seq_get_output_buffer_size(seq)) {
624 err = snd_seq_drain_output(seq);
625 check_snd("drain output", err);
626 err = snd_seq_set_output_buffer_size(seq, event_size + 1);
627 check_snd("set output buffer size", err);
629 while (length > MIDI_BYTES_PER_SEC) {
630 err = snd_seq_event_output(seq, ev);
631 check_snd("output event", err);
632 err = snd_seq_drain_output(seq);
633 check_snd("drain output", err);
634 err = snd_seq_sync_output_queue(seq);
635 check_snd("sync output", err);
638 ev->data.ext.ptr = (char *)ev->data.ext.ptr + MIDI_BYTES_PER_SEC;
639 length -= MIDI_BYTES_PER_SEC;
641 ev->data.ext.len = length;
644 static int fill_legacy_event(struct event* event, snd_seq_event_t *ev)
646 ev->type = event->type;
648 case SND_SEQ_EVENT_NOTEON:
649 case SND_SEQ_EVENT_NOTEOFF:
650 case SND_SEQ_EVENT_KEYPRESS:
651 snd_seq_ev_set_fixed(ev);
652 ev->data.note.channel = event->data.d[0];
653 ev->data.note.note = event->data.d[1];
654 ev->data.note.velocity = event->data.d[2];
656 case SND_SEQ_EVENT_CONTROLLER:
657 snd_seq_ev_set_fixed(ev);
658 ev->data.control.channel = event->data.d[0];
659 ev->data.control.param = event->data.d[1];
660 ev->data.control.value = event->data.d[2];
662 case SND_SEQ_EVENT_PGMCHANGE:
663 case SND_SEQ_EVENT_CHANPRESS:
664 snd_seq_ev_set_fixed(ev);
665 ev->data.control.channel = event->data.d[0];
666 ev->data.control.value = event->data.d[1];
668 case SND_SEQ_EVENT_PITCHBEND:
669 snd_seq_ev_set_fixed(ev);
670 ev->data.control.channel = event->data.d[0];
671 ev->data.control.value = ((event->data.d[1]) |
672 ((event->data.d[2]) << 7)) - 0x2000;
674 case SND_SEQ_EVENT_SYSEX:
675 snd_seq_ev_set_variable(ev, event->data.length, event->sysex);
676 handle_big_sysex(ev);
679 fatal("Invalid event type %d!", ev->type);
684 static unsigned char to_ump_status(unsigned char ev_type)
687 case SND_SEQ_EVENT_NOTEON:
688 return SND_UMP_MSG_NOTE_ON;
689 case SND_SEQ_EVENT_NOTEOFF:
690 return SND_UMP_MSG_NOTE_OFF;
691 case SND_SEQ_EVENT_KEYPRESS:
692 return SND_UMP_MSG_POLY_PRESSURE;
693 case SND_SEQ_EVENT_CONTROLLER:
694 return SND_UMP_MSG_CONTROL_CHANGE;
695 case SND_SEQ_EVENT_PGMCHANGE:
696 return SND_UMP_MSG_PROGRAM_CHANGE;
697 case SND_SEQ_EVENT_CHANPRESS:
698 return SND_UMP_MSG_CHANNEL_PRESSURE;
699 case SND_SEQ_EVENT_PITCHBEND:
700 return SND_UMP_MSG_PITCHBEND;
706 static int fill_ump_event(struct event* event, snd_seq_ump_event_t *ump_ev,
707 const snd_seq_event_t *ev)
709 snd_ump_msg_midi1_t ump = {};
710 unsigned char status = to_ump_status(event->type);
712 memcpy(ump_ev, ev, sizeof(*ev));
714 return 0; /* handle as is */
716 ump.note_on.type = SND_UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE;
717 switch (event->type) {
718 case SND_SEQ_EVENT_NOTEON:
719 /* correct the note-on with velocity 0 to note-off;
720 * UMP may handle velocity 0 differently
722 if (!ev->data.note.velocity)
723 status = SND_UMP_MSG_NOTE_OFF;
725 case SND_SEQ_EVENT_NOTEOFF:
726 case SND_SEQ_EVENT_KEYPRESS:
727 ump.note_on.status = status;
728 ump.note_on.channel = event->data.d[0];
729 ump.note_on.note = event->data.d[1];
730 ump.note_on.velocity = event->data.d[2];
732 case SND_SEQ_EVENT_CONTROLLER:
733 ump.control_change.status = status;
734 ump.control_change.channel = event->data.d[0];
735 ump.control_change.index = event->data.d[1];
736 ump.control_change.data = event->data.d[2];
738 case SND_SEQ_EVENT_PGMCHANGE:
739 ump.program_change.status = status;
740 ump.program_change.channel = event->data.d[0];
741 ump.program_change.program = event->data.d[1];
743 case SND_SEQ_EVENT_CHANPRESS:
744 ump.channel_pressure.status = status;
745 ump.channel_pressure.channel = event->data.d[0];
746 ump.channel_pressure.data = event->data.d[1];
748 case SND_SEQ_EVENT_PITCHBEND:
749 ump.pitchbend.status = status;
750 ump.pitchbend.channel = event->data.d[0];
751 ump.pitchbend.data_msb = event->data.d[2];
752 ump.pitchbend.data_lsb = event->data.d[1];
755 return 0; /* handle as is */
757 snd_seq_ev_set_ump_data(ump_ev, &ump, sizeof(ump));
761 static void play_midi(void)
763 snd_seq_ump_event_t ump_ev;
765 int i, max_tick, err;
767 /* calculate length of the entire file */
769 for (i = 0; i < num_tracks; ++i) {
770 if (tracks[i].end_tick > max_tick)
771 max_tick = tracks[i].end_tick;
774 /* initialize current position in each track */
775 for (i = 0; i < num_tracks; ++i)
776 tracks[i].current_event = tracks[i].first_event;
778 /* common settings for all our events */
779 snd_seq_ev_clear(&ev);
782 ev.flags = SND_SEQ_TIME_STAMP_TICK;
784 err = snd_seq_start_queue(seq, queue, NULL);
785 check_snd("start queue", err);
786 /* The queue won't be started until the START_QUEUE event is
787 * actually drained to the kernel, which is exactly what we want. */
790 struct event* event = NULL;
791 struct track* event_track = NULL;
792 int i, min_tick = max_tick + 1;
794 /* search next event */
795 for (i = 0; i < num_tracks; ++i) {
796 struct track *track = &tracks[i];
797 struct event *e2 = track->current_event;
798 if (e2 && e2->tick < (unsigned int)min_tick) {
805 break; /* end of song reached */
807 /* advance pointer to next event */
808 event_track->current_event = event->next;
810 /* output the event */
811 ev.time.tick = event->tick;
812 ev.dest = ports[event->port];
813 if (event->type == SND_SEQ_EVENT_TEMPO) {
814 snd_seq_ev_set_fixed(&ev);
815 ev.type = event->type;
816 ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
817 ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
818 ev.data.queue.queue = queue;
819 ev.data.queue.param.value = event->data.tempo;
821 err = fill_legacy_event(event, &ev);
827 err = fill_ump_event(event, &ump_ev, &ev);
830 err = snd_seq_ump_event_output(seq, &ump_ev);
831 check_snd("output event", err);
835 /* this blocks when the output pool has been filled */
836 err = snd_seq_event_output(seq, &ev);
837 check_snd("output event", err);
840 /* schedule queue stop at end of song */
841 snd_seq_ev_set_fixed(&ev);
842 ev.type = SND_SEQ_EVENT_STOP;
843 ev.time.tick = max_tick;
844 ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
845 ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
846 ev.data.queue.queue = queue;
847 err = snd_seq_event_output(seq, &ev);
848 check_snd("output event", err);
850 /* make sure that the sequencer sees all our events */
851 err = snd_seq_drain_output(seq);
852 check_snd("drain output", err);
855 * There are three possibilities how to wait until all events have
857 * 1) send an event back to us (like pmidi does), and wait for it;
858 * 2) wait for the EVENT_STOP notification for our queue which is sent
859 * by the system timer port (this would require a subscription);
860 * 3) wait until the output pool is empty.
861 * The last is the simplest.
863 err = snd_seq_sync_output_queue(seq);
864 check_snd("sync output", err);
866 /* give the last notes time to die away */
871 static void play_file(void)
875 if (!strcmp(file_name, "-"))
878 file = fopen(file_name, "rb");
880 errormsg("Cannot open %s - %s", file_name, strerror(errno));
888 case MAKE_ID('M', 'T', 'h', 'd'):
891 case MAKE_ID('R', 'I', 'F', 'F'):
895 errormsg("%s is not a Standard MIDI File", file_name);
908 static void list_ports(void)
910 snd_seq_client_info_t *cinfo;
911 snd_seq_port_info_t *pinfo;
913 snd_seq_client_info_alloca(&cinfo);
914 snd_seq_port_info_alloca(&pinfo);
916 puts(" Port Client name Port name");
918 snd_seq_client_info_set_client(cinfo, -1);
919 while (snd_seq_query_next_client(seq, cinfo) >= 0) {
920 int client = snd_seq_client_info_get_client(cinfo);
922 snd_seq_port_info_set_client(pinfo, client);
923 snd_seq_port_info_set_port(pinfo, -1);
924 while (snd_seq_query_next_port(seq, pinfo) >= 0) {
925 /* port must understand MIDI messages */
926 if (!(snd_seq_port_info_get_type(pinfo)
927 & SND_SEQ_PORT_TYPE_MIDI_GENERIC))
929 /* we need both WRITE and SUBS_WRITE */
930 if ((snd_seq_port_info_get_capability(pinfo)
931 & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE))
932 != (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE))
934 printf("%3d:%-3d %-32.32s %s\n",
935 snd_seq_port_info_get_client(pinfo),
936 snd_seq_port_info_get_port(pinfo),
937 snd_seq_client_info_get_name(cinfo),
938 snd_seq_port_info_get_name(pinfo));
943 static void usage(const char *argv0)
946 "Usage: %s -p client:port[,...] [-d delay] midifile ...\n"
947 "-h, --help this help\n"
948 "-V, --version print current version\n"
949 "-l, --list list all possible output ports\n"
950 "-p, --port=client:port,... set port(s) to play to\n"
951 "-u, --ump=version UMP output (only version=1 is supported)\n"
952 "-d, --delay=seconds delay after song ends\n",
956 static void version(void)
958 puts("aplaymidi version " SND_UTIL_VERSION_STR);
961 #define OPTIONS "hVlp:d:u:"
963 int main(int argc, char *argv[])
965 static const char short_options[] = OPTIONS;
966 static const struct option long_options[] = {
967 {"help", 0, NULL, 'h'},
968 {"version", 0, NULL, 'V'},
969 {"list", 0, NULL, 'l'},
970 {"port", 1, NULL, 'p'},
971 {"ump", 1, NULL, 'u'},
972 {"delay", 1, NULL, 'd'},
980 while ((c = getopt_long(argc, argv, short_options,
981 long_options, NULL)) != -1) {
996 end_delay = atoi(optarg);
999 ump_mode = atoi(optarg);
1000 if (ump_mode < 0 || ump_mode > 1)
1001 fatal("Only MIDI 1.0 is supported");
1012 err = snd_seq_set_client_midi_version(seq, SND_SEQ_CLIENT_UMP_MIDI_1_0);
1013 check_snd("set midi version", err);
1019 if (port_count < 1) {
1020 /* use env var for compatibility with pmidi */
1021 const char *ports_str = getenv("ALSA_OUTPUT_PORTS");
1023 parse_ports(ports_str);
1024 if (port_count < 1) {
1025 errormsg("Please specify at least one port with --port.");
1029 if (optind >= argc) {
1030 errormsg("Please specify a file to play.");
1034 create_source_port();
1038 for (; optind < argc; ++optind) {
1039 file_name = argv[optind];