Functions based on those in alsaseq.py: client(), connectfrom(), connectto(), disconnectfrom(),
disconnectto(), fd(), id(), input(), inputpending(), output(), start(), status(), stop(), syncoutput()
Functions based on those in alsamidi.py: noteevent(), noteonevent(), noteoffevent(), pgmchangeevent(),
pitchbendevent(), controllerevent(), chanpress(), sysex()
Functions to interface with MIDI-Perl: alsa2scoreevent(), scoreevent2alsa()
Functions to get the current ALSA status: listclients(), listnumports(), listconnectedto(),
listconnectedfrom(), parse_address()
client($name, $ninputports, $noutputports, $createqueue)
Create an ALSA sequencer client with zero or more input or output ports, and optionally a timing
queue. ninputports and noutputports are created if the quantity requested is between 1 and 64 for
each. If createqueue = true, it creates a queue for stamping the arrival time of incoming events and
scheduling future start times of outgoing events.
For full ALSA functionality, the $name should contain only letters, digits, underscores or spaces, and
should contain at least one letter.
Unlike in the alsaseq.py Python module, it returns success or failure.
connectfrom( $inputport, $src_client, $src_port )
Connect from src_client:src_port to inputport. Each input port can connect from more than one client.
The input() function will receive events from any intput port and any of the clients connected to each
of them. Events from each client can be distinguised by their source field.
Unlike in the alsaseq.py Python module, it returns success or failure.
Since version 1.11, and unlike in the alsaseq.py Python module, if $src_client contains a letter or
$src_port is undefined, then parse_address($src_client) automatically gets invoked. This allows you
to refer to the clients by name, for example connectfrom($inputport,'Virtual:1') will connect from
port 1 of the 'Virtual Raw MIDI' client.
connectto( $outputport, $dest_client, $dest_port )
Connect outputport to dest_client:dest_port. Each output port can be Connected to more than one
client. Events sent to an output port using the output() function will be sent to all clients that
are connected to it using this function.
Unlike in the alsaseq.py Python module, it returns success or failure.
Since version 1.11, and unlike in the alsaseq.py Python module, if $dest_client contains a letter or
$dest_port is undefined, then parse_address($dest_client) automatically gets invoked. This allows you
to refer to the clients by name, for example connectto($outputport,'Virtual:1') will connect to port 1
of the 'Virtual Raw MIDI' client.
disconnectfrom( $inputport, $src_client, $src_port )
Disconnect the connection from the remote src_client:src_port to my inputport. Returns success or
failure.
Since version 1.11, and unlike in the alsaseq.py Python module, if $dest_client contains a letter or
$dest_port is undefined, then parse_address($src_client) automatically gets invoked. This allows you
to refer to the clients by name, for example disconnectfrom($inputport,'Virtual:1') will disconnect
from port 1 of the 'Virtual Raw MIDI' client.
disconnectto( $outputport, $dest_client, $dest_port )
Disconnect the connection from my outputport to the remote dest_client:dest_port. Returns success or
failure.
Since version 1.11, and unlike in the alsaseq.py Python module, if $dest_client contains a letter or
$dest_port is undefined, then parse_address($dest_client) automatically gets invoked. This allows you
to refer to the clients by name, for example disconnectto($outputport,'Virtual:1') will disconnect to
port 1 of the 'Virtual Raw MIDI' client.
fd()
Return fileno of sequencer.
This piece of code, contributed by Daren Schwenke, uses the AnyEvent module to build an application
which waits both for ALSA events, and for user-input:
my $alsa_midi = AnyEvent->io (
fh => MIDI::ALSA::fd(), poll => "r",
cb => sub {
my @alsaevent = MIDI::ALSA::input();
print "Alsa event: " . Dumper(\@alsaevent);
}
);
id()
Return the client number, or 0 if the client is not yet created.
input()
Wait for an ALSA event in any of the input ports and return it. ALSA events are returned as an array
with 8 elements:
($type, $flags, $tag, $queue, $time, \@source, \@destination, \@data)
Unlike in the alsaseq.py Python module, the time element is in floating-point seconds. The last three
elements are also arrays:
@source = ( $src_client, $src_port )
@destination = ( $dest_client, $dest_port )
@data = ( varies depending on type )
The source and destination arrays may be useful within an application for handling events differently
according to their source or destination. The event-type constants, beginning with SND_SEQ_, are
available as module subroutines with empty prototypes, not as strings, and must therefore be used
without any dollar-sign e.g.:
if ($event[0] == MIDI::ALSA::SND_SEQ_EVENT_PORT_UNSUBSCRIBED) { ...
The data array is mostly as documented in http://alsa-project.org/alsa-doc/alsa-lib/seq.html. For
NOTE events, the elements are ( $channel, $pitch, $velocity, unused, $duration ); where since version
1.15 the duration is in floating-point seconds (unlike in the alsaseq.py Python module where it is in
milliseconds). For SYSEX events, the data array contains just one element: the byte-string, including
any F0 and F7 bytes. For most other events, the elements are ($channel, unused,unused,unused,
$param, $value)
The channel element is always 0..15
In the SND_SEQ_EVENT_PITCHBEND event the value element is from -8192..+8191 (not 0..16383)
If a connection terminates, then input() returns, and the next event will be of type
SND_SEQ_EVENT_PORT_UNSUBSCRIBED
Note that if the event is of type SND_SEQ_EVENT_PORT_SUBSCRIBED or SND_SEQ_EVENT_PORT_UNSUBSCRIBED,
then that message has come from the System, and its dest_port tells you which of your ports is
involved. But its src_client and src_port do not tell you which other client disconnected; you'll
need to use listconnectedfrom() or listconnectedto() to see what's happened.
inputpending()
Return the number of bytes available in input buffer. Use before input() to wait till an event is
ready to be read.
output($type,$flags,$tag,$queue,$time,\@source,\@destination,\@data)
Send an ALSA-event from an output port. The format of the event is as discussed in input() above.
The event will be output immediately either if no queue was created in the client or if the queue
parameter is set to SND_SEQ_QUEUE_DIRECT, and otherwise it will be queued and scheduled.
The @source is an array with two elements: ($src_client, $src_port), specifying the local output-port
from which the event will be sent. If only one output-port exists, all events are sent from it. If
two or more exist, the $src_port determines which to use. The smallest available port-number (as
created by client()) will be used if $src_port is less than it, and the largest available will be used
if $src_port is greater than it.
The @destination is an array with two elements: ($dest_client, $dest_port), specifying the remote
client/port to which the event will be sent. If $dest_client is zero (as generated by
scoreevent2alsa() or noteevent()), or is the same as the local client (as generated by input()), then
the event will be sent to all clients that the local port is connected to (see connectto() and
listconnectedto()). But if you set dest_client to a remote client, then the event will be sent to
that dest_client:dest_port and nowhere else.
It is possible to send an event to a destination to which there is no connection, but it's not usually
the right thing to do. Normally, you should set up a connection, to allow the underlying RawMIDI ports
to remain open while playing - otherwise, ALSA will reset the port after every event.
If the queue buffer is full, output() will wait until space is available to output the event. Use
status() to know how many events are scheduled in the queue.
If no queue has been started, a SND_SEQ_EVENT_NOTE event can only emerge as a SND_SEQ_EVENT_NOTEON,
since a queue is necessary in order to schedule the corresponding NOTEOFF.
start()
Start the queue. It is ignored if the client does not have a queue.
status()
Return ($status,$time,$events ) of the queue.
Status: 0 if stopped, 1 if running.
Time: current time in seconds.
Events: number of output events scheduled in the queue.
If the client does not have a queue then (0,0,0) is returned. Unlike in the alsaseq.py Python module,
the time element is in floating-point seconds.
stop()
Stop the queue. It is ignored if the client does not have a queue.
syncoutput()
Wait until output events are processed.
noteevent( $ch, $key, $vel, $start, $duration )
Returns an ALSA-event-array, to be scheduled by output(). Unlike in the alsaseq.py Python module, the
start and duration elements are in floating-point seconds.
noteonevent( $ch, $key, $vel, $start )
If start is not used, the event will be sent directly. Unlike in the alsaseq.py Python module. if
start is provided, the event will be scheduled in a queue. The start element, when provided, is in
floating-point seconds.
noteoffevent( $ch, $key, $vel, $start )
If start is not used, the event will be sent directly. Unlike in the alsaseq.py Python module, if
start is provided, the event will be scheduled in a queue. The start element, when provided, is in
floating-point seconds.
pgmchangeevent( $ch, $value, $start )
Returns an ALSA-event-array for a patch_change event to be sent by output(). If start is not used,
the event will be sent directly; if start is provided, the event will be scheduled in a queue. Unlike
in the alsaseq.py Python module, the start element, when provided, is in floating-point seconds.
pitchbendevent( $ch, $value, $start )
Returns an ALSA-event-array to be sent by output(). The value is from -8192 to 8191. If start is not
used, the event will be sent directly; if start is provided, the event will be scheduled in a queue.
Unlike in the alsaseq.py Python module, the start element, when provided, is in floating-point
seconds.
controllerevent( $ch, $controllernum, $value, $start )
Returns an ALSA-event-array to be sent by output(). If start is not used, the event will be sent
directly; if start is provided, the event will be scheduled in a queue. Unlike in the alsaseq.py
Python module, the start element, when provided, is in floating-point seconds.
chanpress( $ch, $value, $start )
Returns an ALSA-event-array to be sent by output(). If start is not used, the event will be sent
directly; if start is provided, the event will be scheduled in a queue. Unlike in the alsaseq.py
Python module, the start element, when provided, is in floating-point seconds.
sysex( $ch, $string, $start )
Returns an ALSA-event-array to be sent by output(). If start is not used, the event will be sent
directly; if start is provided, the event will be scheduled in a queue. The string should start with
your Manufacturer ID, but should not contain any of the F0 or F7 bytes, they will be added
automatically; indeed the string must not contain any bytes with the top-bit set.
alsa2scoreevent( @alsaevent )
Returns an event in the millisecond-tick score-format used by the MIDI.lua and MIDI.py modules, based
on the score-format in Sean Burke's MIDI-Perl CPAN module. See:
http://www.pjb.com.au/comp/lua/MIDI.html#events
Since it combines a note_on and a note_off event into one note event, it will return nil when called
with the note_on event; the calling loop must therefore detect nil and not, for example, try to index
it.
scoreevent2alsa( @event )
Returns an ALSA-event-array to be scheduled in a queue by output(). The input is an event in the
millisecond-tick score-format used by the MIDI.lua and MIDI.py modules, based on the score-format in
Sean Burke's MIDI-Perl CPAN module. See:
http://www.pjb.com.au/comp/lua/MIDI.html#events
For example:
output(scoreevent2alsa('note',4000,1000,0,62,110))
Some events in a .mid file have no equivalent real-time-midi event (which is the sort that ALSA deals
in); these events will cause scoreevent2alsa() to return undef. Therefore if you are going through
the events in a midi score converting them with scoreevent2alsa(), you should check that the result is
not undef before doing anything further.
listclients()
Returns a hash of the numbers and descriptive strings of all ALSA clients:
my %clientnumber2clientname = MIDI::ALSA::listclients();
my %clientname2clientnumber = reverse %clientnumber2clientname;
listnumports()
Returns a hash of the client-numbers and how many ports they are running, so if a client is running 4
ports they will be numbered 0..3
my %clientnumber2howmanyports = MIDI::ALSA::listnumports();
listconnectedto()
Returns a list of arrayrefs, each to a three-element array ( $outputport, $dest_client, $dest_port )
exactly as might have been passed to connectto(), or which could be passed to disconnectto().
listconnectedfrom()
Returns a list of arrayrefs, each to a three-element array ( $inputport, $src_client, $src_port )
exactly as might have been passed to connectfrom(), or which could be passed to disconnectfrom().
parse_address( $client_name )
Given a string, this function returns a two-integer array ( $client_number, $port_number ) as might be
needed by connectto() or connectfrom(). For example, even if client() has not been called, "24" will
return 24,0 and "25:1" will return 25,1
If the local client is running, then parse_address() also looks up names. For example, if "aconnect
-oil" reveals a timidity client:
client 128: 'TiMidity' [type=user]
then parse_address("TiM") will return 128,0 and parse_address("TiMi:1") will return 128,1 because it
finds the first client with a start-of-string case-sensitive match to the given name. parse_address()
is called automatically by connectto(), connectfrom(), disconnectto() and disconnectfrom() if they are
called with the third argument undefined.
parse_address() was introduced in version 1.11 and is not present in the alsaseq.py Python module.