"Fossies" - the Fresh Open Source Software Archive

Member "alsa-utils-1.1.9/seq/aplaymidi/arecordmidi.c" (10 May 2019, 24893 Bytes) of package /linux/misc/alsa-utils-1.1.9.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "arecordmidi.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.8_vs_1.1.9.

    1 /*
    2  * arecordmidi.c - record standard MIDI files from sequencer ports
    3  *
    4  * Copyright (c) 2004-2005 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 <stdio.h>
   25 #include <stdlib.h>
   26 #include <stdarg.h>
   27 #include <string.h>
   28 #include <signal.h>
   29 #include <getopt.h>
   30 #include <sys/poll.h>
   31 #include <alsa/asoundlib.h>
   32 #include "aconfig.h"
   33 #include "version.h"
   34 
   35 #define BUFFER_SIZE 4088
   36 
   37 /* linked list of buffers, stores data as in the .mid file */
   38 struct buffer {
   39     struct buffer *next;
   40     unsigned char buf[BUFFER_SIZE];
   41 };
   42 
   43 struct smf_track {
   44     int size;           /* size of entire data */
   45     int cur_buf_size;       /* size of cur_buf */
   46     struct buffer *cur_buf;
   47     snd_seq_tick_time_t last_tick;  /* end of track */
   48     unsigned char last_command; /* used for running status */
   49     int used;           /* anything record on this track */
   50     struct buffer first_buf;    /* list head */
   51 };
   52 
   53 /* timing/sysex + 16 channels */
   54 #define TRACKS_PER_PORT 17
   55 
   56 /* metronome settings */
   57 /* TODO: create options for this */
   58 #define METRONOME_CHANNEL 9
   59 #define METRONOME_STRONG_NOTE 34
   60 #define METRONOME_WEAK_NOTE 33
   61 #define METRONOME_VELOCITY 100
   62 #define METRONOME_PROGRAM 0
   63 
   64 static snd_seq_t *seq;
   65 static int client;
   66 static int port_count;
   67 static snd_seq_addr_t *ports;
   68 static int queue;
   69 static int smpte_timing = 0;
   70 static int beats = 120;
   71 static int frames;
   72 static int ticks = 0;
   73 static FILE *file;
   74 static int channel_split;
   75 static int num_tracks;
   76 static struct smf_track *tracks;
   77 static volatile sig_atomic_t stop = 0;
   78 static int use_metronome = 0;
   79 static snd_seq_addr_t metronome_port;
   80 static int metronome_weak_note = METRONOME_WEAK_NOTE;
   81 static int metronome_strong_note = METRONOME_STRONG_NOTE;
   82 static int metronome_velocity = METRONOME_VELOCITY;
   83 static int metronome_program = METRONOME_PROGRAM;
   84 static int metronome_channel = METRONOME_CHANNEL;
   85 static int ts_num = 4; /* time signature: numerator */
   86 static int ts_div = 4; /* time signature: denominator */
   87 static int ts_dd = 2; /* time signature: denominator as a power of two */
   88 
   89 /* Parse a decimal number from a command line argument. */
   90 static long arg_parse_decimal_num(const char *str, int *err)
   91 {
   92     long val;
   93     char *endptr;
   94 
   95     errno = 0;
   96     val = strtol(str, &endptr, 0);
   97     if (errno > 0) {
   98         *err = -errno;
   99         return 0;
  100     }
  101     if (*endptr != '\0') {
  102         *err = -EINVAL;
  103         return 0;
  104     }
  105 
  106     return val;
  107 }
  108 
  109 /* prints an error message to stderr, and dies */
  110 static void fatal(const char *msg, ...)
  111 {
  112     va_list ap;
  113 
  114     va_start(ap, msg);
  115     vfprintf(stderr, msg, ap);
  116     va_end(ap);
  117     fputc('\n', stderr);
  118     exit(EXIT_FAILURE);
  119 }
  120 
  121 /* memory allocation error handling */
  122 static void check_mem(void *p)
  123 {
  124     if (!p)
  125         fatal("Out of memory");
  126 }
  127 
  128 /* error handling for ALSA functions */
  129 static void check_snd(const char *operation, int err)
  130 {
  131     if (err < 0)
  132         fatal("Cannot %s - %s", operation, snd_strerror(err));
  133 }
  134 
  135 static void init_seq(void)
  136 {
  137     int err;
  138 
  139     /* open sequencer */
  140     err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0);
  141     check_snd("open sequencer", err);
  142 
  143     /* find out our client's id */
  144     client = snd_seq_client_id(seq);
  145     check_snd("get client id", client);
  146 
  147     /* set our client's name */
  148     err = snd_seq_set_client_name(seq, "arecordmidi");
  149     check_snd("set client name", err);
  150 }
  151 
  152 /* parses one or more port addresses from the string */
  153 static void parse_ports(const char *arg)
  154 {
  155     char *buf, *s, *port_name;
  156     int err;
  157 
  158     /* make a copy of the string because we're going to modify it */
  159     buf = strdup(arg);
  160     check_mem(buf);
  161 
  162     for (port_name = s = buf; s; port_name = s + 1) {
  163         /* Assume that ports are separated by commas.  We don't use
  164          * spaces because those are valid in client names. */
  165         s = strchr(port_name, ',');
  166         if (s)
  167             *s = '\0';
  168 
  169         ++port_count;
  170         ports = realloc(ports, port_count * sizeof(snd_seq_addr_t));
  171         check_mem(ports);
  172 
  173         err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name);
  174         if (err < 0)
  175             fatal("Invalid port %s - %s", port_name, snd_strerror(err));
  176     }
  177 
  178     free(buf);
  179 }
  180 
  181 /* parses the metronome port address */
  182 static void init_metronome(const char *arg)
  183 {
  184     int err;
  185 
  186     err = snd_seq_parse_address(seq, &metronome_port, arg);
  187     if (err < 0)
  188         fatal("Invalid port %s - %s", arg, snd_strerror(err));
  189     use_metronome = 1;
  190 }
  191 
  192 /* parses time signature specification */
  193 static void time_signature(const char *arg)
  194 {
  195     long x = 0;
  196     char *sep;
  197 
  198     x = strtol(arg, &sep, 10);
  199     if (x < 1 || x > 64 || *sep != ':')
  200         fatal("Invalid time signature (%s)", arg);
  201     ts_num = x;
  202     x = strtol(++sep, NULL, 10);
  203     if (x < 1 || x > 64)
  204         fatal("Invalid time signature (%s)", arg);
  205     ts_div = x;
  206     for (ts_dd = 0; x > 1; x /= 2)
  207         ++ts_dd;
  208 }
  209 
  210 /*
  211  * Metronome implementation
  212  */
  213 static void metronome_note(unsigned char note, unsigned int tick)
  214 {
  215     snd_seq_event_t ev;
  216     snd_seq_ev_clear(&ev);
  217     snd_seq_ev_set_note(&ev, metronome_channel, note, metronome_velocity, 1);
  218     snd_seq_ev_schedule_tick(&ev, queue, 0, tick);
  219     snd_seq_ev_set_source(&ev, port_count);
  220     snd_seq_ev_set_subs(&ev);
  221     snd_seq_event_output(seq, &ev);
  222 }
  223 
  224 static void metronome_echo(unsigned int tick)
  225 {
  226     snd_seq_event_t ev;
  227     snd_seq_ev_clear(&ev);
  228     ev.type = SND_SEQ_EVENT_USR0;
  229     snd_seq_ev_schedule_tick(&ev, queue, 0, tick);
  230     snd_seq_ev_set_source(&ev, port_count);
  231     snd_seq_ev_set_dest(&ev, client, port_count);
  232     snd_seq_event_output(seq, &ev);
  233 }
  234 
  235 static void metronome_pattern(unsigned int tick)
  236 {
  237     int j, t, duration;
  238 
  239     t = tick;
  240     duration = ticks * 4 / ts_div;
  241     for (j = 0; j < ts_num; j++) {
  242         metronome_note(j ? metronome_weak_note : metronome_strong_note, t);
  243         t += duration;
  244     }
  245     metronome_echo(t);
  246     snd_seq_drain_output(seq);
  247 }
  248 
  249 static void metronome_set_program(void)
  250 {
  251     snd_seq_event_t ev;
  252 
  253     snd_seq_ev_clear(&ev);
  254     snd_seq_ev_set_pgmchange(&ev, metronome_channel, metronome_program);
  255     snd_seq_ev_set_source(&ev, port_count);
  256     snd_seq_ev_set_subs(&ev);
  257     snd_seq_event_output(seq, &ev);
  258 }
  259 
  260 static void init_tracks(void)
  261 {
  262     int i;
  263 
  264     /* MIDI RP-019 says we need at least one track per port */
  265     num_tracks = port_count;
  266     /* Allocate one track for each possible channel.
  267      * Empty tracks won't be written to the file. */
  268     if (channel_split)
  269         num_tracks *= TRACKS_PER_PORT;
  270 
  271     tracks = calloc(num_tracks, sizeof(struct smf_track));
  272     check_mem(tracks);
  273     for (i = 0; i < num_tracks; ++i)
  274         tracks[i].cur_buf = &tracks[i].first_buf;
  275 }
  276 
  277 static void create_queue(void)
  278 {
  279     snd_seq_queue_tempo_t *tempo;
  280     int err;
  281 
  282     queue = snd_seq_alloc_named_queue(seq, "arecordmidi");
  283     check_snd("create queue", queue);
  284 
  285     snd_seq_queue_tempo_alloca(&tempo);
  286     if (!smpte_timing) {
  287         snd_seq_queue_tempo_set_tempo(tempo, 60000000 / beats);
  288         snd_seq_queue_tempo_set_ppq(tempo, ticks);
  289     } else {
  290         /*
  291          * ALSA doesn't know about the SMPTE time divisions, so
  292          * we pretend to have a musical tempo with the equivalent
  293          * number of ticks/s.
  294          */
  295         switch (frames) {
  296         case 24:
  297             snd_seq_queue_tempo_set_tempo(tempo, 500000);
  298             snd_seq_queue_tempo_set_ppq(tempo, 12 * ticks);
  299             break;
  300         case 25:
  301             snd_seq_queue_tempo_set_tempo(tempo, 400000);
  302             snd_seq_queue_tempo_set_ppq(tempo, 10 * ticks);
  303             break;
  304         case 29:
  305             snd_seq_queue_tempo_set_tempo(tempo, 100000000);
  306             snd_seq_queue_tempo_set_ppq(tempo, 2997 * ticks);
  307             break;
  308         case 30:
  309             snd_seq_queue_tempo_set_tempo(tempo, 500000);
  310             snd_seq_queue_tempo_set_ppq(tempo, 15 * ticks);
  311             break;
  312         default:
  313             fatal("Invalid SMPTE frames %d", frames);
  314         }
  315     }
  316     err = snd_seq_set_queue_tempo(seq, queue, tempo);
  317     if (err < 0)
  318         fatal("Cannot set queue tempo (%u/%i)",
  319               snd_seq_queue_tempo_get_tempo(tempo),
  320               snd_seq_queue_tempo_get_ppq(tempo));
  321 }
  322 
  323 static void create_ports(void)
  324 {
  325     snd_seq_port_info_t *pinfo;
  326     int i, err;
  327     char name[32];
  328 
  329     snd_seq_port_info_alloca(&pinfo);
  330 
  331     /* common information for all our ports */
  332     snd_seq_port_info_set_capability(pinfo,
  333                      SND_SEQ_PORT_CAP_WRITE |
  334                      SND_SEQ_PORT_CAP_SUBS_WRITE);
  335     snd_seq_port_info_set_type(pinfo,
  336                    SND_SEQ_PORT_TYPE_MIDI_GENERIC |
  337                    SND_SEQ_PORT_TYPE_APPLICATION);
  338     snd_seq_port_info_set_midi_channels(pinfo, 16);
  339 
  340     /* we want to know when the events got delivered to us */
  341     snd_seq_port_info_set_timestamping(pinfo, 1);
  342     snd_seq_port_info_set_timestamp_queue(pinfo, queue);
  343 
  344     /* our port number is the same as our port index */
  345     snd_seq_port_info_set_port_specified(pinfo, 1);
  346     for (i = 0; i < port_count; ++i) {
  347         snd_seq_port_info_set_port(pinfo, i);
  348 
  349         sprintf(name, "arecordmidi port %i", i);
  350         snd_seq_port_info_set_name(pinfo, name);
  351 
  352         err = snd_seq_create_port(seq, pinfo);
  353         check_snd("create port", err);
  354     }
  355 
  356     /* create an optional metronome port */
  357     if (use_metronome) {
  358         snd_seq_port_info_set_port(pinfo, port_count);
  359         snd_seq_port_info_set_name(pinfo, "arecordmidi metronome");
  360         snd_seq_port_info_set_capability(pinfo,
  361                          SND_SEQ_PORT_CAP_READ |
  362                          SND_SEQ_PORT_CAP_WRITE);
  363         snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_APPLICATION);
  364         snd_seq_port_info_set_midi_channels(pinfo, 0);
  365         snd_seq_port_info_set_timestamping(pinfo, 0);
  366         err = snd_seq_create_port(seq, pinfo);
  367         check_snd("create metronome port", err);
  368     }
  369 }
  370 
  371 static void connect_ports(void)
  372 {
  373     int i, err;
  374 
  375     for (i = 0; i < port_count; ++i) {
  376         err = snd_seq_connect_from(seq, i, ports[i].client, ports[i].port);
  377         if (err < 0)
  378             fatal("Cannot connect from port %d:%d - %s",
  379                   ports[i].client, ports[i].port, snd_strerror(err));
  380     }
  381 
  382     /* subscribe the metronome port */
  383     if (use_metronome) {
  384             err = snd_seq_connect_to(seq, port_count, metronome_port.client, metronome_port.port);
  385         if (err < 0)
  386                 fatal("Cannot connect to port %d:%d - %s",
  387                   metronome_port.client, metronome_port.port, snd_strerror(err));
  388     }
  389 }
  390 
  391 /* records a byte to be written to the .mid file */
  392 static void add_byte(struct smf_track *track, unsigned char byte)
  393 {
  394     /* make sure we have enough room in the current buffer */
  395     if (track->cur_buf_size >= BUFFER_SIZE) {
  396         track->cur_buf->next = calloc(1, sizeof(struct buffer));
  397         if (!track->cur_buf->next)
  398             fatal("out of memory");
  399         track->cur_buf = track->cur_buf->next;
  400         track->cur_buf_size = 0;
  401     }
  402 
  403     track->cur_buf->buf[track->cur_buf_size++] = byte;
  404     track->size++;
  405 }
  406 
  407 /* record a variable-length quantity */
  408 static void var_value(struct smf_track *track, int v)
  409 {
  410     if (v >= (1 << 28))
  411         add_byte(track, 0x80 | ((v >> 28) & 0x03));
  412     if (v >= (1 << 21))
  413         add_byte(track, 0x80 | ((v >> 21) & 0x7f));
  414     if (v >= (1 << 14))
  415         add_byte(track, 0x80 | ((v >> 14) & 0x7f));
  416     if (v >= (1 << 7))
  417         add_byte(track, 0x80 | ((v >> 7) & 0x7f));
  418     add_byte(track, v & 0x7f);
  419 }
  420 
  421 /* record the delta time from the last event */
  422 static void delta_time(struct smf_track *track, const snd_seq_event_t *ev)
  423 {
  424     int diff = ev->time.tick - track->last_tick;
  425     if (diff < 0)
  426         diff = 0;
  427     var_value(track, diff);
  428     track->last_tick = ev->time.tick;
  429 }
  430 
  431 /* record a status byte (or not if we can use running status) */
  432 static void command(struct smf_track *track, unsigned char cmd)
  433 {
  434     if (cmd != track->last_command)
  435         add_byte(track, cmd);
  436     track->last_command = cmd < 0xf0 ? cmd : 0;
  437 }
  438 
  439 /* put port numbers into all tracks */
  440 static void record_port_numbers(void)
  441 {
  442     int i;
  443 
  444     for (i = 0; i < num_tracks; ++i) {
  445         var_value(&tracks[i], 0);
  446         add_byte(&tracks[i], 0xff);
  447         add_byte(&tracks[i], 0x21);
  448         var_value(&tracks[i], 1);
  449         if (channel_split)
  450             add_byte(&tracks[i], i / TRACKS_PER_PORT);
  451         else
  452             add_byte(&tracks[i], i);
  453     }
  454 }
  455 
  456 static void record_event(const snd_seq_event_t *ev)
  457 {
  458     unsigned int i;
  459     struct smf_track *track;
  460 
  461     /* ignore events without proper timestamps */
  462     if (ev->queue != queue || !snd_seq_ev_is_tick(ev))
  463         return;
  464 
  465     /* determine which track to record to */
  466     i = ev->dest.port;
  467     if (i == port_count) {
  468         if (ev->type == SND_SEQ_EVENT_USR0)
  469             metronome_pattern(ev->time.tick);
  470         return;
  471     }
  472     if (channel_split) {
  473         i *= TRACKS_PER_PORT;
  474         if (snd_seq_ev_is_channel_type(ev))
  475             i += 1 + (ev->data.note.channel & 0xf);
  476     }
  477     if (i >= num_tracks)
  478         return;
  479     track = &tracks[i];
  480 
  481     switch (ev->type) {
  482     case SND_SEQ_EVENT_NOTEON:
  483         delta_time(track, ev);
  484         command(track, MIDI_CMD_NOTE_ON | (ev->data.note.channel & 0xf));
  485         add_byte(track, ev->data.note.note & 0x7f);
  486         add_byte(track, ev->data.note.velocity & 0x7f);
  487         break;
  488     case SND_SEQ_EVENT_NOTEOFF:
  489         delta_time(track, ev);
  490         command(track, MIDI_CMD_NOTE_OFF | (ev->data.note.channel & 0xf));
  491         add_byte(track, ev->data.note.note & 0x7f);
  492         add_byte(track, ev->data.note.velocity & 0x7f);
  493         break;
  494     case SND_SEQ_EVENT_KEYPRESS:
  495         delta_time(track, ev);
  496         command(track, MIDI_CMD_NOTE_PRESSURE | (ev->data.note.channel & 0xf));
  497         add_byte(track, ev->data.note.note & 0x7f);
  498         add_byte(track, ev->data.note.velocity & 0x7f);
  499         break;
  500     case SND_SEQ_EVENT_CONTROLLER:
  501         delta_time(track, ev);
  502         command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf));
  503         add_byte(track, ev->data.control.param & 0x7f);
  504         add_byte(track, ev->data.control.value & 0x7f);
  505         break;
  506     case SND_SEQ_EVENT_PGMCHANGE:
  507         delta_time(track, ev);
  508         command(track, MIDI_CMD_PGM_CHANGE | (ev->data.control.channel & 0xf));
  509         add_byte(track, ev->data.control.value & 0x7f);
  510         break;
  511     case SND_SEQ_EVENT_CHANPRESS:
  512         delta_time(track, ev);
  513         command(track, MIDI_CMD_CHANNEL_PRESSURE | (ev->data.control.channel & 0xf));
  514         add_byte(track, ev->data.control.value & 0x7f);
  515         break;
  516     case SND_SEQ_EVENT_PITCHBEND:
  517         delta_time(track, ev);
  518         command(track, MIDI_CMD_BENDER | (ev->data.control.channel & 0xf));
  519         add_byte(track, (ev->data.control.value + 8192) & 0x7f);
  520         add_byte(track, ((ev->data.control.value + 8192) >> 7) & 0x7f);
  521         break;
  522     case SND_SEQ_EVENT_CONTROL14:
  523         /* create two commands for MSB and LSB */
  524         delta_time(track, ev);
  525         command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf));
  526         add_byte(track, ev->data.control.param & 0x7f);
  527         add_byte(track, (ev->data.control.value >> 7) & 0x7f);
  528         if ((ev->data.control.param & 0x7f) < 0x20) {
  529             delta_time(track, ev);
  530             /* running status */
  531             add_byte(track, (ev->data.control.param & 0x7f) + 0x20);
  532             add_byte(track, ev->data.control.value & 0x7f);
  533         }
  534         break;
  535     case SND_SEQ_EVENT_NONREGPARAM:
  536         delta_time(track, ev);
  537         command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf));
  538         add_byte(track, MIDI_CTL_NONREG_PARM_NUM_LSB);
  539         add_byte(track, ev->data.control.param & 0x7f);
  540         delta_time(track, ev);
  541         add_byte(track, MIDI_CTL_NONREG_PARM_NUM_MSB);
  542         add_byte(track, (ev->data.control.param >> 7) & 0x7f);
  543         delta_time(track, ev);
  544         add_byte(track, MIDI_CTL_MSB_DATA_ENTRY);
  545         add_byte(track, (ev->data.control.value >> 7) & 0x7f);
  546         delta_time(track, ev);
  547         add_byte(track, MIDI_CTL_LSB_DATA_ENTRY);
  548         add_byte(track, ev->data.control.value & 0x7f);
  549         break;
  550     case SND_SEQ_EVENT_REGPARAM:
  551         delta_time(track, ev);
  552         command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf));
  553         add_byte(track, MIDI_CTL_REGIST_PARM_NUM_LSB);
  554         add_byte(track, ev->data.control.param & 0x7f);
  555         delta_time(track, ev);
  556         add_byte(track, MIDI_CTL_REGIST_PARM_NUM_MSB);
  557         add_byte(track, (ev->data.control.param >> 7) & 0x7f);
  558         delta_time(track, ev);
  559         add_byte(track, MIDI_CTL_MSB_DATA_ENTRY);
  560         add_byte(track, (ev->data.control.value >> 7) & 0x7f);
  561         delta_time(track, ev);
  562         add_byte(track, MIDI_CTL_LSB_DATA_ENTRY);
  563         add_byte(track, ev->data.control.value & 0x7f);
  564         break;
  565 #if 0   /* ignore */
  566     case SND_SEQ_EVENT_SONGPOS:
  567     case SND_SEQ_EVENT_SONGSEL:
  568     case SND_SEQ_EVENT_QFRAME:
  569     case SND_SEQ_EVENT_START:
  570     case SND_SEQ_EVENT_CONTINUE:
  571     case SND_SEQ_EVENT_STOP:
  572     case SND_SEQ_EVENT_TUNE_REQUEST:
  573     case SND_SEQ_EVENT_RESET:
  574     case SND_SEQ_EVENT_SENSING:
  575         break;
  576 #endif
  577     case SND_SEQ_EVENT_SYSEX:
  578         if (ev->data.ext.len == 0)
  579             break;
  580         delta_time(track, ev);
  581         if (*(unsigned char*)ev->data.ext.ptr == 0xf0)
  582             command(track, 0xf0), i = 1;
  583         else
  584             command(track, 0xf7), i = 0;
  585         var_value(track, ev->data.ext.len - i);
  586         for (; i < ev->data.ext.len; ++i)
  587             add_byte(track, ((unsigned char*)ev->data.ext.ptr)[i]);
  588         break;
  589     default:
  590         return;
  591     }
  592     track->used = 1;
  593 }
  594 
  595 static void finish_tracks(void)
  596 {
  597     snd_seq_queue_status_t *queue_status;
  598     int tick, i, err;
  599 
  600     snd_seq_queue_status_alloca(&queue_status);
  601 
  602     err = snd_seq_get_queue_status(seq, queue, queue_status);
  603     check_snd("get queue status", err);
  604     tick = snd_seq_queue_status_get_tick_time(queue_status);
  605 
  606     /* make length of first track the recording length */
  607     var_value(&tracks[0], tick - tracks[0].last_tick);
  608     add_byte(&tracks[0], 0xff);
  609     add_byte(&tracks[0], 0x2f);
  610     var_value(&tracks[0], 0);
  611 
  612     /* finish other tracks */
  613     for (i = 1; i < num_tracks; ++i) {
  614         var_value(&tracks[i], 0);
  615         add_byte(&tracks[i], 0xff);
  616         add_byte(&tracks[i], 0x2f);
  617         var_value(&tracks[i], 0);
  618     }
  619 }
  620 
  621 static void write_file(void)
  622 {
  623     int used_tracks, time_division, i;
  624     struct buffer *buf;
  625 
  626     used_tracks = 0;
  627     for (i = 0; i < num_tracks; ++i)
  628         used_tracks += !!tracks[i].used;
  629 
  630     /* header id and length */
  631     fwrite("MThd\0\0\0\6", 1, 8, file);
  632     /* type 0 or 1 */
  633     fputc(0, file);
  634     fputc(used_tracks > 1 ? 1 : 0, file);
  635     /* number of tracks */
  636     fputc((used_tracks >> 8) & 0xff, file);
  637     fputc(used_tracks & 0xff, file);
  638     /* time division */
  639     time_division = ticks;
  640     if (smpte_timing)
  641         time_division |= (0x100 - frames) << 8;
  642     fputc(time_division >> 8, file);
  643     fputc(time_division & 0xff, file);
  644 
  645     for (i = 0; i < num_tracks; ++i) {
  646         if (!tracks[i].used)
  647             continue;
  648         /* track id */
  649         fwrite("MTrk", 1, 4, file);
  650         /* data length */
  651         fputc((tracks[i].size >> 24) & 0xff, file);
  652         fputc((tracks[i].size >> 16) & 0xff, file);
  653         fputc((tracks[i].size >> 8) & 0xff, file);
  654         fputc(tracks[i].size & 0xff, file);
  655         /* track contents */
  656         for (buf = &tracks[i].first_buf; buf; buf = buf->next)
  657             fwrite(buf->buf, 1, buf == tracks[i].cur_buf
  658                    ? tracks[i].cur_buf_size : BUFFER_SIZE, file);
  659     }
  660 }
  661 
  662 static void list_ports(void)
  663 {
  664     snd_seq_client_info_t *cinfo;
  665     snd_seq_port_info_t *pinfo;
  666 
  667     snd_seq_client_info_alloca(&cinfo);
  668     snd_seq_port_info_alloca(&pinfo);
  669 
  670     puts(" Port    Client name                      Port name");
  671 
  672     snd_seq_client_info_set_client(cinfo, -1);
  673     while (snd_seq_query_next_client(seq, cinfo) >= 0) {
  674         int client = snd_seq_client_info_get_client(cinfo);
  675 
  676         if (client == SND_SEQ_CLIENT_SYSTEM)
  677             continue; /* don't show system timer and announce ports */
  678         snd_seq_port_info_set_client(pinfo, client);
  679         snd_seq_port_info_set_port(pinfo, -1);
  680         while (snd_seq_query_next_port(seq, pinfo) >= 0) {
  681             /* port must understand MIDI messages */
  682             if (!(snd_seq_port_info_get_type(pinfo)
  683                   & SND_SEQ_PORT_TYPE_MIDI_GENERIC))
  684                 continue;
  685             /* we need both READ and SUBS_READ */
  686             if ((snd_seq_port_info_get_capability(pinfo)
  687                  & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ))
  688                 != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ))
  689                 continue;
  690             printf("%3d:%-3d  %-32.32s %s\n",
  691                    snd_seq_port_info_get_client(pinfo),
  692                    snd_seq_port_info_get_port(pinfo),
  693                    snd_seq_client_info_get_name(cinfo),
  694                    snd_seq_port_info_get_name(pinfo));
  695         }
  696     }
  697 }
  698 
  699 static void help(const char *argv0)
  700 {
  701     fprintf(stderr, "Usage: %s [options] outputfile\n"
  702         "\nAvailable options:\n"
  703         "  -h,--help                  this help\n"
  704         "  -V,--version               show version\n"
  705         "  -l,--list                  list input ports\n"
  706         "  -p,--port=client:port,...  source port(s)\n"
  707         "  -b,--bpm=beats             tempo in beats per minute\n"
  708         "  -f,--fps=frames            resolution in frames per second (SMPTE)\n"
  709         "  -t,--ticks=ticks           resolution in ticks per beat or frame\n"
  710         "  -s,--split-channels        create a track for each channel\n"
  711         "  -m,--metronome=client:port play a metronome signal\n"
  712         "  -i,--timesig=nn:dd         time signature\n"
  713         "  -n,--num-events=events     fixed number of events to record, then exit\n",
  714         argv0);
  715 }
  716 
  717 static void version(void)
  718 {
  719     fputs("arecordmidi version " SND_UTIL_VERSION_STR "\n", stderr);
  720 }
  721 
  722 static void sighandler(int sig)
  723 {
  724     stop = 1;
  725 }
  726 
  727 int main(int argc, char *argv[])
  728 {
  729     static const char short_options[] = "hVlp:b:f:t:sdm:i:n:";
  730     static const struct option long_options[] = {
  731         {"help", 0, NULL, 'h'},
  732         {"version", 0, NULL, 'V'},
  733         {"list", 0, NULL, 'l'},
  734         {"port", 1, NULL, 'p'},
  735         {"bpm", 1, NULL, 'b'},
  736         {"fps", 1, NULL, 'f'},
  737         {"ticks", 1, NULL, 't'},
  738         {"split-channels", 0, NULL, 's'},
  739         {"dump", 0, NULL, 'd'},
  740         {"metronome", 1, NULL, 'm'},
  741         {"timesig", 1, NULL, 'i'},
  742         {"num-events", 1, NULL, 'n'},
  743         { }
  744     };
  745 
  746     char *filename = NULL;
  747     int do_list = 0;
  748     struct pollfd *pfds;
  749     int npfds;
  750     int c, err;
  751     /* If |num_events| isn't specified, leave it at 0. */
  752     long num_events = 0;
  753     long events_received = 0;
  754 
  755     init_seq();
  756 
  757     while ((c = getopt_long(argc, argv, short_options,
  758                 long_options, NULL)) != -1) {
  759         switch (c) {
  760         case 'h':
  761             help(argv[0]);
  762             return 0;
  763         case 'V':
  764             version();
  765             return 0;
  766         case 'l':
  767             do_list = 1;
  768             break;
  769         case 'p':
  770             parse_ports(optarg);
  771             break;
  772         case 'b':
  773             beats = atoi(optarg);
  774             if (beats < 4 || beats > 6000)
  775                 fatal("Invalid tempo");
  776             smpte_timing = 0;
  777             break;
  778         case 'f':
  779             frames = atoi(optarg);
  780             if (frames != 24 && frames != 25 &&
  781                 frames != 29 && frames != 30)
  782                 fatal("Invalid number of frames/s");
  783             smpte_timing = 1;
  784             break;
  785         case 't':
  786             ticks = atoi(optarg);
  787             if (ticks < 1 || ticks > 0x7fff)
  788                 fatal("Invalid number of ticks");
  789             break;
  790         case 's':
  791             channel_split = 1;
  792             break;
  793         case 'd':
  794             fputs("The --dump option isn't supported anymore, use aseqdump instead.\n", stderr);
  795             break;
  796         case 'm':
  797             init_metronome(optarg);
  798             break;
  799         case 'i':
  800             time_signature(optarg);
  801             break;
  802         case 'n':
  803             err = 0;
  804             num_events = arg_parse_decimal_num(optarg, &err);
  805             if (err != 0) {
  806                 fatal("Couldn't parse num_events argument: %s\n",
  807                     strerror(-err));
  808             }
  809             if (num_events <= 0)
  810                 fatal("num_events must be greater than 0");
  811             break;
  812         default:
  813             help(argv[0]);
  814             return 1;
  815         }
  816     }
  817 
  818     if (do_list) {
  819         list_ports();
  820         return 0;
  821     }
  822 
  823     if (port_count < 1) {
  824         fputs("Pleast specify a source port with --port.\n", stderr);
  825         return 1;
  826     }
  827 
  828     if (!ticks)
  829         ticks = smpte_timing ? 40 : 384;
  830     if (smpte_timing && ticks > 0xff)
  831         ticks = 0xff;
  832 
  833     if (optind >= argc) {
  834         fputs("Please specify a file to record to.\n", stderr);
  835         return 1;
  836     }
  837     filename = argv[optind];
  838 
  839     init_tracks();
  840     create_queue();
  841     create_ports();
  842     connect_ports();
  843     if (port_count > 1)
  844         record_port_numbers();
  845 
  846     /* record tempo */
  847     if (!smpte_timing) {
  848         int usecs_per_quarter = 60000000 / beats;
  849         var_value(&tracks[0], 0); /* delta time */
  850         add_byte(&tracks[0], 0xff);
  851         add_byte(&tracks[0], 0x51);
  852         var_value(&tracks[0], 3);
  853         add_byte(&tracks[0], usecs_per_quarter >> 16);
  854         add_byte(&tracks[0], usecs_per_quarter >> 8);
  855         add_byte(&tracks[0], usecs_per_quarter);
  856 
  857         /* time signature */
  858         var_value(&tracks[0], 0); /* delta time */
  859         add_byte(&tracks[0], 0xff);
  860         add_byte(&tracks[0], 0x58);
  861         var_value(&tracks[0], 4);
  862         add_byte(&tracks[0], ts_num);
  863         add_byte(&tracks[0], ts_dd);
  864         add_byte(&tracks[0], 24); /* MIDI clocks per metronome click */
  865         add_byte(&tracks[0], 8); /* notated 32nd-notes per MIDI quarter note */
  866     }
  867     
  868     /* always write at least one track */
  869     tracks[0].used = 1;
  870 
  871     file = fopen(filename, "wb");
  872     if (!file)
  873         fatal("Cannot open %s - %s", filename, strerror(errno));
  874 
  875     err = snd_seq_start_queue(seq, queue, NULL);
  876     check_snd("start queue", err);
  877     snd_seq_drain_output(seq);
  878 
  879     err = snd_seq_nonblock(seq, 1);
  880     check_snd("set nonblock mode", err);
  881     
  882     if (use_metronome) {
  883         metronome_set_program();
  884         metronome_pattern(0);
  885     }
  886 
  887     signal(SIGINT, sighandler);
  888     signal(SIGTERM, sighandler);
  889 
  890     npfds = snd_seq_poll_descriptors_count(seq, POLLIN);
  891     pfds = alloca(sizeof(*pfds) * npfds);
  892     for (;;) {
  893         snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN);
  894         if (poll(pfds, npfds, -1) < 0)
  895             break;
  896         do {
  897             snd_seq_event_t *event;
  898             err = snd_seq_event_input(seq, &event);
  899             if (err < 0)
  900                 break;
  901             if (event) {
  902                 record_event(event);
  903                 events_received++;
  904             }
  905         } while (err > 0);
  906         if (stop)
  907             break;
  908         if (num_events && (events_received == num_events))
  909             break;
  910     }
  911 
  912     if (num_events && events_received < num_events)
  913         fputs("Warning: Received signal before num_events\n", stdout);
  914 
  915     finish_tracks();
  916     write_file();
  917 
  918     fclose(file);
  919     snd_seq_close(seq);
  920     return 0;
  921 }