macOS: Crash when unplugging headphones

,

Hi everyone,

my game (with custom engine) uses the fmod library (v2.02.07) for audio output. Few problems so far which is great!

However, when I unplug my headphones (connected via headphone jack, not USB or bluetooth) during gameplay on macOS, my app crashes with the following console output:

HAL_HardwarePlugIn_DeviceStart: no device
HALPlugIn::StopIOProc: got an error from the plug-in routine, Error: 560947818 (!obj)

Now, I am not sure if fmod is to blame here or some underlying macOS API but the problem is strictly reproducible and only occurs when unplugging the headphones from my machine, not when plugging it in during gameplay.

Any guesses about the potential root cause?

Thanks!
Thomas

Hi,

Do you have any FMOD logs that we could have a look at? If not, you can enable FMOD Logging by including the fmodL.dll and the fmodL_vc.lib. Included in the FMOD Engine directory under FMOD Studio API Windows/api/core/lib/x(the system you are using). Including those in your project, you will then need to initialize the debug system. You will call FMOD_Debug_Initialize(FMOD_DEBUG_LEVEL_LOG, FMOD_DEBUG_MODE_FILE, 0, "FILE NAME"). This will output all FMOD calls to a log file. If you could upload that log file it will help resolve the issue.

Hi Connor,

thanks for getting back to me. I did what you suggested and got the following log:

[LOG] SystemI::init : Initialize version=20207 (125130), maxchannels=32, flags=0x00000000
[LOG] SystemI::setOutputInternal : Setting output to ‘FMOD Core Audio Output’
[LOG] OutputCoreAudio::init : Output running 2 channels at 44100Hz sample rate.
[LOG] OutputCoreAudio::init : Maximum hardware read size: 512 samples, Software buffer size: 512 samples, Number of software buffers: 4.
[LOG] SystemI::init : Output requires a sample rate of 44100Hz, resampling will occur.
[LOG] Thread::initThread : Init FMOD stream thread. Affinity: 0x4000000000000003, Priority: 0xFFFF7FFB, Stack Size: 98304, Semaphore: No, Sleep Time: 10, Looping: Yes.
[LOG] Thread::initThread : Init FMOD mixer thread. Affinity: 0x4000000000000001, Priority: 0xFFFF7FFA, Stack Size: 81920, Semaphore: Yes, Sleep Time: 0, Looping: Yes.
[LOG] SystemI::createSoundInternal : Create name=‘assets/sounds/hit-a.mp3’, mode=0x00000200
[LOG] SystemI::DSPCodecPoolRegister : register codec pool for pool type 3
[LOG] SystemI::createSoundInternal : Sample 0/0: name=‘(null)’, format=2, channels=2, frequency=48000, lengthbytes=8976, lengthpcm=41472, pcmblocksize=1152, loopstart=0, loopend=0, mode=0x00000000, channelmask=0x00000000, channelorder=0, peakvolume=0.000000.
[LOG] SystemI::createSoundInternal : Create name=‘assets/tracks/corelli-op6-no12/corelli-op6-no12.ogg’, mode=0x00000080
[LOG] SystemI::createSoundInternal : Stream: name=‘(null)’, format=2, channels=2, frequency=44100, lengthbytes=3331708, lengthpcm=5340613, pcmblocksize=0, loopstart=0, loopend=0, mode=0x00000000, channelmask=0x00000000, channelorder=0, peakvolume=0.000000.
[LOG] Thread::initThread : Init FMOD file thread. Affinity: 0x4000000000000003, Priority: 0xFFFF7FFC, Stack Size: 65536, Semaphore: No, Sleep Time: 10, Looping: Yes.

I guess it doesn’t show anything unusual (the crash did happen but did not produce any visible FMOD log output) so I suspect the issue is outside of FMOD? I can also not reproduce the problem on Windows.

Best regards

Thomas

Thanks for sharing the log, I cannot see anything in there to indicate this failure is coming from FMOD.
It might be worth seeing if you still get the crash after disabling the default device switching behaviour. You can do this by setting an FMOD_SYSTEM_CALLBACK on FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED or FMOD_SYSTEM_CALLBACK_ALL and just returning FMOD_OK, e.g

FMOD_RESULT F_CALLBACK DeviceListChangedCallback(FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACK_TYPE type, void *commanddata1, void *commanddata2, void *userdata)
{
    return FMOD_OK;
}

int main()
{
    FMOD::System *system = 0;
    FMOD_RESULT result = FMOD::System_Create(&system);
    result = system->init(100, FMOD_INIT_NORMAL, 0);
    system->setCallback(&DeviceListChangedCallback, FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED);
    ...
}

Please give that a shot and let me know the outcome. If it doesn’t crash then you might be able to implement your own switching behaviour inside that callback to workaround the issue. Otherwise I have not been able to reproduce this- are you on the latest MacOS?

Thanks Jeff for the hints. I tried what you suggested. The crash still happens and the FMOD log output stays the same. What I do get is a slightly different general output:

AudioObjectGetPropertyData: no object with given ID 78
AudioObjectRemovePropertyListener: no object with given ID 78

Interestingly, when the crash happens, the stack is (reproducibly) residing in my Metal backend code which I find somewhat curious.

Best regards,
Thomas