I’m working on hot swapping Audio output devices. Everything wokrs nice and smoothly until i re-plug the last remaining device in the system. When it’s remove i get this error:
[FMOD] OutputWASAPI::mixerThread : GetCurrentPadding returned 0x88890004. Device was unplugged!
After pluging it back, the DEVICE LIST CHANGED callback kicks in, but iterating through list of devices shows only one entry and it’s “no device” . Fmod never recovers and i can;t hear audio at all.
Same thing happens when i start the game with all devices unplugged.
Thanks for bringing this to our attention. What version of the FMOD integration are you using? Please could I get the code you are using to detect the output devices?
List<string> GetOutputDevices()
{
List<string> devices = new();
RuntimeManager.CoreSystem.getNumDrivers(out var drivers);
for (int i = 0; i < drivers; i++)
{
RuntimeManager.CoreSystem.getDriverInfo(i, out var name, 120, out Guid g, out int sample, out var speakerMode, out int a);
Debug.Log($"{i}: {name}");
if (g == Guid.Empty)
continue;
devices.Add(name);
}
return devices;
}
[AOT.MonoPInvokeCallback(typeof(FMOD.SYSTEM_CALLBACK))]
static FMOD.RESULT DeviceChangedCallback(IntPtr system, FMOD.SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata)
{
Debug.Log("output device list changed");
foreach (var instance in instances)
{
if (instance.GetOutputDevices().Count > 0)
instance.Setting.SetChoices(instance.GetOutputDevices());
else
instance.Setting.SetChoices(new List<string>());
}
return FMOD.RESULT.OK;
}
Hey @Connor_FMOD , we have experienced this issue on version 2.02.22 as well. Could you verify that it’s also broken on your end and also perhaps give an idea about a possible timeline for a fix?
Since Connor is away, I will continue with this support case.
I was able to reproduce this locally with a minimal Unity test. When the DEVICELISTCHANGED callback is registered, FMOD reports NoSound Driver after the last device is disabled, and it does not automatically switch back when the device becomes available again.
In this case the application needs to handle the device change itself (for example by selecting a driver again or reinitializing the system). If the callback is not registered, FMOD will normally handle device switching automatically.
There is also a related discussion here about handling device changes on Windows:
Hey! Thanks for the reply. Unfortunately, I don’t think that encompasses the entire situation here.
The problem is not about it not detecting driver changes or swapping to the most recently connected device automatically. That we already handle as the documentation says.
The problem is the method RuntimeManager.CoreSystem.getNumDrivers(out numDrivers); always returns 1 and the RuntimeManager.CoreSystem.getDriverInfo for that driver always returns the Guid.Empty driver.
And this keeps going on regardless of how many devices you connect after disconnecting the last.
This methods return the expected values when disconnecting or connecting devices as long as you don’t disconnect the last one.
In this case the application needs to handle the device change itself (for example by selecting a driver again or reinitializing the system)
What exactly do you mean by we should reinitialize the system ourselves?
Like, reinitialize the FMOD plugin entirely? or like the have to restart the app?
We can’t select a driver because FMOD detects none
A nasty workaround we ended up with was having to check every 5 seconds if there are other drivers returned that don’t have GUID.Empty, then we can fall back on using the DEVICELISTCHANGED callback.
But to be perfectly honest, it all just seems like a bug.
If I subscribe to a callback that says “DEVICELISTCHANGED” then when the device list changes, I should be able to query the device list and get something other than “EMPTY”
getNumDrivers returns the number of actual drivers the output plugin found, excluding nosound. However, if the last device is unplugged FMOD changes its output plugin to FMOD_OUTPUTTYPE_NOSOUND, which will always report a device count of 1 with a device called NoSound Driver.
You should be able to attempt switching to a new audio device in the DEVICELISTCHANGED callback using System::setOutput.
Sorry for the confusion earlier. When I mentioned “reinitializing the system”, I meant recreating the FMOD system instance via System::close and System::init. I was just exploring whether there might be another possible solution, but that may not be the best fit for your project.
Thanks for the feedback. I will pass this along to the dev team for further review and investigation.