Re: [linux-audio-dev] API design again [code]

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] API design again [code]
From: David Olofson (audiality_AT_swipnet.se)
Date: la loka   09 1999 - 17:00:04 EDT


On Sat, 09 Oct 1999, Paul Barton-Davis wrote:
> >> 2) h/w-driven events get noticed by other threads, and are then
> >> delivered to the engine thread somehow. this seems to imply some
> >> wholly different event-type-specific-API. seems like a bad idea,
> >> given that this event system is supposed to be generic.
>
> >This is closer to my solution. However, the physical event_port_t
> >instance you see from your thread is not the same one as the actual
> >destination. (Unless the destination is running in the same thread.)
>
> it can't be, by my very definition: the engine thread is where plugins
> run, and other threads are what wakeup from select(2) in order to
> generate an event_t.

"h/w-driven events get noticed by other threads, and are then delivered to the
engine thread somehow." is what I was thinking about... This is what happens
with my system, only you're not passing the events one by one between threads.

> >It's a "shadow port" that's only used to hide the fact that you're
> >working on your own, in your own context, all the time until you're
> >done with all work related to the current cycle. It's not until then
> >that the event buffers will be sent off to their real destinations.
>
> this still seems unclear to me. suppose i am a MIDI input thread, and
> I wake up from select(2). i read the available data. what do i do now?
> how do I generate an event_t that can be inserted into the relevant
> queues passed to plugins ?

You qm_malloc() some memory for your new event (will be from shared memory if
the destination is on the same machine), you fill it in and "send" it to your
local event port.

As your MIDI thread has no notion of cycle times, it would preferably use some
other time base; perhaps the total sample count (as opposed to samples from the
current buffer) of the target port's context. The translation is done when the
events are passed to the real destination.

Regarding the flushing of the heap buffers you use: As you don't have cycles,
there will be no natural interval for sending the current buffer off to the
garbage collector for the context of the event port. What will happen is just
that the buffers will be left around, and you'll implicitly pass them to the
garbage collector when they're full.

(Note: "Sending to the garbage collector" is a bit simplified. A buffer will
first move to the "queue of buffers to be used" of the real destination event
port. From there, the buffer is returned to the global heap when it's been
parsed by the destination plug-in or client, and is no longer needed.)

> Turning to the first approach, you commented:
>
> >> 1) you're imagining that, external "h/w" events (e.g. MIDI i/o, GUI
> >> events, etc) get handled by a plugin run by the engine thread.
> >> In the case of MIDI-like stuff, this gets rid of sample accuracy,
> >> since we can't notice the event till we execute the plugin, which
> >> happens once per control cycle.
>
> >Implementation flaw. You will always need an IRQ handler or a separate thread
> >to add timing info, if the hardware doesn't.
>
> but add it to what ? what is the data structure that the timing
> information gets marked in ?

That's what you use qm_malloc() on your local (in this case; shadow) event port
for.

> device drivers that manage byte streams
> don't read/write structures, so it can't be part of the data stream
> from the driver.

Sending events through streams is a different matter, and means that you need
to call a function that encodes (basically removes pointers) and writes the
events to the device. This can be done rather nicely as well, but it's not the
way it's intended to be done in the normal case. Shared memory is what I've
been talking about so far...

> it can't be an event_t, since the thread that handles
> the h/w event can't allocate event_t's without a lock.

It can, as it owns the local shadow port, and hence the heap that qm_malloc()
will allocate from. (qm_new_buffer() could be seen as transfering ownership of
a nem buffer from the global heap to the heap that requests it.)

//David

 ·A·U·D·I·A·L·I·T·Y· P r o f e s s i o n a l L i n u x A u d i o
- - ------------------------------------------------------------- - -
    ·Rock Solid David Olofson:
    ·Low Latency www.angelfire.com/or/audiality ·Audio Hacker
    ·Plug-Ins audiality_AT_swipnet.se ·Linux Advocate
    ·Open Source ·Singer/Composer


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:27:13 EST