Search code examples
macosaudiocore-audio

on macOS, can an app disable/suppress all system audio output which is not emitted by itself?


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.


Solution

  • 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.