summaryrefslogtreecommitdiff
path: root/seq
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2006-12-04 18:01:23 +0100
committerClemens Ladisch <clemens@ladisch.de>2006-12-04 18:01:23 +0100
commit4de3d5a273a4cc6b2ca59e97cbb17bbb5ef4d37a (patch)
treee4991d9cbade87c303e5e2e98532b19e152fae0c /seq
parent815fc4bea040be1950684d6744ec0fe32d15e7b3 (diff)
downloadalsa-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.c36
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);