AudioDeviceSelectorComponent, DeviceType Issue

Hi
May I suggest a change in the AudioDeviceSelectorComponent?
When switching Device type, (ASIO/Direct Sound/etc) could the comp please NOT load the first driver in the list?
Just set it to “no device selected” or something.
I get plenty of crash reports from users wanting to use their asio device, but then get a crash when selecting ASIO. It then turns out the app is crashing because the first driver is loaded.
The first driver might be a disconnected device that crash, or one of the incompatible devices.
The way it is implemented now the user never gets a chance to select the actual working driver he/she wants.
Makes sense?

Hi
Any update on this, or suggestions for a mod?

It’s in our backlog, but everyone’s pretty busy on JUCE 5 stuff. I’m afraid I can’t give you a sensible ETA.

Any news on this, or suggestion on how to not make it open a “random” driver when selecting ASIO ? These crashes are so pain to help the end user track down

it is my humble opinion that it is better to return no device than try to find ASIO4ALL, or open a random driver.

I created this workaround:
Added “return -1;” in juce_win32_ASIO.cpp (1442)

int getDefaultDeviceIndex (bool) const override
{
 return -1; //dont return any default device, just "no device selected"   
 jassert (hasScanned); // need to call scanForDevices() before doing this
	
    for (int i = deviceNames.size(); --i >= 0;)
        if (deviceNames[i].containsIgnoreCase ("asio4all"))
            return i; // asio4all is a safe choice for a default..

   #if JUCE_DEBUG
    if (deviceNames.size() > 1 && deviceNames[0].containsIgnoreCase ("digidesign"))
        return 1; // (the digi m-box driver crashes the app when you run
                  // it in the debugger, which can be a bit annoying)
   #endif

    return 0;
}

Also added a check here:

void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const

As this, as far as I can tell, assumes a valid device index.
So I just surrounded it in:

  if (type->getDefaultDeviceIndex(false) >= 0)
  {

Running into this again 7 years after the original post. This seems a bit silly to me because on the one hand, we have code in AudioDeviceManager::insertDefaultDeviceNames() which is called by AudioDeviceManager::setCurrentAudioDeviceType() that does this:

// We set default device names, so in case no in-out pair passes the validation, we still
// produce the same result as before
if (setup.outputDeviceName.isEmpty() && ! outputsToTest.isEmpty())
    setup.outputDeviceName = outputsToTest[0];

if (setup.inputDeviceName.isEmpty() && ! inputsToTest.isEmpty())
    setup.inputDeviceName = inputsToTest[0];

And yet we have a jassert in juce_win32_ASIO.cpp in createDevice() that does this:

// ASIO can't open two different devices for input and output - they must be the same one.
jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty());

When using ASIO device types, this assert demands the input and output device names be the same, and yet insertDefaultDeviceNames() applies a default inputDeviceName which may be different than the output name, with no ability to intervene when making calls to AudioDeviceManager::setCurrentAudioDeviceType().

Since it appears that with ASIO the input and output device names must match, why not enforce that in AudioDeviceManager::insertDefaultDeviceNames() when the device type is ASIO?

For me, changing the end of AudioDeviceManager::insertDefaultDeviceNames() from:

// We check all possible in-out pairs until the first validation pass. If no pair passes we
// leave the setup unchanged.
for (const auto& out : outputsToTest)
{
    for (const auto& in : inputsToTest)
    {
        if (validate(out, in))
        {
             setup.outputDeviceName = out;
             setup.inputDeviceName = in;

             return;
        }
    }
}

To this…

// Windows ASIO requires input and output device names to match
if (type->getTypeName() == "ASIO")
{
    setup.inputDeviceName = setup.outputDeviceName;
}
else
{
    // We check all possible in-out pairs until the first validation pass. If no pair passes we
    // leave the setup unchanged.
    for (const auto& out : outputsToTest)
    {
        for (const auto& in : inputsToTest)
        {
            if (validate(out, in))
            {
                setup.outputDeviceName = out;
                setup.inputDeviceName = in;

                return;
            }
          }
    }
}

…fixes the issue and avoids the jassert.

1 Like