Wrote a bit of "documentation" based on my reading of the sequencer
code.  It's an attempt to answer the question "how does one send and
receive sys-ex using the sequencer?"  Read and use at will, but don't
trust it until Takashi, Frank, and / or Jaroslav give their approval..

===================================================================

Sysex and the ALSA sequencer
----------------------------

System exclusive messages are unique in the MIDI protocol; they are the
only MIDI messages which can vary in length, and they are the only
ones which have a start and a stop byte.  Furthermore, MIDI places no
limit on the length of a sys-ex message.

Because of this, sys-ex messages cannot be encoded directly into ALSA
sequencer events, which are fixed in length.  Instead, the sequencer
uses the special _external_ event type, so named because its data
payload is kept outside the event; the event itself contains only a 
pointer to the data and the length of the data.

* Reception

Sys-ex messages are not always packed into one sequencer
event.  As of this writing, the sequencer's MIDI input system has a
buffer 256 bytes in length, which is, of course, not long enough to
hold all sys-ex messages.  Large sys-ex messages are broken into chunks:
each time the buffer becomes full, the sequencer sends another sys-ex
event, which contains the most recently received bytes of the sys-ex
message.  It is the client application's task to reassemble these into
a complete message, if necessary.

This is actually a more favourable situation for the client, as it
allows the client to monitor the progress of sys-ex transfers, and to
process large messages without storing them, where possible.

Sys-ex events are transmitted along with the beginning and
ending bytes 0xF0 and 0xF7.  This is the only way for a client to tell
the beginning, middle, and ending parts of a series of sys-ex events
apart.

Note that interleaved sys-ex events are not an issue, since it isn't
possible for sys-ex messages to be interleaved over a single MIDI
port.

* Transmission

Currently, ALSA does not require that sys-ex messages be sent in
pieces, but it does allow this.  Sys-ex messages are not parsed for
output in any way; they are simply dumped to the destination port as
given.  (It is therefore possible to send _any_ MIDI bytestream this
way!)  Messages may be sent as a single event or multiple events,
regardless of length, which is limited only by available memory.

To transmit events, the client calls snd_seq_event_output_buffer() or
snd_seq_event_output_direct(), both of which are library functions.
Both functions take as argument a sequencer handle and a pointer to
the event struct to be transmitted.

snd_seq_event_output_buffer() places the event in an event buffer; the
event waits there, possibly with others, until snd_seq_drain_output()
is called or until the buffer becomes full, at which time
snd_seq_drain_output() is called automatically.  If a variable-length
event is sent using this function, it is copied in its entirety onto
the buffer, along with the accompanying event record.  If the event is
too large for the buffer, ALSA simply refuses to send it.

The other method, snd_seq_event_output_direct(), writes the event
directly to the kernel driver; the event buffer is not used (or
affected).  Variable-length events are treated slightly differently: a
block of memory is allocated to contain their payload, and this is
then written, preceded by the event record, to the kernel.

Curiously, the kernel driver appears to have the ability to copy data
directly from user-space, but the library currently does not seem to 
make use of this.


-- 

Michael Ashton <[EMAIL PROTECTED]>
----
"God gave them to me; how can I sell them to someone else?"
-- George Washington Carver, when asked why he patented only three
   of his hundreds of inventions


_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to