In an app, I'm driving a laser projection device using a connected USB audio interface on macOS.
The laser device takes analog audio as an input.
As a safety feature, it would be great if I could make the audio output from my app the exclusive output, because any other audio from other apps or from the OS itself which is routed to the USB audio interface is mixed with my laser control audio, is unwanted and a potential safety hazard.
Is it possible on macOS to make my app's audio output exclusive? I know you can configure AVAudioSession on iOS to achieve this (somewhat - you can duck other apps' audio, but notification sounds will in turn duck your app), but is something like this possible on the Mac? It does not need to be AppStore compatible.
Yes, you can request that CoreAudio
gives you exclusive access to an audio output device. This is called hogging the device. If you hogged all of the devices, no other application (including the system) would be able to emit any sound.
Something like this would do the trick for a single device:
AudioObjectPropertyAddress HOG_MODE_PROPERTY = { kAudioDevicePropertyHogMode, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
AudioDeviceID deviceId = // your audio device ID
pid_t hoggingProcess = -1; // -1 means attempt to acquire exclusive access
UInt32 size = sizeof(pid_t);
AudioObjectSetPropertyData(deviceId, &HOG_MODE_PROPERTY, 0, NULL, size, &hoggingProcess);
assert(hoggingProcess == getpid()); // check that you have exclusive access
Hog mode works by setting an AudioObject
property called kAudioDevicePropertyHogMode
. The value of the property is -1 if the device is not hogged. If it is hogged the value is the process id of the hogging process.
If you jump to definition
on kAudioDevicePropertyHogMode
in Xcode
you can read the header doc for the hog mode property. That is the best way to learn about how this property (and pretty much anything and everything else in CoreAudio
) works.
For completeness, here's the header doc:
A pid_t indicating the process that currently owns exclusive access to the AudioDevice or a value of -1 indicating that the device is currently available to all processes. If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc. Note that when setting this property, the value passed in is ignored. If another process owns exclusive access, that remains unchanged. If the current process owns exclusive access, it is released and made available to all processes again. If no process has exclusive access (meaning the current value is -1), this process gains ownership of exclusive access. On return, the pid_t pointed to by inPropertyData will contain the new value of the property.