diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2006-12-04 18:01:23 +0100 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2006-12-04 18:01:23 +0100 |
commit | 4de3d5a273a4cc6b2ca59e97cbb17bbb5ef4d37a (patch) | |
tree | e4991d9cbade87c303e5e2e98532b19e152fae0c /seq | |
parent | 815fc4bea040be1950684d6744ec0fe32d15e7b3 (diff) | |
download | alsa-utils-4de3d5a273a4cc6b2ca59e97cbb17bbb5ef4d37a.tar.gz |
aplaymidi: handle big SysEx commands
Make sure that the sequencer output buffer is big enough to handle all
events that we send, and split large SysEx commands into one-second
chunks so that the sequencer kernel code can handle them.
Diffstat (limited to 'seq')
-rw-r--r-- | seq/aplaymidi/aplaymidi.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/seq/aplaymidi/aplaymidi.c b/seq/aplaymidi/aplaymidi.c index c2819d0..b9377e5 100644 --- a/seq/aplaymidi/aplaymidi.c +++ b/seq/aplaymidi/aplaymidi.c @@ -1,7 +1,7 @@ /* * aplaymidi.c - play Standard MIDI Files to sequencer port(s) * - * Copyright (c) 2004 Clemens Ladisch <clemens@ladisch.de> + * Copyright (c) 2004-2006 Clemens Ladisch <clemens@ladisch.de> * * * This program is free software; you can redistribute it and/or modify @@ -31,6 +31,8 @@ #include "aconfig.h" #include "version.h" +#define MIDI_BYTES_PER_SEC 3125 + /* * A MIDI event after being parsed/loaded from the file. * There could be made a case for using snd_seq_event_t instead. @@ -601,6 +603,37 @@ static void cleanup_file_data(void) tracks = NULL; } +static void handle_big_sysex(snd_seq_event_t *ev) +{ + unsigned int length; + ssize_t event_size; + int err; + + length = ev->data.ext.len; + if (length > MIDI_BYTES_PER_SEC) + ev->data.ext.len = MIDI_BYTES_PER_SEC; + event_size = snd_seq_event_length(ev); + if (event_size + 1 > snd_seq_get_output_buffer_size(seq)) { + err = snd_seq_drain_output(seq); + check_snd("drain output", err); + err = snd_seq_set_output_buffer_size(seq, event_size + 1); + check_snd("set output buffer size", err); + } + while (length > MIDI_BYTES_PER_SEC) { + err = snd_seq_event_output(seq, ev); + check_snd("output event", err); + err = snd_seq_drain_output(seq); + check_snd("drain output", err); + err = snd_seq_sync_output_queue(seq); + check_snd("sync output", err); + if (sleep(1)) + fatal("aborted"); + ev->data.ext.ptr += MIDI_BYTES_PER_SEC; + length -= MIDI_BYTES_PER_SEC; + } + ev->data.ext.len = length; +} + static void play_midi(void) { snd_seq_event_t ev; @@ -684,6 +717,7 @@ static void play_midi(void) case SND_SEQ_EVENT_SYSEX: snd_seq_ev_set_variable(&ev, event->data.length, event->sysex); + handle_big_sysex(&ev); break; case SND_SEQ_EVENT_TEMPO: snd_seq_ev_set_fixed(&ev); |