How to use two clients in a single application?

Takashi Iwai <tiwai@suse.de>

Well, the title might sound strange to you, but it's possible! The ALSA sequencer allows multiple access to the single sequencer device (/dev/snd/seq as default). Then why not multiple access from a single application process?

What you need to do is to call snd_seq_open functions twice:

	snd_seq_t *seq1, *seq2;
	snd_seq_open(&seq1, SND_SEQ_OPEN);
	snd_seq_open(&seq2, SND_SEQ_OPEN);
That's all, folks. Now you can attach ports to each client.
	snd_seq_port_info_t pinfo;
	memset(&pinfo, 0, sizeof(pinfo));
	pinfo.capability = SND_SEQ_PORT_CAP_READ;
	pinfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
	snd_seq_create_port(seq1, &pinfo);

	memset(&pinfo, 0, sizeof(pinfo));
	pinfo.capability = SND_SEQ_PORT_CAP_WRITE;
	pinfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
	snd_seq_create_port(seq2, &pinfo);
In this example, read-only port is created for client1, and write-only port is for client2.

Please be aware that in order to handle two clients simultaneously, they should be accessed in non-blocking mode. As alternatives, it might be possible to use threads to deal with the individual client.

Well, what is the merit to have multiple clients in an application?

The first one becomes sometimes important when you want to control queues in real-time with buffered event output. Since alsa-lib itself has output buffer and any output events (including direct events) are once written on this buffer, the event can't be sent in real time. This appears obviously a failure of alsa-lib. But forget it now, since multiple clients help you, and this is the very topic of this text.

You open two clients seq1 and seq2, one for normal output events and another for queue control. Any queue controls (start, stop, continue queue, change tempo, etc.) are sent via seq2, while other MIDI events (note-on, control change, etc.) are sent via seq1. Even if seq1 becomes full, queue tempo can be changed via seq2 without pause. For this purpse, the queue must be allocated (and owned) by seq2. You need to call snd_seq_alloc_queue using seq2 handler. The queue itself can be safely used by seq1, although seq1 can't control it.

If you have more or better ideas, please let me know.


Takashi Iwai tiwai@suse.de My ALSA Page