Subject: [linux-audio-dev] LAAGA - main components
From: Kai Vehmanen (kaiv_AT_wakkanet.fi)
Date: Sat Apr 28 2001 - 00:38:53 EEST
Continuing my earlier post - this time with a technical twist. :)
Paul already mentioned adding a separate layer for providing network
access to the plugin system. I think similar middleware layer will also
be needed in other cases.
Converting an existing audio server into a LAAGA server should be quite
easy in most cases. On the client side, things are much more difficult.
For instance, let's take a simple single-threaded audio file player as an
example. The inner loop is something like:
--cut--
while(eof() != true):
read_from_file() // can block
apply_eq()
write_to_soundcard() // can block
--cut--
Now I think it should be easy to convert existing apps into LAAGA
clients. The above application is clearly driven by soundcard
interrupts (most of the time it sleeps in write_to_soundcard()). One
problem in the design is that read_from_file() can also block - we'd need
some kind double-buffering to cover these cases.
But how to convert the above into a LAAGA client; basicly we have two
approaches:
1) Implement the above as a callback function
--cut--
process():
read_from_file() // can block
apply_eq()
server->write_to_laaga_channel()
--cut--
Of course, the same problem with read_from_file()'s possible blocking
behaviour is still present. The above code would run in the same process
context as the LAAGA server. If the file player has a GUI, it
runs as a separate process (app needs to handle IPC between the
process() callback and GUI callbacks/events).
2) Implement middleware that emulates the blocking OSS-style API
--cut--
while(eof() != true)
read_from_file() // can block
apply_eq()
write_to_laaga_channel() // can block
--cut--
If we have a GUI, this code will need to be run in a separate
process. write_to_laaga_channel() must transfer the audio data using
IPC (=sysv shared memory) to the LAAGA server process.
Using semaphores we can implement the required blocking behaviour to the
client side.
..
Now I think to the two big questions are:
- what is allowed in process()
- who performs the process-to-process communication
One possible solution is to divide the LAAGA design into:
1. audio server process
1.1 audio server thread (hw access, no blocking calls)
1.2 client callbacks (set of functions called by the server [1.1])
1.3 client thread (runs in the server process and communicates
with the client callback functions [1.2]; lock-free buffers)
2. worker client process
2.1 client interface thread (communicates with the client thread [1.3])
2.2 client middleware layer
2.3 worker client (GUI/network/file driven application)
Not all clients need this many levels. A non-GUI application can be
implemented as a replacement for 1.2 or 1.3. A GUI softsynth might replace
1.3 and add its own audio-thread<->GUI communication for passing control
values.
Then again, application that both has a GUI and is reading data from
network, is best implemented as a 2.3, using the OSS-style LAAGA
middleware layer.
Now it's not clear what we should aim at? Maybe we should limit LAAGA to
only support 1.3. Ie. client application provides a set of callback
functions (audio server context), and one function that is forked() as the
main() of a new process. At the moment, this approach sounds rather good
to me. Comments?
-- http://www.eca.cx Audio software for Linux!
This archive was generated by hypermail 2b28 : Thu May 24 2001 - 00:24:11 EEST