Moving Off Deprecated HAL APIs
This Technical Note discusses transitioning to the newer AudioDevice
and AudioObject
APIs available since the release of Mac OS X 10.5.
Introduction
The AudioHardware.h
header file contains APIs used to work with the audio HAL. The audio HAL provides the abstraction through which applications can access audio hardware. There are a set of HAL APIs which have been deprecated since the release of Mac OS X 10.5 and should no longer be used.
There are two types of deprecated APIs. The first type are the AudioDeviceIOProc
registration calls, these include AudioDeviceAddIOProc
and AudioDeviceRemoveIOProc
. The second type are the property accessors such as AudioHardwareGetProperty
, AudioDeviceSetProperty
and related APIs.
Transitioning to the newer APIs is straight forward and recommended for all applications currently using the older deprecated APIs.
IOProc Registration Changes
The AudioDeviceIOProc
registration change introduces the AudioDeviceIOProcID
type and remaps AudioDeviceAddIOProc
and AudioDeviceRemoveIOProc
to AudioDeviceCreateIOProcID
and AudioDeviceDestroyIOProcID
respectively.
An AudioDeviceIOProcID
represents both an IOProc and the client data that goes with it. Once created, an AudioDeviceIOProcID
can be used everywhere one would use a regular IOProc. The purpose for an AudioDeviceIOProcID
is to allow a client to register the same function pointer as an IOProc with a device multiple times (as long as the user client data pointer is different each time).
When using these new registration APIs, you pass the AudioDeviceIOProcID
returned from AudioDeviceCreateIOProcID
to AudioDeviceStart
and AudioDeviceStop
rather than the IOProc itself.
Examples
Listing 1 Deprecated - AudioDeviceIOProc
Registration.
OSStatus MyIOProc(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData) { // your IOProc here ... } // Deprecated void DeprecatedFakePlay(AudioObjectID inDevice, void* inClientData) { // register the IOProc OSStatus theError = AudioDeviceAddIOProc(inDevice, MyIOProc, inClientData); // handle errors // start IO theError = AudioDeviceStart(inDevice, MyIOProc); ... // stop IO theError = AudioDeviceStop(inDevice, MyIOProc); // unregister the IOProc theError = AudioDeviceRemoveIOProc(inDevice, MyIOProc); } |
Listing 2 New - AudioDeviceIOProc
Registration.
OSStatus MyIOProc(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData) { // your IOProc here ... } // New Mac OS X 10.5+ void NewFakePlay(AudioObjectID inDevice, void* inClientData) { // register the IOProc AudioDeviceIOProcID theIOProcID = NULL; OSStatus theError = AudioDeviceCreateIOProcID(inDevice, MyIOProc, inClientData, &theIOProcID); // handle errors // ensure theIOProcID != NULL // start IO theError = AudioDeviceStart(inDevice, theIOProcID); ... // stop IO theError = AudioDeviceStop(inDevice, theIOProcID); // unregister the IOProc theError = AudioDeviceDestroyIOProcID(inDevice, theIOProcID); } |
Property Accessor Changes
The Property Accessor changes are a little different but can be summed up like this -- All the individual class property access functions have been replaced by a similarly named AudioObject
-prefixed function.
The table below illustrates the basic mapping where 'XXX' in the older API name can be replaced by 'Hardware', 'Device' or 'Stream':
Deprecated API | New API |
---|---|
AudioXXXGetPropertyInfo | AudioObjectHasProperty, AudioObjectIsPropertySettable, AudioObjectGetPropertyDataSize |
AudioXXXGetProperty | AudioObjectGetPropertyData |
AudioXXXSetProperty | AudioObjectSetPropertyData |
AudioXXXAddPropertyListener | AudioObjectAddPropertyListener |
AudioXXXRemovePropertyListener | AudioObjectRemovePropertyListener |
The key difference between the deprecated and new API is the use of the AudioObjectPropertyAddress
structure.
struct AudioObjectPropertyAddress { AudioObjectPropertySelector mSelector; AudioObjectPropertyScope mScope; AudioObjectPropertyElement mElement; }; typedef struct AudioObjectPropertyAddress AudioObjectPropertyAddress; |
The AudioObjectPropertyAddress
structure is used with the new APIs to encapsulate the distinguishing information for a specific property; the selector ID (mSelector
), the scope (mScope
) and the element (mElement
). The HAL uses the terms scope and element in the same way that the AudioUnit API does.
Most objects have only one scope and one element, for example the System Object, Stream Object and Control Object have only one scope, kAudioObjectPropertyScopeGlobal
and one element, kAudioObjectPropertyElementMaster
.
Device Objects are different and may have three other scopes beside kAudioObjectPropertyScopeGlobal
. These are kAudioDevicePropertyScopeInput
, kAudioDevicePropertyScopeOutput
, and kAudioDevicePropertyScopePlayThrough
.
For a Device Object, the element (mElement
) of the AudioObjectPropertyAddress
structure refers to the channel number on the device.
Examples
Listing 3 Deprecated - Getting the default Input device.
AudioDeviceID DeprecatedGetDefaultInputDevice() { AudioDeviceID theAnswer = 0; UInt32 theSize = sizeof(AudioDeviceID); OSStatus theError = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &theAnswer); // handle errors return theAnswer; } |
Listing 4 New - Getting the default input device.
AudioDeviceID NewGetDefaultInputDevice() { AudioDeviceID theAnswer = 0; UInt32 theSize = sizeof(AudioDeviceID); AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; OSStatus theError = AudioObjectGetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, &theSize, &theAnswer); // handle errors return theAnswer; } |
Listing 5 Deprecated - Getting the current volume scalar.
Float32 DeprecatedGetVolumeScalar(AudioDeviceID inDevice, bool inIsInput, UInt32 inChannel) { Float32 theAnswer = 0; UInt32 theSize = sizeof(Float32); OSStatus theError = AudioDeviceGetProperty(inDevice, inChannel, inIsInput, kAudioDevicePropertyVolumeScalar, &theSize, &theAnswer); // handle errors return theAnswer; } |
Listing 6 New - Getting the current volume scalar.
Float32 NewGetVolumeScalar(AudioDeviceID inDevice, bool inIsInput, UInt32 inChannel) { Float32 theAnswer = 0; UInt32 theSize = sizeof(Float32); AudioObjectPropertyScope theScope = inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyVolumeScalar, theScope, inChannel }; OSStatus theError = AudioObjectGetPropertyData(inDevice, &theAddress, 0, NULL, &theSize, &theAnswer); // handle errors return theAnswer; } |
Note the usage of kAudioObjectSystemObject
when replacing the old APIs. kAudioObjectSystemObject
is an AudioObjectID
that always refers to the one and only instance of the Audio System Object.
Reference
See CoreAudio/AudioHardware.h
for further details.
Document Revision History
Date | Notes |
---|---|
2010-04-14 | Editorial |
2010-04-08 | Editorial |
2010-01-09 | New document that discusses transitioning to the newer AudioDevice and AudioObject APIs available on Mac OS X 10.5+ |
Copyright © 2010 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2010-04-14