SEQUENCER


1.2 Clients

Sequencer clients are an essential part of the ALSA sequencer architecture. Clients are used for generating and processing events.

1.2.1 Client applications

There are roughly 4 categories of applications for clients:
The first category is the one that will be used by most application programmers. This is comparable to the OSS /dev/sequencer or /dev/music interface with the big difference that multiple clients are allowed.

The other categories are more specific to the ALSA sequencer, and are needed (especially the device drivers) to get any sound out of it.

1.2.2 Client interfaces

There exist two type of interfaces for clients: a user-land interface and a kernel mode interface. Which one is to be used depends on the place the client is executing.

Each type has its own strengths and weaknesses:

1.2.3 User-land clients

The applications that are seen as user-land clients just open a /dev/sndseq device (or something similar), and read()/write() data from/to it, just like they used to do with the /dev/music device. For registering and interrogation the sequencer an ioctl() interface is used.

Efficient blocking I/O (ie. no polling) can be performed by using the select() call for I/O multiplexing.

This /dev/sndseq device has to support being opened r/w by multiple concurrent clients, much like pty's etc. If this is not possible to implement, we can revert to simply using a whole range of character devices /dev/sndseq0 ... /dev/sndseq254 for each possible client connection (ugly!), and make it a library call to allocate a free client.

Other possibility is to implement an interface to multiple clients using multiple open of /dev/sndseq file. The open() sys-call opens only sequencer which isn't connected to any event queue / timer / kernel clients. Ioctl calls will provide these connections. Resources (event queue, clients) should be identified with some key (probably string) which allows to application specify exact resource which want create / connect. For security some scheme has to be added to prevent application accessing clients that belong to other applications. Per client I/O blocking and read()/write() is not possible in this scenario???

Comments please...

Latest news:

I just wrote a test program, and found out that multiple open of /dev/sndseq works great. The file structure passed on all operation (read/write/ioctl etc) allows us to set a private_data field, to identify this client connection. The user-land interface will exist of one /dev/sndseq device that can be opened by all the user-land clients. Each time a client opens the /dev/sndseq the sequencer connects it to a free client slot.

The presence of multiple user-land applications allows for some nice features:

1.2.4 Kernel mode clients

The kernel mode clients reside in kernel modules. These can be stand-alone loadable kernel modules, or modules that offer other functionality (eg. MIDI driver, sound card driver).

The module level interface exists of following:

Because the events can be dispatched to kernel mode client immediately, this offers possibilities to provide good midi thru and filtering functions.

Example:
Midi input driver receives midi bytes (interrupt driven), once a complete midi message is received, it is send to the sequencer. This event (which has current timestamp) goes directly to the clients that requested reception of the note events. If there is a kernel mode midi thru module, it is directly called, the midi event is perhaps transformed (swapped channel/port), and send back to the sequencer, where it's directly dispatched to the midi (or synth) client, which plays the event. Nice low-latency midi patch-bay! Because midi runs at 31.250 kbps, it will take 0.96 ms to receive a note on message (without running state). Sending this event will also take 0.96 ms, so the event arrives 1.92 ms later at the playback device, which is faster than the typical delay within synthesizers before a sound is produced.

Other applications (apart from drivers) could be support modules for high-end sequencers, that need fine-graded real-time control.

1.2.5 Client communication

The event passing mechanism is well suited for real-time controls, note events etc. But to access very specific functions of a device (client) like for instance downloading samples to a sample player, or changing the microcode for a DSP or on-board processor a different interface will have to be provided. Make this a special 'for the device or application', or use the sequencer as a multiplexer to pass the data to the driver.

Perhaps large data streams (samples!) can be sent directly to the client, bypassing the priority queue. The data can be encapsulated in messages, and transmitted as a packetised stream.

1.2.6 MIDI ports

Note that there is no such thing as a MIDI port, synth device or mixer in this picture. The idea behind this is that a driver for a midi port should be implemented as a 'kernel module'. This 'MIDI Port' module can of course be part of a low-level midi port, and register is from there. There is no need to have both a MIDI low-level module and a MIDI sequencer interface module.

To prevent the misery of stuck notes a low-level midi driver should keep an image of which notes are active. In case a note\_off message is missed (which is an application error!) the driver can shut the notes when asked (all note off message).

The presence of a priority queue also offers the opportunity to process NOTE events what come with an length. On reception of such an event (by eg. a midi driver client), the note can be started and the corresponding note off can be enqueued. Using this facility the chance of hanging notes because of abrupt abortion of a midi player will be reduced to 0.

1.2.7 OSS Compatibility

Because almost every MIDI application that exists for Unix makes use of the OSS /dev/sequencer or /dev/music interface, it's a must to provide backwards compatibility for these applications. Users then can use the new sequencer engine, while keeping their old applications. The application writers then can migrate to the new sequencer and make use of improved capabilities.

To achieve the compatibility a wrapper for /dev/sequencer and /dev/music devices has to be implemented (as a loadable module). This wrapper can simply map the OSS events to the corresponding sequencer calls.

1.2.8 Using OSS as the workhorse

At the time of writing for this document, the only currently available midi and synth driver is the OSS. If a client task is developed that presents itself to the sequencer core as a bunch of input and output device, and simply does read/writes to the OSS /dev/music interface (perhaps directly call the exported functions); a sequencer can be developed and used while using the OSS as workhorse / low-level driver.



Version 0.036, April 2nd, 1999Usage:
Copyright (c) 1998 by Frank van de Pol, NetherlandsAdvanced Linux Sound Architecture