[Openal] Defective ALC_ENUMERATION_EXT support on Mac OS X / Need
OpenAL community's support
E. Wing
ewmailing at gmail.com
Mon Dec 29 15:31:36 PST 2008
There is a bug in the current Mac OS X implementation concerning the
ALC_ENUMERATION_EXT.
The current implementation fails to do two things:
1) It fails to return a list of devices as intended by the
ALC_ENUMERATION_EXT, even though the implementation claims to support
the extension.
2) It fails to support opening of specific devices that would be named
in this list.
As my Xmas gift to the community, I have implemented these
deficiencies and made my changes publicly available. My wish is that
these will be included into the main Mac OS X distribution as I really
don't wish to maintain a fork for the long haul.
The current behavior of Apple's OpenAL is to claim the implementation
supports the ALC_ENUMERATION_EXT (i.e. alcIsExtensionPresent(NULL,
"ALC_ENUMERATION_EXT") returns true), but the "list" that gets
returned using
alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)
and
alcGetString(NULL, ALC_DEVICE_SPECIFIER)
only contains a single item, which is the default device. The list
will not return any other devices. So for example, Macs come with both
a microphone and a line-in for capture devices. But the list will not
contain both items. It will only contain the device that is the system
default (as selected in System Preferences).
I originally submitted this bug to Apple, but the bug was immediately
closed claiming that this is the proper behavior and we shouldn't be
able to select non-default devices.
I am usually deferential to these kinds of decisions, but this is
absolutely wrong in my opinion. This violates the intent of having the
ALC_ENUMERATION_EXT and may ultimately create a poor user experience
for users.
First, OpenAL already has ALC_DEFAULT_DEVICE_SPECIFIER and
ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER so it is always possible to get
the default device without the enumeration extension. This makes
Apple's current implementation of the enumeration extension completely
redundant and pointless.
Second, as far as user experience goes, this limitation can pose a
serious problem for users in specific circumstances. This is my own
situation:
I am working on an application that analyzes tones from a sound
generator. I basically record a sound and then do some processing on
it. I may playback the sound as it comes in so the user can tell
what's going on.
The cleanest sound samples will obviously come directly from the
line-in attached directly to the sound generator. This requires the
sound generator to have a connection that supports line-in.
As a fallback though, I would also like to support microphone input.
However, there are considerable differences between using a microphone
and line-in as everybody is aware of. Due to noise, it may be produce
terrible results so the user will want to change this.
My problem is that most people have microphone as the system's default
input device (via System Preferences). Since the current Apple OpenAL
implementation will not let me list all devices, nor will it let me
choose a specific device, I must require the user to go to System
Preferences to change the default, and possibly refresh (or worse,
restart) my app so I can see the change.
This is very annoying for a user. This is even more annoying if they
frequently use other applications that rely on a microphone such as
iChat or Skype. So not only must the user change the system default
for my app before they run, they must also remember to go back to
System Preferences after they run my app and change back the default
so iChat/Skype continue to work. But a lot of users won't remember to
do this, and when they go into iChat/Skype, they will be puzzled why
their microphone seems to be broken. If they finally do realize the
problem, they will be angry at my application for making them change
the default in the first place. They will not want to run my
application because it is too much of a pain to setup and cleanup
afterwards.
My application is a very niche application. I have no justification
for requiring the user to change their system default device just for
my application. The user should be able to pick the device they use
the most as the system default, but still be able to run my
application and change the devices within my application if they deem
necessary without messing up their system defaults.
This is why properly supporting the enumeration extension is
important. I understand perfectly about respecting user defaults and I
do so. But it is sometimes necessary to allow users to change from the
defaults in a per-application (non-system-wide) context as I just
described.
Apple need not fear about developers ignoring system defaults. The way
the OpenAL implementation and API currently works, it is much easier
to respect the defaults than to not. Only the apps that have hit the
usability problem I described are going to be inclined to do the extra
work involved to incorporate enumeration. There won't be a wave of
poorly designed apps suddenly hitting the market just because this
extension was properly implemented.
I have placed my changed into a Git repository which can be found at:
http://www.assembla.com/spaces/OpenALCoreAudioDeviceEnumeration
Although I only cared about the Capture devices, I implemented both
Capture and Output fixes to improve the chances of this being
accepted.
I have fixed the following:
- Enumeration lists return all devices, not just the default devices
for both capture and output devices,
e.g. list_of_devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
- Fixed specific device queries to return the actual device name
associated with the passed in device rather than the default device
name,
e.g. device_name = alcGetString(captureDevice, ALC_CAPTURE_DEVICE_SPECIFIER);
- Added support to alcOpenDevice and alcCaptureOpenDevice to allow
device names to be passed in instead of NULL as a parameter and the
device name is not ignored.
My changes preserve compatibility with the current implementation. In
the enumeration lists, I always make sure to place the default device
as the first item in the list so any code that unwisely made
assumptions about the default device being in the first part of the
string will continue to work. I also double-null-terminate
individual/specific device queries since that is what the current
implementation does even though the 1.1 spec says nothing about this.
And of course you still may pass NULL to alc*OpenDevice, and it will
behave exactly as before.
Yes, there were a few design decisions. Probably the most significant
is the use of Device Names as opposed to Device UID strings. The
justification is pretty clear for this though. The current
implementation already returns Device Names and not Device UIDs when
querying for the device, the default device, or the current broken
enumeration list. So for consistency and compatibility, this must
continue. But in addition, UIDs aren't very helpful to humans in most
cases as the strings are unfriendly (and possibly non-localized).
There is a corner case due to the above design decision if there are
multiple devices of the same type (input or output) by the same exact
name. I don't know if OS X tries to make sound device names unique
like Bonjour (by adding numbers at the end). If not, the code won't be
able to distinguish between devices. (In this case though I would
suggest device naming really should work like Bonjour. Zeroconf was
extremely well thought out.) But even with this corner case, this is
still a huge improvement over the current broken implementation.
(By the way, this might also suggest a need for another OpenAL
extension. This suggests there is a distinction between a unique
identifier and a human-readable localized device description.)
The changed files are:
oalCaptureDevice.cpp
oalCaptureDevice.h
oalDevice.cpp
oalDevice.h
oalImp.cpp
oalImp.h
oalOSX.h
I've tested on an iMac with built-in microphone, built-in line-in,
built-in speaker, and an iMic just so I would have a non-Apple and
secondary output device to select.
So for the OpenAL community at large, if you agree with me that the
current OS X implementation is defective in this regard, I request
your support. Please (politely) let Apple know you would like to see
my patch integrated into the main distribution. (I've met the
OpenAL/Apple engineers in person before and they are kind people and
don't wish to offend them.) Please file a bug report on the Apple
radar (bugreport.apple.com) and vote for Bug ID: 6469095 (new
submission) and Bug ID:6455088 (the original closed one).
Meanwhile, anybody who needs this fix is welcome to use it and embed
the modified OpenAL framework directly in their app bundle.
Thanks,
Eric
More information about the Openal
mailing list