Re: User-land CoreAudio driver and Leopard
Re: User-land CoreAudio driver and Leopard
- Subject: Re: User-land CoreAudio driver and Leopard
- From: Jeff Moore <email@hidden>
- Date: Wed, 14 Nov 2007 11:43:03 -0800
On Nov 14, 2007, at 6:53 AM, Stéphane Letz wrote:
You need to have you plug-in code in client processes watching for
coreaudiod to disappear. This can be done a variety of ways, but the
easiest is to have your plug-in in the server create a mach port that
clients can sign up for port death notifications on.
I'm confused here : why should the JackRouter plug-in code watch for
the coreaudiod server ??
I presumed the two talked to one another, like they do in my code.
Hence my client code watches for a port in the coreaudiod process to
die to indicate that it has to recreate the state it had in the server
the next time it talks to the server.
Sounds like you're doing something different.
What I was describing is the following situation:
1) our server jack runs in the user login context (it is more
difficult to have it running in the global context )
This may be problematic for processes like coreaudiod, which run
outside of any login session. In particular, the System Sound Server,
which runs in coreaudiod, needs to do IO with the system default
output device for each logged in user.
2) when loaded by an application, our JackRouter driver check if
the jack server is running. If yes then the device is opened
normally and will appear as a possible audio device for the
application. If not we just throw a kAudioHardwareNotRunningError.
While I should be the last to bring up error code usage, this usage of
kAudioHardwareIllegalOperationError is probably not following the
spirit of it's meaning. It would be better to use
kAudioHardwareIllegalOperationError or to make up your own error code
if you don't feel the standard ones quite match your semantics.
3) it seems that the "coreaudiod needs to access the JackRouter
plug-in" to see it as a possible default input/output device can be
solved by just having the JackRouter plug-in check which process
loads it: if it is "coreaudiod" than we don't do the "jack server
running" step explained in 2) . Doing that and implementing
CanBeDefaultDevice allows the JackRouter to correctly be available
as a default input/output device.
Hmm. Can a user of the JackRouter plug-in inside the coreaudiod
process, like the SSS, still talk to the jack server to do IO?
Note that if this can't happen because "it is more difficult to have
it running in the global context", you should be sure to say that your
devices cannot be the system default output device at minimum because
that's the device that the SSS uses to play it's sounds on from inside
of coreaudiod.
4) Say the user choose the "JackRouter" device as the default input/
output device, then say the user stops jack server. Opening AMS or
HALLab then show this incorrect audio device list: since the jack
server is not running anymore, then JackRouter will not be loaded
anymore, and we see this weird device list. The point is: what is
the HAL supposed to do if a user-land driver is not available
anymore because some required resources (having the jack server
running in our case) are not there anymore? I guess since the
previously chosen default input/output device it not there, then
another one should be chosen by the HAL?
You need to make your device disappear from the device list in this
case using the standard methods available to you. If the device can't
be used, it should not be presented to the user. When the server gets
relaunched, then you can make your device re-appear on the system.
- we started to use the SDK by hacking the SHP_XXX classes. Is this
the recommended way?
It is certainly a way to do it. It's probably the best way to learn
about what's going on and how the classes fit together. Ultimately,
this SDK is a lot like what AUBase provides to the AudioUnit world.
So, you should feel free to approach it as best suits your work-flow.
- the "SampleHardwarePluin" given as an example is quite complex
with the use of this mIOThread. We don't need to have a thread in
our case since our "hardware (the server) already provides a
callback mechanism to drive audio in/out. But since this mIOThread
objet is used everywhere it seems that just removing it has some bad
consequences... What is the recommended way?
To remove it and replace it with a more suitable mechanism. This will
likely involve creating your own subclass of HP_Device directly and
implementing the IO methods to talk to your server. You will probably
also want to tweak how the IOProc buffers are handled if your IO
mechanism allocates the buffers you want to pass to an IOProc. This
is
done by configuring the HP_IOProc instance, mIOProcList.
Ok. I dropped the thread completely. But I'm still using a CAGuard
object between our audio callback and external calls (like
DeviceStartIOProc/DeviceStartIOProc) for sequential access on the
mIOProcList object.
That's a fine idea. Note that you'll be overriding
HP_Device::StartCommandExecution and HP_Device::FinishCommandExecution
to lock and unlock that guard when API calls that affect the IOProc
list are made.
Anyway we still have several problems:
- the JackRouter plugin basically start audio processing in
"StartHardware" and stop it in "StopHardware". We then have an audio
callback that does processing and use the mIOProcList to access the
IOProc that have been added and started.
I'm not sure it matters, but it may be helpful if you described how
this callback mechanism works. At the very least, I'll have a fuller
picture of how your engine works and can provide better guidance on
mapping the SDK onto it.
- in some cases (that is with badly implemented application ))-:
like DVD Player for instance) we see several consecutive calls to
"StopIOEngine" then "StartHardware". This cause all kinds of problem
in our code. I was *really* hoping the HP_XXX classes would
completely handle all "incorrect" calls sequences. A *lot* of
applications as just so badly implemented that they end up doing
completely illogical calls on the driver side. Another example is
QuickTime Broadcaster that call DeviceStartIOProc on a IOProc that
was just previously removed witth RemoveOProc... (this currenty
cause our plug-in to just crash...)
So the point is : are the HP_XXX classes designed to somewhat
"filter" what applications do with the drivers so that what has to
be implemented in the SP_XXX kind of class can be sure to *always*
get a correct call sequence? I hope yes otherwise things become so
much tricky...
Remember, the HAL makes the guarantee that the app can call any API
function from any thread context at any time and the right things will
happen. This guarantee has to be lived up to by your plug-in too.
If your engine can't deal with that, then you need to put in place the
proper thread synchronization stuff to protect your engine. Note that
it is expected that most (and possibly all, I haven't thoroughly
checked recently) HAL API calls will probably block. Further, most of
the API calls don't have any particular guarantees about timing. You
can exploit this to your advantage when mapping the API onto your
engine.
Please file bugs about things like this. With aggregate device bugs,
it helps immensely to include information about exactly what devices
are involved and how the aggregates are being configured.
Will do if i can reproduce the problem in a systematic way.
Thanks!
--
Jeff Moore
Core Audio
Apple
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden