How to fallback to the default audio device using AudioDeviceManager?


#1

https://docs.juce.com/master/tutorial_audio_device_manager.html
This tutorial said that:

The AudioDeviceManager class can also fallback to the default device in such circumstances if the preferred device is no longer available (for example, if an external audio device has been unplugged since the last launch).

But after building this tutorial, I found that when I unplugged the initial audio device, the current audio device wil become empty…and when I plugged it back, this audio device will no longer work either…
Unless I re-select this audio device by hand…
But isn’t there, and shouldn’t there be some convinent way to fallback to the default device automaticlly???


[bug report] AudioSourcePlayer cannot playback audio after re-plugging the initialized audio device
#2

Is there anyone for this issue??
@jules @t0m @ed95
I sent three similar posts, but after a few days passed, none of them got your reply. Is this post different from other posts in the forum? Why don’t you reply to me?


#3

We’re currently looking into some related issues with the AudioDeviceSelectorComponent and improving the behaviour of the AudioDeviceManager will be part of that.


We’re still catching up with a backlog of forum messages. If we can respond instantly then we will, but otherwise there will be a bit of a delay. The JUCE team doesn’t work over the weekends so please bear with us!


#4

Thanks, Tom
And I apologize for my rude attitude.
I mainly want to confirm that this issue is indeed on your todo list, and will be fixed in the next release.
So looking forward for your update!:wink:


#5

I completely understand; it can be frustrating to have gone to the effort of preparing a bug report only to hear nothing back. We always appreciate people letting us know how we can do things better, even if we’re a bit slow to acknowledge them!


#6

#7

Thanks Tom.
But when I try this out using the AudioDeviceManagerTutorial, it crashed at:
AudioDeviceManagerTutorial.exe!juce::CharPointer_UTF8::CharPointer_UTF8(const juce::CharPointer_UTF8 & other) line 45 C++

An exception was thrown: Read access permission conflict.
other is 0x18.

when I unplugged the external audio device.

Here is the call stack, maybe it is helpful to you:

> AudioDeviceManagerTutorial.exe!juce::CharPointer_UTF8::CharPointer_UTF8(const juce::CharPointer_UTF8 & other) 行 45 C++
AudioDeviceManagerTutorial.exe!juce::String::String(const juce::String & other) 行 252 C++
AudioDeviceManagerTutorial.exe!juce::XmlElement::XmlElement(const juce::XmlElement & other) 行 111 C++
AudioDeviceManagerTutorial.exe!juce::AudioDeviceManager::initialiseFromXML(const juce::XmlElement & xml, bool selectDefaultDeviceOnFailure, const juce::String & preferredDefaultDeviceName, const juce::AudioDeviceManager::AudioDeviceSetup * preferredSetupOptions) 行 262 C++
AudioDeviceManagerTutorial.exe!juce::AudioDeviceManager::audioDeviceListChanged() 行 143 C++
AudioDeviceManagerTutorial.exe!juce::AudioDeviceManager::CallbackHandler::audioDeviceListChanged() 行 80 C++
AudioDeviceManagerTutorial.exe!juce::AudioIODeviceType::callDeviceChangeListeners::__l2::(juce::AudioIODeviceType::Listener & l) 行 41 C++
AudioDeviceManagerTutorial.exe!juce::ListenerList<juce::AudioIODeviceType::Listener,juce::Array<juce::AudioIODeviceType::Listener *,juce::DummyCriticalSection,0> >::call<void (juce::AudioIODeviceType::Listener &) >(juce::AudioIODeviceType::callDeviceChangeListeners::__l2::void (juce::AudioIODeviceType::Listener &) && callback) 行 124 C++
AudioDeviceManagerTutorial.exe!juce::AudioIODeviceType::callDeviceChangeListeners() 行 42 C++
AudioDeviceManagerTutorial.exe!juce::WasapiClasses::WASAPIAudioIODeviceType::systemDeviceChanged() 行 1643 C++
AudioDeviceManagerTutorial.exe!juce::DeviceChangeDetector::timerCallback() 行 132 C++
AudioDeviceManagerTutorial.exe!juce::timer::TimerThread::callTimers() 行 119 C++
AudioDeviceManagerTutorial.exe!juce::timer::TimerThread::CallTimersMessage::messageCallback() 行 181 C++
AudioDeviceManagerTutorial.exe!juce::WindowsMessageHelpers::dispatchMessageFromLParam(__int64 lParam) 行 57 C++
AudioDeviceManagerTutorial.exe!juce::MessageManager::dispatchNextMessageOnSystemQueue(bool returnIfNoPendingMessages) 行 143 C++
AudioDeviceManagerTutorial.exe!juce::MessageManager::runDispatchLoop() 行 128 C++
AudioDeviceManagerTutorial.exe!juce::JUCEApplicationBase::main() 行 266 C++
AudioDeviceManagerTutorial.exe!WinMain(HINSTANCE__ * formal, HINSTANCE * __formal, char * __formal, int __formal) 行 64 C++

#8

But your commit did give me a lot of inspiration, and I fixed this issue in my project on my own.
Here is what I did to fix this:
First, I stored the last initialised audio device name (through the AudioDeviceManager’s getCurrentAudioDevice()->getName() method) in a String in the audio device initialisation code.
Then I made my class inherit from AudioIODeviceType::Listener, and implements the “audioDeviceListChanged()”, and use AudioDeviceManager’s getCurrentDeviceTypeObject()->addListener method to register my AudioIODeviceType::Listener subclass to the AudioDeviceManager after first initialisation of the AudioDeviceManager.
And finally, in my implementation of audioDeviceListChanged, I re-scan the audio devices (through AudioDeviceManager’s getCurrentDeviceTypeObject()->scanForDevices()), and then judge whether the new default device is the same as the last initialised one. If not, then re-initialise the audio device, then all the audio callbacks will be using the new audio device.

I hope this solution will give some inspiration to you guys, as well as some people who have encountered the same problem.


#9