From 7f592f78e87d6bbbae650d51c0d08f6919d91ed3 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 21 Feb 2015 01:54:50 -0800 Subject: [PATCH] Qt: Runtime configurable audio driver --- CHANGES | 1 + src/platform/qt/AudioProcessor.cpp | 33 ++++++++++++++++++++++++------ src/platform/qt/AudioProcessor.h | 12 +++++++++++ src/platform/qt/AudioProcessorQt.h | 2 +- src/platform/qt/CMakeLists.txt | 17 ++++++++++----- src/platform/qt/GBAApp.cpp | 4 ++++ src/platform/qt/GameController.cpp | 15 ++++++++++++++ src/platform/qt/GameController.h | 1 + src/platform/qt/SettingsView.cpp | 23 +++++++++++++++++++++ src/platform/qt/SettingsView.h | 1 + src/platform/qt/SettingsView.ui | 13 ------------ src/platform/qt/Window.cpp | 1 + 12 files changed, 98 insertions(+), 25 deletions(-) diff --git a/CHANGES b/CHANGES index 91fdac308..0dda282e8 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Features: - 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 diff --git a/src/platform/qt/AudioProcessor.cpp b/src/platform/qt/AudioProcessor.cpp index 6516da48f..42f92a318 100644 --- a/src/platform/qt/AudioProcessor.cpp +++ b/src/platform/qt/AudioProcessor.cpp @@ -7,7 +7,9 @@ #ifdef BUILD_SDL #include "AudioProcessorSDL.h" -#else +#endif + +#ifdef BUILD_QT_MULTIMEDIA #include "AudioProcessorQt.h" #endif @@ -17,12 +19,31 @@ extern "C" { using namespace QGBA; -AudioProcessor* AudioProcessor::create() { -#ifdef BUILD_SDL - return new AudioProcessorSDL(); +#ifdef BUILD_QT_MULTIMEDIA +AudioProcessor::Driver AudioProcessor::s_driver = AudioProcessor::Driver::QT_MULTIMEDIA; #else - return new AudioProcessorQt(); -#endif +AudioProcessor::Driver AudioProcessor::s_driver = AudioProcessor::Driver::SDL; +#endif + +AudioProcessor* AudioProcessor::create() { + switch (s_driver) { +#ifdef BUILD_SDL + 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 AudioProcessorSDL(); +#endif + } } AudioProcessor::AudioProcessor(QObject* parent) diff --git a/src/platform/qt/AudioProcessor.h b/src/platform/qt/AudioProcessor.h index 0f5e82ff7..a29763c23 100644 --- a/src/platform/qt/AudioProcessor.h +++ b/src/platform/qt/AudioProcessor.h @@ -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 @@ protected: private: GBAThread* m_context; int m_samples; + static Driver s_driver; }; } diff --git a/src/platform/qt/AudioProcessorQt.h b/src/platform/qt/AudioProcessorQt.h index 1c15a66a0..38edf28d7 100644 --- a/src/platform/qt/AudioProcessorQt.h +++ b/src/platform/qt/AudioProcessorQt.h @@ -7,7 +7,7 @@ #define QGBA_AUDIO_PROCESSOR_QT #include "AudioProcessor.h" - class QAudioOutput; +class QAudioOutput; namespace QGBA { diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 0783d0b2d..531ab4886 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -74,15 +74,22 @@ qt5_wrap_ui(UI_FILES 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) diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index b69ebc05b..e11315b17 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GBAApp.h" +#include "AudioProcessor.h" #include "GameController.h" #include @@ -38,6 +39,9 @@ GBAApp::GBAApp(int& argc, char* argv[]) } freeArguments(&args); + AudioProcessor::setDriver(static_cast(m_configController.getQtOption("audioDriver").toInt())); + m_window.controller()->reloadAudioDriver(); + #ifdef Q_OS_MAC m_window.show(); #endif diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 250710bfc..eff59a9e8 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -460,6 +460,21 @@ void GameController::clearAVStream() { 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(value - 0x16, 0); diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 2c11837f6..32cfb2352 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -106,6 +106,7 @@ public slots: void setTurbo(bool, bool forced = true); void setAVStream(GBAAVStream*); void clearAVStream(); + void reloadAudioDriver(); void setLuminanceValue(uint8_t value); void setLuminanceLevel(int level); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 12ee968ea..95c6e34e0 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SettingsView.h" +#include "AudioProcessor.h" #include "ConfigController.h" #include @@ -39,6 +40,21 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent) 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(AudioProcessor::Driver::QT_MULTIMEDIA)); + if (audioDriver == static_cast(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(AudioProcessor::Driver::SDL)); + if (audioDriver == static_cast(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())); } @@ -76,6 +92,13 @@ void SettingsView::updateConfig() { 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(audioDriver.toInt())); + emit audioDriverChanged(); + } + m_controller->write(); emit biosLoaded(m_ui.bios->text()); diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index b6fd981ee..73694facd 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -22,6 +22,7 @@ public: signals: void biosLoaded(const QString&); + void audioDriverChanged(); private slots: void selectBios(); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 8b2b7b3e4..b3852c4ec 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -89,25 +89,12 @@ - - false - 0 0 - - - SDL - - - - - Qt Multimedia - - diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 0bf6a3274..72a2c9948 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -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(); }