From 33457969073abec4f40afb803e6b255ed1a624f8 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Mon, 29 Apr 2024 21:51:40 +0200 Subject: [PATCH] Fall back to using the NULL audio backend if the default backends don't provide any devices. --- src/SFML/Audio/AudioDevice.cpp | 56 ++++++++++++++++++++++---------- src/SFML/Audio/SoundRecorder.cpp | 45 ++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/SFML/Audio/AudioDevice.cpp b/src/SFML/Audio/AudioDevice.cpp index a7693976c..700bae11b 100644 --- a/src/SFML/Audio/AudioDevice.cpp +++ b/src/SFML/Audio/AudioDevice.cpp @@ -30,6 +30,7 @@ #include #include +#include #include @@ -68,33 +69,52 @@ AudioDevice::AudioDevice() // Create the context m_context.emplace(); - auto contextConfig = ma_context_config_init(); - contextConfig.pLog = &*m_log; + auto contextConfig = ma_context_config_init(); + contextConfig.pLog = &*m_log; + ma_uint32 deviceCount = 0; + const auto nullBackend = ma_backend_null; + const std::array backendLists{nullptr, &nullBackend}; - if (const auto result = ma_context_init(nullptr, 0, &contextConfig, &*m_context); result != MA_SUCCESS) + for (const auto* backendList : backendLists) { - m_context.reset(); - err() << "Failed to initialize the audio context: " << ma_result_description(result) << std::endl; - return; + // We can set backendCount to 1 since it is ignored when backends is set to nullptr + if (const auto result = ma_context_init(backendList, 1, &contextConfig, &*m_context); result != MA_SUCCESS) + { + m_context.reset(); + err() << "Failed to initialize the audio playback context: " << ma_result_description(result) << std::endl; + return; + } + + // Count the playback devices + if (const auto result = ma_context_get_devices(&*m_context, nullptr, &deviceCount, nullptr, nullptr); + result != MA_SUCCESS) + { + err() << "Failed to get audio playback devices: " << ma_result_description(result) << std::endl; + return; + } + + // Check if there are audio playback devices available on the system + if (deviceCount > 0) + break; + + // Warn if no devices were found using the default backend list + if (backendList == nullptr) + err() << "No audio playback devices available on the system" << std::endl; + + // Clean up the context if we didn't find any devices + ma_context_uninit(&*m_context); } - // Count the playback devices - ma_uint32 deviceCount = 0; - - if (const auto result = ma_context_get_devices(&*m_context, nullptr, &deviceCount, nullptr, nullptr); - result != MA_SUCCESS) - { - err() << "Failed to get audio playback devices: " << ma_result_description(result) << std::endl; - return; - } - - // Check if there are audio playback devices available on the system + // If the NULL audio backend also doesn't provide a device we give up if (deviceCount == 0) { - err() << "No audio playback devices available on the system" << std::endl; + m_context.reset(); return; } + if (m_context->backend == ma_backend_null) + err() << "Using NULL audio backend for playback" << std::endl; + // Create the playback device m_playbackDevice.emplace(); diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp index 202ae0b04..da4493dce 100644 --- a/src/SFML/Audio/SoundRecorder.cpp +++ b/src/SFML/Audio/SoundRecorder.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -187,16 +188,52 @@ SoundRecorder::SoundRecorder() : m_impl(std::make_unique(this)) // Create the context m_impl->context.emplace(); - auto contextConfig = ma_context_config_init(); - contextConfig.pLog = &*m_impl->log; + auto contextConfig = ma_context_config_init(); + contextConfig.pLog = &*m_impl->log; + ma_uint32 deviceCount = 0; + const auto nullBackend = ma_backend_null; + const std::array backendLists{nullptr, &nullBackend}; - if (const auto result = ma_context_init(nullptr, 0, &contextConfig, &*m_impl->context); result != MA_SUCCESS) + for (const auto* backendList : backendLists) + { + // We can set backendCount to 1 since it is ignored when backends is set to nullptr + if (const auto result = ma_context_init(backendList, 1, &contextConfig, &*m_impl->context); result != MA_SUCCESS) + { + m_impl->context.reset(); + err() << "Failed to initialize the audio capture context: " << ma_result_description(result) << std::endl; + return; + } + + // Count the capture devices + if (const auto result = ma_context_get_devices(&*m_impl->context, nullptr, nullptr, nullptr, &deviceCount); + result != MA_SUCCESS) + { + err() << "Failed to get audio capture devices: " << ma_result_description(result) << std::endl; + return; + } + + // Check if there are audio capture devices available on the system + if (deviceCount > 0) + break; + + // Warn if no devices were found using the default backend list + if (backendList == nullptr) + err() << "No audio capture devices available on the system" << std::endl; + + // Clean up the context if we didn't find any devices + ma_context_uninit(&*m_impl->context); + } + + // If the NULL audio backend also doesn't provide a device we give up + if (deviceCount == 0) { m_impl->context.reset(); - err() << "Failed to initialize the audio context: " << ma_result_description(result) << std::endl; return; } + if (m_impl->context->backend == ma_backend_null) + err() << "Using NULL audio backend for capture" << std::endl; + // Create the capture device m_impl->initialize(); }