Qt: Runtime configurable audio driver
jump to
@@ -24,6 +24,7 @@ - Support loading 7-Zip files
- Drag and drop game loading - Cheat code support - Debugger: Add CLI functions for examining memory regions + - Runtime configurable audio driver Bugfixes: - ARM7: Extend prefetch by one stage - GBA Audio: Support 16-bit writes to FIFO audio
@@ -7,7 +7,9 @@ #include "AudioProcessor.h"
#ifdef BUILD_SDL #include "AudioProcessorSDL.h" -#else +#endif + +#ifdef BUILD_QT_MULTIMEDIA #include "AudioProcessorQt.h" #endif@@ -17,12 +19,31 @@ }
using namespace QGBA; +#ifdef BUILD_QT_MULTIMEDIA +AudioProcessor::Driver AudioProcessor::s_driver = AudioProcessor::Driver::QT_MULTIMEDIA; +#else +AudioProcessor::Driver AudioProcessor::s_driver = AudioProcessor::Driver::SDL; +#endif + AudioProcessor* AudioProcessor::create() { + switch (s_driver) { #ifdef BUILD_SDL - return new AudioProcessorSDL(); + case Driver::SDL: + return new AudioProcessorSDL(); +#endif + +#ifdef BUILD_QT_MULTIMEDIA + case Driver::QT_MULTIMEDIA: + return new AudioProcessorQt(); +#endif + + default: +#ifdef BUILD_QT_MULTIMEDIA + return new AudioProcessorQt(); #else - return new AudioProcessorQt(); -#endif + return new AudioProcessorSDL(); +#endif + } } AudioProcessor::AudioProcessor(QObject* parent)
@@ -15,7 +15,18 @@ class AudioProcessor : public QObject {
Q_OBJECT public: + enum class Driver { +#ifdef BUILD_QT_MULTIMEDIA + QT_MULTIMEDIA = 0, +#endif +#ifdef BUILD_SDL + SDL = 1, +#endif + }; + static AudioProcessor* create(); + static void setDriver(Driver driver) { s_driver = driver; } + AudioProcessor(QObject* parent = nullptr); virtual void setInput(GBAThread* input);@@ -34,6 +45,7 @@
private: GBAThread* m_context; int m_samples; + static Driver s_driver; }; }
@@ -7,7 +7,7 @@ #ifndef QGBA_AUDIO_PROCESSOR_QT
#define QGBA_AUDIO_PROCESSOR_QT #include "AudioProcessor.h" - class QAudioOutput; +class QAudioOutput; namespace QGBA {
@@ -74,15 +74,22 @@ VideoView.ui)
set(QT_LIBRARIES) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libqt5widgets5,libqt5opengl5" PARENT_SCOPE) + +set(AUDIO_SRC) if(BUILD_SDL) - list(APPEND SOURCE_FILES AudioProcessorSDL.cpp) -elseif(Qt5Multimedia_FOUND) - list(APPEND SOURCE_FILES + list(APPEND AUDIO_SRC AudioProcessorSDL.cpp) +endif() + +if(Qt5Multimedia_FOUND) + list(APPEND AUDIO_SRC AudioProcessorQt.cpp AudioDevice.cpp) list(APPEND QT_LIBRARIES Qt5::Multimedia) + add_definitions(-DBUILD_QT_MULTIMEDIA) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libqt5multimedia5" PARENT_SCOPE) -else() +endif() + +if(NOT AUDIO_SRC) message(WARNING "No supported audio modules found") set(BUILD_QT OFF PARENT_SCOPE) return()@@ -101,7 +108,7 @@ qt5_add_resources(RESOURCES resources.qrc)
if(WIN32) list(APPEND RESOURCES ${CMAKE_SOURCE_DIR}/res/mgba.rc) endif() -add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_FILES} ${RESOURCES}) +add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_FILES} ${AUDIO_SRC} ${RESOURCES}) set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in) list(APPEND QT_LIBRARIES Qt5::Widgets Qt5::OpenGL)
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GBAApp.h" +#include "AudioProcessor.h" #include "GameController.h" #include <QFileOpenEvent>@@ -37,6 +38,9 @@ } else {
m_window.loadConfig(); } freeArguments(&args); + + AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt())); + m_window.controller()->reloadAudioDriver(); #ifdef Q_OS_MAC m_window.show();
@@ -460,6 +460,21 @@ m_threadContext.stream = nullptr;
threadContinue(); } +void GameController::reloadAudioDriver() { + m_audioProcessor->pause(); + delete m_audioProcessor; + m_audioProcessor = AudioProcessor::create(); + m_audioProcessor->moveToThread(m_audioThread); + connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start())); + connect(this, SIGNAL(gameStopped(GBAThread*)), m_audioProcessor, SLOT(pause())); + connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); + connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); + if (isLoaded()) { + m_audioProcessor->setInput(&m_threadContext); + QMetaObject::invokeMethod(m_audioProcessor, "start"); + } +} + void GameController::setLuminanceValue(uint8_t value) { m_luxValue = value; value = std::max<int>(value - 0x16, 0);
@@ -106,6 +106,7 @@ void setFrameskip(int);
void setTurbo(bool, bool forced = true); void setAVStream(GBAAVStream*); void clearAVStream(); + void reloadAudioDriver(); void setLuminanceValue(uint8_t value); void setLuminanceLevel(int level);
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SettingsView.h" +#include "AudioProcessor.h" #include "ConfigController.h" #include <QFileDialog>@@ -39,6 +40,21 @@ } else if (idleOptimization == "detect") {
m_ui.idleOptimization->setCurrentIndex(2); } + int audioDriver = m_controller->getQtOption("audioDriver").toInt(); +#ifdef BUILD_QT_MULTIMEDIA + m_ui.audioDriver->addItem(tr("Qt Multimedia"), static_cast<int>(AudioProcessor::Driver::QT_MULTIMEDIA)); + if (audioDriver == static_cast<int>(AudioProcessor::Driver::QT_MULTIMEDIA)) { + m_ui.audioDriver->setCurrentIndex(m_ui.audioDriver->count() - 1); + } +#endif + +#ifdef BUILD_SDL + m_ui.audioDriver->addItem(tr("SDL"), static_cast<int>(AudioProcessor::Driver::SDL)); + if (audioDriver == static_cast<int>(AudioProcessor::Driver::SDL)) { + m_ui.audioDriver->setCurrentIndex(m_ui.audioDriver->count() - 1); + } +#endif + connect(m_ui.biosBrowse, SIGNAL(clicked()), this, SLOT(selectBios())); connect(m_ui.buttonBox, SIGNAL(accepted()), this, SLOT(updateConfig())); }@@ -74,6 +90,13 @@ break;
case IDLE_LOOP_DETECT: saveSetting("idleOptimization", "detect"); break; + } + + QVariant audioDriver = m_ui.audioDriver->itemData(m_ui.audioDriver->currentIndex()); + if (audioDriver != m_controller->getQtOption("audioDriver")) { + m_controller->setQtOption("audioDriver", audioDriver); + AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(audioDriver.toInt())); + emit audioDriverChanged(); } m_controller->write();
@@ -22,6 +22,7 @@ SettingsView(ConfigController* controller, QWidget* parent = nullptr);
signals: void biosLoaded(const QString&); + void audioDriverChanged(); private slots: void selectBios();
@@ -89,25 +89,12 @@ </widget>
</item> <item row="4" column="1"> <widget class="QComboBox" name="audioDriver"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <item> - <property name="text"> - <string>SDL</string> - </property> - </item> - <item> - <property name="text"> - <string>Qt Multimedia</string> - </property> - </item> </widget> </item> <item row="5" column="0">
@@ -219,6 +219,7 @@ void Window::openSettingsWindow() {
SettingsView* settingsWindow = new SettingsView(m_config); connect(this, SIGNAL(shutdown()), settingsWindow, SLOT(close())); connect(settingsWindow, SIGNAL(biosLoaded(const QString&)), m_controller, SLOT(loadBIOS(const QString&))); + connect(settingsWindow, SIGNAL(audioDriverChanged()), m_controller, SLOT(reloadAudioDriver())); settingsWindow->setAttribute(Qt::WA_DeleteOnClose); settingsWindow->show(); }