From 1ab45e4994851d5a629db4a22d7825f79386ef5d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 1 Jun 2024 20:41:06 +0200 Subject: [PATCH] Configuration of output device for SDL Let users configure the output device that's used by the SDL driver. Code-wise the implementation is very similar to the input device configuration. Use a `QComboBox` instead of a `QLineEdit` for `m_device` and rename it to `m_playbackDeviceComboBox`. Rename `s_defaultInputDevice` to `s_systemDefaultDevice` because it is used in the context of playback and input devices. --- include/AudioSdl.h | 5 ++- src/core/audio/AudioSdl.cpp | 64 +++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/include/AudioSdl.h b/include/AudioSdl.h index d4f08733a..c8e9c4f7e 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -39,7 +39,6 @@ #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" -class QLineEdit; class QComboBox; namespace lmms @@ -67,10 +66,10 @@ public: void saveSettings() override; private: - QLineEdit * m_device; + QComboBox* m_playbackDeviceComboBox; QComboBox* m_inputDeviceComboBox = nullptr; - static QString s_defaultInputDevice; + static QString s_systemDefaultDevice; } ; diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index dedc7dc16..772317491 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -78,11 +78,19 @@ AudioSdl::AudioSdl( bool & _success_ful, AudioEngine* _audioEngine ) : SDL_AudioSpec actual; #ifdef LMMS_HAVE_SDL2 - m_outputDevice = SDL_OpenAudioDevice (nullptr, - 0, - &m_audioHandle, - &actual, - 0); + const QString playbackDevice = ConfigManager::inst()->value("audiosdl", "device"); + const bool isDefaultPlayback = playbackDevice.isEmpty(); + + // Try with the configured device + const auto playbackDeviceCStr = isDefaultPlayback ? nullptr : playbackDevice.toLocal8Bit().data(); + m_outputDevice = SDL_OpenAudioDevice(playbackDeviceCStr, 0, &m_audioHandle, &actual, 0); + + // If we did not get a device ID try again with the default device if we did not try that before + if (m_outputDevice == 0 && !isDefaultPlayback) + { + m_outputDevice = SDL_OpenAudioDevice(nullptr, 0, &m_audioHandle, &actual, 0); + } + if (m_outputDevice == 0) { qCritical( "Couldn't open SDL-audio: %s\n", SDL_GetError() ); return; @@ -291,22 +299,42 @@ void AudioSdl::sdlInputAudioCallback(Uint8 *_buf, int _len) { #endif -QString AudioSdl::setupWidget::s_defaultInputDevice = QObject::tr("[System Default]"); +QString AudioSdl::setupWidget::s_systemDefaultDevice = QObject::tr("[System Default]"); AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : AudioDeviceSetupWidget( AudioSdl::name(), _parent ) { QFormLayout * form = new QFormLayout(this); - QString dev = ConfigManager::inst()->value( "audiosdl", "device" ); - m_device = new QLineEdit( dev, this ); + m_playbackDeviceComboBox = new QComboBox(this); - form->addRow(tr("Device"), m_device); +#ifdef LMMS_HAVE_SDL2 + m_playbackDeviceComboBox->addItem(s_systemDefaultDevice); + + const int numberOfPlaybackDevices = SDL_GetNumAudioDevices(0); + for (int i = 0; i < numberOfPlaybackDevices; ++i) + { + const QString deviceName = SDL_GetAudioDeviceName(i, 0); + m_playbackDeviceComboBox->addItem(deviceName); + } + + QString playbackDevice = ConfigManager::inst()->value("audiosdl", "device"); + if (playbackDevice.isEmpty()) + { + m_playbackDeviceComboBox->setCurrentText(s_systemDefaultDevice); + } + else + { + m_playbackDeviceComboBox->setCurrentText(playbackDevice); + } +#endif + + form->addRow(tr("Device"), m_playbackDeviceComboBox); m_inputDeviceComboBox = new QComboBox(this); #ifdef LMMS_HAVE_SDL2 - m_inputDeviceComboBox->addItem(s_defaultInputDevice); + m_inputDeviceComboBox->addItem(s_systemDefaultDevice); const int numberOfInputDevices = SDL_GetNumAudioDevices(1); for (int i = 0; i < numberOfInputDevices; ++i) @@ -319,7 +347,7 @@ AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : const auto inputDevice = ConfigManager::inst()->value("audiosdl", "inputdevice"); if (inputDevice.isEmpty()) { - m_inputDeviceComboBox->setCurrentText(s_defaultInputDevice); + m_inputDeviceComboBox->setCurrentText(s_systemDefaultDevice); } else { @@ -335,11 +363,19 @@ AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : void AudioSdl::setupWidget::saveSettings() { - ConfigManager::inst()->setValue( "audiosdl", "device", - m_device->text() ); + const auto currentPlaybackDevice = m_playbackDeviceComboBox->currentText(); + if (currentPlaybackDevice == s_systemDefaultDevice) + { + // Represent the default input device with an empty string + ConfigManager::inst()->setValue("audiosdl", "device", ""); + } + else if (!currentPlaybackDevice.isEmpty()) + { + ConfigManager::inst()->setValue("audiosdl", "device", currentPlaybackDevice); + } const auto currentInputDevice = m_inputDeviceComboBox->currentText(); - if (currentInputDevice == s_defaultInputDevice) + if (currentInputDevice == s_systemDefaultDevice) { // Represent the default input device with an empty string ConfigManager::inst()->setValue("audiosdl", "inputdevice", "");