From: Clemens Ladisch Date: Mon, 4 Dec 2006 17:01:23 +0000 (+0100) Subject: aplaymidi: handle big SysEx commands X-Git-Tag: v1.0.14rc1~1 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=4de3d5a273a4cc6b2ca59e97cbb17bbb5ef4d37a;p=alsa-utils.git 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. --- 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 + * Copyright (c) 2004-2006 Clemens Ladisch * * * 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);