From 1c44c3af6b235056265ca0435eb66f9b781ef10a Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Thu, 29 Jul 2021 13:49:09 +0200 Subject: [PATCH] ControlIndicatorTimer: Add support for legacy vsyncthread mode Due to concerns that a regular QTimer that fires during vsync could cause jerking legacy waveforms, this implements a way to use the legacy vsync thread/GuiTick infrastructure instead of a `QTimer` in the `ControlIndicatorTimer` (although I'm still not convinced that this actually makes a difference). This can be toggled explicitly using `setLegacyVsyncEnabled` when switching between a legacy and a QML skin (the latter has no vsync thread, so a regular timer needs to be used). Relevant discussion can be found here: https://github.com/mixxxdj/mixxx/pull/4157#issuecomment-888945348 --- src/control/controlindicatortimer.cpp | 38 ++++++++++++++++++++++++++- src/control/controlindicatortimer.h | 14 ++++++++++ src/coreservices.cpp | 2 +- src/coreservices.h | 6 ++++- src/mixxxmainwindow.cpp | 5 ++++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/control/controlindicatortimer.cpp b/src/control/controlindicatortimer.cpp index 4b84efef041..bcba1851b89 100644 --- a/src/control/controlindicatortimer.cpp +++ b/src/control/controlindicatortimer.cpp @@ -2,6 +2,7 @@ #include "control/controlobject.h" #include "moc_controlindicatortimer.cpp" +#include "util/math.h" namespace mixxx { @@ -10,7 +11,9 @@ ControlIndicatorTimer::ControlIndicatorTimer(QObject* pParent) m_pCOIndicator250millis(std::make_unique( ConfigKey("[Master]", "indicator_250millis"))), m_pCOIndicator500millis(std::make_unique( - ConfigKey("[Master]", "indicator_500millis"))) { + ConfigKey("[Master]", "indicator_500millis"))), + m_nextSwitchTime(0.0), + m_pCPGuiTick50ms(nullptr) { m_pCOIndicator250millis->setReadOnly(); m_pCOIndicator500millis->setReadOnly(); connect(&m_timer, &QTimer::timeout, this, &ControlIndicatorTimer::slotTimeout); @@ -28,4 +31,37 @@ void ControlIndicatorTimer::slotTimeout() { } } +// TODO: Everything below this comment only added for compatiblity with the +// legacy waveform vsync thread. It should be removed when the legacy skin +// system is dropped. + +void ControlIndicatorTimer::setLegacyVsyncEnabled(bool enabled) { + const bool isLegacyVsyncEnabled = (m_pCPGuiTick50ms != nullptr); + if (isLegacyVsyncEnabled == enabled) { + return; + } + + if (enabled) { + m_timer.stop(); + m_pCPGuiTick50ms = std::make_unique(ConfigKey("[Master]", "guiTick50ms")); + m_pCPGuiTick50ms->connectValueChanged(this, &ControlIndicatorTimer::slotGuiTick50ms); + } else { + m_pCPGuiTick50ms->disconnect(this); + m_pCPGuiTick50ms.reset(); + m_timer.start(250); + } +} + +void ControlIndicatorTimer::slotGuiTick50ms(double cpuTime) { + if (m_nextSwitchTime > cpuTime) { + return; + } + + constexpr double duration = 0.25; + const double tickTime = ControlObject::get(ConfigKey("[Master]", "guiTickTime")); + const double toggles = floor(tickTime / duration); + m_nextSwitchTime = (toggles + 1) * duration; + slotTimeout(); +} + } // namespace mixxx diff --git a/src/control/controlindicatortimer.h b/src/control/controlindicatortimer.h index 5472d19faf0..0a5d42e88d0 100644 --- a/src/control/controlindicatortimer.h +++ b/src/control/controlindicatortimer.h @@ -5,6 +5,7 @@ #include #include "control/controlobject.h" +#include "control/controlproxy.h" namespace mixxx { @@ -27,6 +28,19 @@ class ControlIndicatorTimer : public QObject { QTimer m_timer; std::unique_ptr m_pCOIndicator250millis; std::unique_ptr m_pCOIndicator500millis; + + /// TODO: Everything below this comment only added for compatiblity with the + /// legacy waveform vsync thread. It should be removed when the legacy skin + /// system is dropped. + public: + void setLegacyVsyncEnabled(bool enabled); + + private slots: + void slotGuiTick50ms(double cpuTime); + + private: + double m_nextSwitchTime; + std::unique_ptr m_pCPGuiTick50ms; }; } // namespace mixxx diff --git a/src/coreservices.cpp b/src/coreservices.cpp index 2f3ea05e5ba..fd8737b4fde 100644 --- a/src/coreservices.cpp +++ b/src/coreservices.cpp @@ -188,7 +188,7 @@ void CoreServices::initialize(QApplication* pApp) { exit(-1); } - m_pControlIndicatorTimer = std::make_unique(this); + m_pControlIndicatorTimer = std::make_shared(this); auto pChannelHandleFactory = std::make_shared(); diff --git a/src/coreservices.h b/src/coreservices.h index 5c403825dda..48e3ebc00b9 100644 --- a/src/coreservices.h +++ b/src/coreservices.h @@ -55,6 +55,10 @@ class CoreServices : public QObject { return m_pKbdConfig; } + std::shared_ptr getControlIndicatorTimer() const { + return m_pControlIndicatorTimer; + } + std::shared_ptr getSoundManager() const { return m_pSoundManager; } @@ -119,7 +123,7 @@ class CoreServices : public QObject { bool initializeDatabase(); std::shared_ptr m_pSettingsManager; - std::unique_ptr m_pControlIndicatorTimer; + std::shared_ptr m_pControlIndicatorTimer; std::shared_ptr m_pEffectsManager; // owned by EffectsManager LV2Backend* m_pLV2Backend; diff --git a/src/mixxxmainwindow.cpp b/src/mixxxmainwindow.cpp index 7d62fc83947..bf1b751a496 100644 --- a/src/mixxxmainwindow.cpp +++ b/src/mixxxmainwindow.cpp @@ -28,6 +28,7 @@ #ifdef __BROADCAST__ #include "broadcast/broadcastmanager.h" #endif +#include "control/controlindicatortimer.h" #include "control/controlpushbutton.h" #include "controllers/controllermanager.h" #include "controllers/keyboard/keyboardeventfilter.h" @@ -132,6 +133,8 @@ MixxxMainWindow::MixxxMainWindow( m_pCoreServices->initialize(pApp); + m_pCoreServices->getControlIndicatorTimer()->setLegacyVsyncEnabled(true); + UserSettingsPointer pConfig = m_pCoreServices->getSettings(); // Set the visibility of tooltips, default "1" = ON @@ -426,6 +429,8 @@ MixxxMainWindow::~MixxxMainWindow() { qDebug() << t.elapsed(false).debugMillisWithUnit() << "deleting DlgPreferences"; delete m_pPrefDlg; + m_pCoreServices->getControlIndicatorTimer()->setLegacyVsyncEnabled(false); + WaveformWidgetFactory::destroy(); delete m_pGuiTick;