From 0a3b60a2aeb819c13cb8cf87cee55f4acfb2dbc8 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sat, 27 Sep 2025 16:50:00 +0200 Subject: [PATCH 01/13] Waveform preferences: remove empty destructor --- src/preferences/dialog/dlgprefwaveform.cpp | 3 --- src/preferences/dialog/dlgprefwaveform.h | 1 - 2 files changed, 4 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index d1d724fee56f..92ca820b9f41 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -246,9 +246,6 @@ DlgPrefWaveform::DlgPrefWaveform( setScrollSafeGuardForAllInputWidgets(this); } -DlgPrefWaveform::~DlgPrefWaveform() { -} - void DlgPrefWaveform::slotSetWaveformOptions( allshader::WaveformRendererSignalBase::Option option, bool enabled) { allshader::WaveformRendererSignalBase::Options currentOption = m_pConfig->getValue( diff --git a/src/preferences/dialog/dlgprefwaveform.h b/src/preferences/dialog/dlgprefwaveform.h index f5d3545f0cfa..4efb8c396802 100644 --- a/src/preferences/dialog/dlgprefwaveform.h +++ b/src/preferences/dialog/dlgprefwaveform.h @@ -21,7 +21,6 @@ class DlgPrefWaveform : public DlgPreferencePage, public Ui::DlgPrefWaveformDlg QWidget* pParent, UserSettingsPointer pConfig, std::shared_ptr pLibrary); - virtual ~DlgPrefWaveform(); public slots: void slotUpdate() override; From 63e48ff89d8d17f5b82cdf73ae86222012572031 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Thu, 11 Sep 2025 17:13:30 +0200 Subject: [PATCH 02/13] Waveform preferences: move get/set acceleration to factory methods --- src/preferences/dialog/dlgprefwaveform.cpp | 47 +++++----------------- src/waveform/waveformwidgetfactory.cpp | 19 +++++++-- src/waveform/waveformwidgetfactory.h | 2 + 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index 92ca820b9f41..8927aeb97928 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -18,8 +18,6 @@ const ConfigKey kOverviewTypeCfgKey(kWaveformGroup, QStringLiteral("WaveformOverviewType")); const ConfigKey kWaveformOptionsKey(kWaveformGroup, QStringLiteral("waveform_options")); -const ConfigKey kHardwareAccelerationKey(kWaveformGroup, - QStringLiteral("use_hardware_acceleration")); } // namespace // for OverviewType @@ -270,10 +268,8 @@ void DlgPrefWaveform::slotUpdate() { if (factory->isOpenGlAvailable() || factory->isOpenGlesAvailable()) { openGlStatusData->setText(factory->getOpenGLVersion()); useAccelerationCheckBox->setEnabled(true); - isAccelerationEnabled = m_pConfig->getValue( - kHardwareAccelerationKey, - factory->preferredBackend()) != - WaveformWidgetBackend::None; + isAccelerationEnabled = + factory->getBackendFromConfig() != WaveformWidgetBackend::None; useAccelerationCheckBox->setChecked(isAccelerationEnabled); } else { openGlStatusData->setText(tr("OpenGL not available") + ": " + factory->getOpenGLVersion()); @@ -293,9 +289,7 @@ void DlgPrefWaveform::slotUpdate() { allshader::WaveformRendererSignalBase::Options currentOptions = m_pConfig->getValue( kWaveformOptionsKey, allshader::WaveformRendererSignalBase::Option::None); - WaveformWidgetBackend backend = m_pConfig->getValue( - kHardwareAccelerationKey, - factory->preferredBackend()); + WaveformWidgetBackend backend = factory->getBackendFromConfig(); updateWaveformAcceleration(factory->getType(), backend); updateWaveformTypeOptions(useWaveform, backend, currentOptions); waveformTypeComboBox->setEnabled(useWaveform); @@ -386,7 +380,7 @@ void DlgPrefWaveform::slotResetToDefaults() { // Restore waveform backend and option setting instantly m_pConfig->setValue(kWaveformOptionsKey, allshader::WaveformRendererSignalBase::Option::None); - m_pConfig->setValue(kHardwareAccelerationKey, defaultBackend); + factory->setDefaultBackend(); factory->setWidgetTypeFromHandle( factory->findHandleIndexFromType( WaveformWidgetFactory::defaultType()), @@ -445,7 +439,7 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { waveformTypeComboBox->itemData(index).toInt()); auto* factory = WaveformWidgetFactory::instance(); - auto backend = m_pConfig->getValue(kHardwareAccelerationKey, factory->preferredBackend()); + auto backend = factory->getBackendFromConfig(); // When setting the type, factory uses current 'use acceleration' state, // which may currently be off. However, with QOpenGL there are Simple and Stacked // which require acceleration and auto-enable it if possible. @@ -455,16 +449,7 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { // Store the value so it's available in factory. Same as // slotSetWaveformAcceleration(useAccelerationCheckBox->isChecked()) just // without the redundant actions - if (useAccelerationCheckBox->isChecked()) { - backend = -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - ; - } - m_pConfig->setValue(kHardwareAccelerationKey, backend); + factory->setAcceleration(useAccelerationCheckBox->isChecked()); // Now set the new type factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type)); @@ -492,19 +477,9 @@ void DlgPrefWaveform::slotSetWaveformEnabled(bool checked) { } void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { - WaveformWidgetBackend backend = WaveformWidgetBackend::None; - if (checked) { - backend = -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - ; - } - m_pConfig->setValue(kHardwareAccelerationKey, backend); - auto type = static_cast(waveformTypeComboBox->currentData().toInt()); auto* factory = WaveformWidgetFactory::instance(); + auto backend = factory->setAcceleration(checked); + auto type = static_cast(waveformTypeComboBox->currentData().toInt()); factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); allshader::WaveformRendererSignalBase::Options currentOptions = m_pConfig->getValue( kWaveformOptionsKey, @@ -586,10 +561,8 @@ void DlgPrefWaveform::updateEnableUntilMark() { #else WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); const bool enabled = - WaveformWidgetFactory::instance()->widgetTypeSupportsUntilMark() && - m_pConfig->getValue(kHardwareAccelerationKey, - factory->preferredBackend()) != - WaveformWidgetBackend::None; + factory->widgetTypeSupportsUntilMark() && + factory->getBackendFromConfig() != WaveformWidgetBackend::None; #endif untilMarkShowBeatsCheckBox->setEnabled(enabled); untilMarkShowTimeCheckBox->setEnabled(enabled); diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index 3c0f273dfeff..d659ce5288df 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -695,6 +695,21 @@ bool WaveformWidgetFactory::setWidgetTypeFromHandle(int handleIndex, bool force) return true; } +WaveformWidgetBackend WaveformWidgetFactory::setAcceleration(bool enabled) { + WaveformWidgetBackend backend = WaveformWidgetBackend::None; + if (enabled) { + backend = +#ifdef MIXXX_USE_QOPENGL + WaveformWidgetBackend::AllShader +#else + WaveformWidgetBackend::GL +#endif + ; + } + m_config->setValue(kHardwareAccelerationKey, backend); + return backend; +} + void WaveformWidgetFactory::setDefaultZoom(double zoom) { m_defaultZoom = math_clamp(zoom, WaveformWidgetRenderer::s_waveformMinZoom, WaveformWidgetRenderer::s_waveformMaxZoom); @@ -1304,9 +1319,7 @@ WaveformWidgetBackend WaveformWidgetFactory::getBackendFromConfig() const { // in case of issue when we release, we can communicate workaround on // editing the INI file to target a specific rendering backend. If no // complains come back, we can convert this safely to a backend eventually. - return m_config->getValue( - ConfigKey(QStringLiteral("[Waveform]"), QStringLiteral("use_hardware_acceleration")), - preferredBackend()); + return m_config->getValue(kHardwareAccelerationKey, preferredBackend()); } WaveformWidgetBackend WaveformWidgetFactory::preferredBackend() const { diff --git a/src/waveform/waveformwidgetfactory.h b/src/waveform/waveformwidgetfactory.h index edbccfc0feed..d88ae9a2c24a 100644 --- a/src/waveform/waveformwidgetfactory.h +++ b/src/waveform/waveformwidgetfactory.h @@ -227,6 +227,8 @@ class WaveformWidgetFactory : public QObject, } static bool isOverviewNormalizedDefault(); + WaveformWidgetBackend setAcceleration(bool enabled); + const QVector& getAvailableTypes() const { return m_waveformWidgetHandles; } From f8a1c3e00cbef39a5fee647ccfedc145fa59c767 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sat, 27 Sep 2025 17:21:53 +0200 Subject: [PATCH 03/13] Waveform preferences: move get/set WaveformOptions to factory methods --- src/preferences/dialog/dlgprefwaveform.cpp | 52 +++++----------------- src/waveform/waveformwidgetfactory.cpp | 38 ++++++++++++++++ src/waveform/waveformwidgetfactory.h | 7 +++ 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index 8927aeb97928..565549a711ad 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -16,8 +16,6 @@ namespace { const QString kWaveformGroup(QStringLiteral("[Waveform]")); const ConfigKey kOverviewTypeCfgKey(kWaveformGroup, QStringLiteral("WaveformOverviewType")); -const ConfigKey kWaveformOptionsKey(kWaveformGroup, - QStringLiteral("waveform_options")); } // namespace // for OverviewType @@ -246,17 +244,10 @@ DlgPrefWaveform::DlgPrefWaveform( void DlgPrefWaveform::slotSetWaveformOptions( allshader::WaveformRendererSignalBase::Option option, bool enabled) { - allshader::WaveformRendererSignalBase::Options currentOption = m_pConfig->getValue( - kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); - m_pConfig->setValue(ConfigKey("[Waveform]", "waveform_options"), - enabled ? currentOption | - option - : currentOption ^ - option); + auto* factory = WaveformWidgetFactory::instance(); + factory->setWaveformOption(option, enabled); auto type = static_cast( waveformTypeComboBox->currentData().toInt()); - auto* factory = WaveformWidgetFactory::instance(); factory->setWidgetTypeFromHandle( factory->findHandleIndexFromType(type), true); } @@ -286,9 +277,7 @@ void DlgPrefWaveform::slotUpdate() { bool useWaveform = factory->getType() != WaveformWidgetType::Empty; useWaveformCheckBox->setChecked(useWaveform); - allshader::WaveformRendererSignalBase::Options currentOptions = m_pConfig->getValue( - kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); + allshader::WaveformRendererSignalBase::Options currentOptions = factory->getWaveformOptions(); WaveformWidgetBackend backend = factory->getBackendFromConfig(); updateWaveformAcceleration(factory->getType(), backend); updateWaveformTypeOptions(useWaveform, backend, currentOptions); @@ -378,8 +367,7 @@ void DlgPrefWaveform::slotResetToDefaults() { allshader::WaveformRendererSignalBase::Option::None); // Restore waveform backend and option setting instantly - m_pConfig->setValue(kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); + factory->resetWaveformOptions(); factory->setDefaultBackend(); factory->setWidgetTypeFromHandle( factory->findHandleIndexFromType( @@ -454,9 +442,8 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { // Now set the new type factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type)); - allshader::WaveformRendererSignalBase::Options currentOptions = m_pConfig->getValue( - kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); + allshader::WaveformRendererSignalBase::Options currentOptions = + factory->getWaveformOptions(); updateWaveformTypeOptions(true, backend, currentOptions); updateEnableUntilMark(); updateStemOptionsEnabled(); @@ -481,9 +468,7 @@ void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { auto backend = factory->setAcceleration(checked); auto type = static_cast(waveformTypeComboBox->currentData().toInt()); factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); - allshader::WaveformRendererSignalBase::Options currentOptions = m_pConfig->getValue( - kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); + allshader::WWaveformRendererSignalBase::Options currentOptions = factory->getWaveformOptions(); updateWaveformTypeOptions(true, backend, currentOptions); updateEnableUntilMark(); updateStemOptionsEnabled(); @@ -492,14 +477,9 @@ void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { void DlgPrefWaveform::updateWaveformAcceleration( WaveformWidgetType::Type type, WaveformWidgetBackend backend) { auto* factory = WaveformWidgetFactory::instance(); - int handleIdx = factory->findHandleIndexFromType(type); - bool supportAcceleration = false, supportSoftware = true; - if (handleIdx != -1) { - const auto& handle = factory->getAvailableTypes()[handleIdx]; - supportAcceleration = handle.supportAcceleration(); - supportSoftware = handle.supportSoftware(); - } + bool supportAcceleration = factory->widgetTypeSupportsAcceleration(type); + bool supportSoftware = factory->widgetTypeSupportsSoftware(type); useAccelerationCheckBox->blockSignals(true); @@ -525,22 +505,14 @@ void DlgPrefWaveform::updateWaveformTypeOptions(bool useWaveform, #ifdef MIXXX_USE_QOPENGL WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); - allshader::WaveformRendererSignalBase::Options supportedOption = - allshader::WaveformRendererSignalBase::Option::None; auto type = static_cast(waveformTypeComboBox->currentData().toInt()); - int handleIdx = factory->findHandleIndexFromType(type); - - if (handleIdx != -1) { - supportedOption = factory->getAvailableTypes()[handleIdx].supportedOptions(backend); - } + auto supportedOptions = factory->getWaveformOptionsSupportedByType(type, backend); splitLeftRightCheckBox->setEnabled(useWaveform && - (supportedOption & - allshader::WaveformRendererSignalBase::Option::SplitStereoSignal)); + supportedOptions & allshader::WaveformRendererSignalBase::Option::SplitStereoSignal); highDetailCheckBox->setEnabled(useWaveform && - (supportedOption & - allshader::WaveformRendererSignalBase::Option::HighDetail)); + supportedOptions & allshader::WaveformRendererSignalBase::Option::HighDetail); splitLeftRightCheckBox->setChecked(splitLeftRightCheckBox->isEnabled() && (currentOptions & allshader::WaveformRendererSignalBase::Option::SplitStereoSignal)); diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index d659ce5288df..75a9ba334c08 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -72,6 +72,8 @@ const ConfigKey kWaveformTypeKey = ConfigKey(kWaveformGroup, QStringLiteral("WaveformType")); const ConfigKey kHardwareAccelerationKey = ConfigKey(kWaveformGroup, QStringLiteral("use_hardware_acceleration")); +const ConfigKey kWaveformOptionsKey(kWaveformGroup, + QStringLiteral("waveform_options")); const ConfigKey kZoomSyncKey = ConfigKey( kWaveformGroup, QStringLiteral("ZoomSynchronization")); const ConfigKey kEndOfTrackWarningKey = ConfigKey( @@ -1340,6 +1342,42 @@ void WaveformWidgetFactory::setDefaultBackend() { m_config->setValue(kHardwareAccelerationKey, preferredBackend()); } +allshader::WaveformRendererSignalBase::Options WaveformWidgetFactory::getWaveformOptions() { + auto options = m_config->getValue( + kWaveformOptionsKey, + allshader::WaveformRendererSignalBase::Option::None); + return options; +} + +allshader::WaveformRendererSignalBase::Options +WaveformWidgetFactory::getWaveformOptionsSupportedByType( + WaveformWidgetType::Type type, WaveformWidgetBackend backend) { + allshader::WaveformRendererSignalBase::Options supportedOptions = + allshader::WaveformRendererSignalBase::Option::None; + int handleIdx = findHandleIndexFromType(type); + if (handleIdx != -1) { + supportedOptions = getAvailableTypes()[handleIdx].supportedOptions(backend); + } + return supportedOptions; +} + +void WaveformWidgetFactory::setWaveformOption( + allshader::WaveformRendererSignalBase::Option option, bool enabled) { + allshader::WaveformRendererSignalBase::Options currentOption = m_config->getValue( + kWaveformOptionsKey, + allshader::WaveformRendererSignalBase::Option::None); + m_config->setValue(kWaveformOptionsKey, + enabled ? currentOption | + option + : currentOption ^ + option); +} + +void WaveformWidgetFactory::resetWaveformOptions() { + m_config->setValue(kWaveformOptionsKey, + allshader::WaveformRendererSignalBase::Option::None); +} + QString WaveformWidgetAbstractHandle::getDisplayName() const { return getDisplayName(m_type); } diff --git a/src/waveform/waveformwidgetfactory.h b/src/waveform/waveformwidgetfactory.h index d88ae9a2c24a..0e9633446e31 100644 --- a/src/waveform/waveformwidgetfactory.h +++ b/src/waveform/waveformwidgetfactory.h @@ -229,6 +229,13 @@ class WaveformWidgetFactory : public QObject, WaveformWidgetBackend setAcceleration(bool enabled); + allshader::WaveformRendererSignalBase::Options getWaveformOptions(); + allshader::WaveformRendererSignalBase::Options getWaveformOptionsSupportedByType( + WaveformWidgetType::Type type, WaveformWidgetBackend backend); + void setWaveformOption( + allshader::WaveformRendererSignalBase::Option option, bool enabled); + void resetWaveformOptions(); + const QVector& getAvailableTypes() const { return m_waveformWidgetHandles; } From 752e7d27578d075ef08324982ce21a74b32eec25 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sat, 27 Sep 2025 17:22:57 +0200 Subject: [PATCH 04/13] Waveform preferences: factory writes beatgrid alpha to config --- src/preferences/dialog/dlgprefwaveform.cpp | 3 --- src/waveform/waveformwidgetfactory.cpp | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index 565549a711ad..cfac64cc8bfb 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -653,9 +653,6 @@ void DlgPrefWaveform::slotClearCachedWaveforms() { } void DlgPrefWaveform::slotSetBeatGridAlpha(int alpha) { - // TODO(xxx) For consistency set this in WaveformWidgetFactory like - // the other waveform controls. - m_pConfig->setValue(ConfigKey(kWaveformGroup, QStringLiteral("beatGridAlpha")), alpha); WaveformWidgetFactory::instance()->setDisplayBeatGridAlpha(alpha); } diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index 75a9ba334c08..d8561f6e3a81 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -749,6 +749,7 @@ void WaveformWidgetFactory::setDisplayBeatGridAlpha(int alpha) { for (const auto& holder : std::as_const(m_waveformWidgetHolders)) { holder.m_waveformWidget->setDisplayBeatGridAlpha(m_beatGridAlpha); } + m_config->setValue(ConfigKey(kWaveformGroup, QStringLiteral("beatGridAlpha")), alpha); } void WaveformWidgetFactory::setVisualGain(BandIndex index, double gain) { From 2f9d2d5ecdab899249e536b29bc892f19ecdf3cd Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 12 Sep 2025 16:49:09 +0200 Subject: [PATCH 05/13] Waveform preferences: simplify set/update methods --- src/preferences/dialog/dlgprefwaveform.cpp | 49 +++++++++------------- src/preferences/dialog/dlgprefwaveform.h | 7 +--- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index cfac64cc8bfb..737491cbd0cd 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -255,11 +255,10 @@ void DlgPrefWaveform::slotSetWaveformOptions( void DlgPrefWaveform::slotUpdate() { WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); - bool isAccelerationEnabled = false; if (factory->isOpenGlAvailable() || factory->isOpenGlesAvailable()) { openGlStatusData->setText(factory->getOpenGLVersion()); useAccelerationCheckBox->setEnabled(true); - isAccelerationEnabled = + bool isAccelerationEnabled = factory->getBackendFromConfig() != WaveformWidgetBackend::None; useAccelerationCheckBox->setChecked(isAccelerationEnabled); } else { @@ -269,18 +268,17 @@ void DlgPrefWaveform::slotUpdate() { } // The combobox holds a list of [handle name, handle index] - int currentIndex = waveformTypeComboBox->findData(factory->getType()); - if (currentIndex != -1 && waveformTypeComboBox->currentIndex() != currentIndex) { - waveformTypeComboBox->setCurrentIndex(currentIndex); + int indexOfCurrentType = waveformTypeComboBox->findData(factory->getType()); + if (indexOfCurrentType != -1 && waveformTypeComboBox->currentIndex() != indexOfCurrentType) { + waveformTypeComboBox->setCurrentIndex(indexOfCurrentType); } - bool useWaveform = factory->getType() != WaveformWidgetType::Empty; + auto type = factory->getType(); + bool useWaveform = type != WaveformWidgetType::Empty; useWaveformCheckBox->setChecked(useWaveform); - allshader::WaveformRendererSignalBase::Options currentOptions = factory->getWaveformOptions(); - WaveformWidgetBackend backend = factory->getBackendFromConfig(); - updateWaveformAcceleration(factory->getType(), backend); - updateWaveformTypeOptions(useWaveform, backend, currentOptions); + updateWaveformAcceleration(type); + updateWaveformTypeOptions(useWaveform); waveformTypeComboBox->setEnabled(useWaveform); updateEnableUntilMark(); updateWaveformGeneralOptionsEnabled(); @@ -358,17 +356,14 @@ void DlgPrefWaveform::slotResetToDefaults() { if (defaultIndex != -1 && waveformTypeComboBox->currentIndex() != defaultIndex) { waveformTypeComboBox->setCurrentIndex(defaultIndex); } - auto defaultBackend = factory->preferredBackend(); + factory->setDefaultBackend(); useWaveformCheckBox->setChecked(true); waveformTypeComboBox->setEnabled(true); - updateWaveformAcceleration(WaveformWidgetFactory::defaultType(), defaultBackend); - updateWaveformTypeOptions(true, - defaultBackend, - allshader::WaveformRendererSignalBase::Option::None); + updateWaveformAcceleration(factory->defaultType()); // Restore waveform backend and option setting instantly factory->resetWaveformOptions(); - factory->setDefaultBackend(); + updateWaveformTypeOptions(true); factory->setWidgetTypeFromHandle( factory->findHandleIndexFromType( WaveformWidgetFactory::defaultType()), @@ -427,13 +422,12 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { waveformTypeComboBox->itemData(index).toInt()); auto* factory = WaveformWidgetFactory::instance(); - auto backend = factory->getBackendFromConfig(); // When setting the type, factory uses current 'use acceleration' state, // which may currently be off. However, with QOpenGL there are Simple and Stacked // which require acceleration and auto-enable it if possible. // FIXME Find a better solution? // See https://github.com/mixxxdj/mixxx/pull/15277 for details. - updateWaveformAcceleration(type, backend); + updateWaveformAcceleration(type); // Store the value so it's available in factory. Same as // slotSetWaveformAcceleration(useAccelerationCheckBox->isChecked()) just // without the redundant actions @@ -442,9 +436,7 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { // Now set the new type factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type)); - allshader::WaveformRendererSignalBase::Options currentOptions = - factory->getWaveformOptions(); - updateWaveformTypeOptions(true, backend, currentOptions); + updateWaveformTypeOptions(true); updateEnableUntilMark(); updateStemOptionsEnabled(); } @@ -465,18 +457,17 @@ void DlgPrefWaveform::slotSetWaveformEnabled(bool checked) { void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { auto* factory = WaveformWidgetFactory::instance(); - auto backend = factory->setAcceleration(checked); + factory->setAcceleration(checked); auto type = static_cast(waveformTypeComboBox->currentData().toInt()); factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); - allshader::WWaveformRendererSignalBase::Options currentOptions = factory->getWaveformOptions(); - updateWaveformTypeOptions(true, backend, currentOptions); + updateWaveformTypeOptions(true); updateEnableUntilMark(); updateStemOptionsEnabled(); } -void DlgPrefWaveform::updateWaveformAcceleration( - WaveformWidgetType::Type type, WaveformWidgetBackend backend) { +void DlgPrefWaveform::updateWaveformAcceleration(WaveformWidgetType::Type type) { auto* factory = WaveformWidgetFactory::instance(); + auto backend = factory->getBackendFromConfig(); bool supportAcceleration = factory->widgetTypeSupportsAcceleration(type); bool supportSoftware = factory->widgetTypeSupportsSoftware(type); @@ -497,9 +488,7 @@ void DlgPrefWaveform::updateWaveformAcceleration( useAccelerationCheckBox->blockSignals(false); } -void DlgPrefWaveform::updateWaveformTypeOptions(bool useWaveform, - WaveformWidgetBackend backend, - allshader::WaveformRendererSignalBase::Options currentOptions) { +void DlgPrefWaveform::updateWaveformTypeOptions(bool useWaveform) { splitLeftRightCheckBox->blockSignals(true); highDetailCheckBox->blockSignals(true); @@ -507,6 +496,8 @@ void DlgPrefWaveform::updateWaveformTypeOptions(bool useWaveform, WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); auto type = static_cast(waveformTypeComboBox->currentData().toInt()); + auto backend = factory->getBackendFromConfig(); + auto currentOptions = factory->getWaveformOptions(); auto supportedOptions = factory->getWaveformOptionsSupportedByType(type, backend); splitLeftRightCheckBox->setEnabled(useWaveform && diff --git a/src/preferences/dialog/dlgprefwaveform.h b/src/preferences/dialog/dlgprefwaveform.h index 4efb8c396802..3871cb76ca71 100644 --- a/src/preferences/dialog/dlgprefwaveform.h +++ b/src/preferences/dialog/dlgprefwaveform.h @@ -72,11 +72,8 @@ class DlgPrefWaveform : public DlgPreferencePage, public Ui::DlgPrefWaveformDlg void calculateCachedWaveformDiskUsage(); void notifyRebootNecessary(); void updateEnableUntilMark(); - void updateWaveformTypeOptions(bool useWaveform, - WaveformWidgetBackend backend, - allshader::WaveformRendererSignalBase::Options currentOption); - void updateWaveformAcceleration( - WaveformWidgetType::Type type, WaveformWidgetBackend backend); + void updateWaveformTypeOptions(bool useWaveform); + void updateWaveformAcceleration(WaveformWidgetType::Type type); void updateWaveformGeneralOptionsEnabled(); void updateWaveformGainEnabled(); void updateStemOptionsEnabled(); From a6e3b0299fb8e181c871890eb5d8185e021a5570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Tue, 16 Dec 2025 22:58:43 +0100 Subject: [PATCH 06/13] Fall back to WaveformWidgetBackend::None if some other is configured but not available. --- src/waveform/waveformwidgetfactory.cpp | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index d8561f6e3a81..167cbe17ab8f 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -1322,8 +1322,32 @@ WaveformWidgetBackend WaveformWidgetFactory::getBackendFromConfig() const { // in case of issue when we release, we can communicate workaround on // editing the INI file to target a specific rendering backend. If no // complains come back, we can convert this safely to a backend eventually. - return m_config->getValue(kHardwareAccelerationKey, preferredBackend()); -} + WaveformWidgetBackend backend = m_config->getValue( + kHardwareAccelerationKey, + preferredBackend()); + switch (backend) { + case WaveformWidgetBackend::None: + break; + case WaveformWidgetBackend::GL: + if (!m_openGlAvailable) { + backend = WaveformWidgetBackend::None; + } + break; + case WaveformWidgetBackend::GLSL: + if (!m_openGlAvailable || !m_openGLShaderAvailable) { + backend = WaveformWidgetBackend::None; + } + break; +#ifdef MIXXX_USE_QOPENGL + case WaveformWidgetBackend::AllShader: + if (!m_openGlAvailable && !m_openGlesAvailable) { + backend = WaveformWidgetBackend::None; + } + break; +#endif + } + return backend; +}; WaveformWidgetBackend WaveformWidgetFactory::preferredBackend() const { #ifdef MIXXX_USE_QOPENGL From 247c47a6ff95e9bf11599cee00132150bf1ef5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 17 Dec 2025 14:18:27 +0100 Subject: [PATCH 07/13] Rename pFactory --- src/preferences/dialog/dlgprefwaveform.cpp | 137 ++++++++++----------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index 737491cbd0cd..ea1e09c08aea 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -55,11 +55,11 @@ DlgPrefWaveform::DlgPrefWaveform( m_pTypeControl->forceSet(cfgTypeIndex); // Populate waveform options. - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); // We assume that the original type list order remains constant. // We will use the type index later on to set waveform types and to // update the combobox. - QVector types = factory->getAvailableTypes(); + QVector types = pFactory->getAvailableTypes(); for (int i = 0; i < types.size(); ++i) { if (types[i].getType() == WaveformWidgetType::Empty) { continue; @@ -190,7 +190,7 @@ DlgPrefWaveform::DlgPrefWaveform( this, &DlgPrefWaveform::slotSetOverviewMinuteMarkers); - connect(factory, + connect(pFactory, &WaveformWidgetFactory::waveformMeasured, this, &DlgPrefWaveform::slotWaveformMeasured); @@ -244,36 +244,35 @@ DlgPrefWaveform::DlgPrefWaveform( void DlgPrefWaveform::slotSetWaveformOptions( allshader::WaveformRendererSignalBase::Option option, bool enabled) { - auto* factory = WaveformWidgetFactory::instance(); - factory->setWaveformOption(option, enabled); + auto* pFactory = WaveformWidgetFactory::instance(); + pFactory->setWaveformOption(option, enabled); auto type = static_cast( waveformTypeComboBox->currentData().toInt()); - factory->setWidgetTypeFromHandle( - factory->findHandleIndexFromType(type), true); + pFactory->setWidgetTypeFromHandle( + pFactory->findHandleIndexFromType(type), true); } void DlgPrefWaveform::slotUpdate() { - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); - - if (factory->isOpenGlAvailable() || factory->isOpenGlesAvailable()) { - openGlStatusData->setText(factory->getOpenGLVersion()); + auto* pFactory = WaveformWidgetFactory::instance(); + if (pFactory->isOpenGlAvailable() || pFactory->isOpenGlesAvailable()) { + openGlStatusData->setText(pFactory->getOpenGLVersion()); useAccelerationCheckBox->setEnabled(true); bool isAccelerationEnabled = - factory->getBackendFromConfig() != WaveformWidgetBackend::None; + pFactory->getBackendFromConfig() != WaveformWidgetBackend::None; useAccelerationCheckBox->setChecked(isAccelerationEnabled); } else { - openGlStatusData->setText(tr("OpenGL not available") + ": " + factory->getOpenGLVersion()); + openGlStatusData->setText(tr("OpenGL not available") + ": " + pFactory->getOpenGLVersion()); useAccelerationCheckBox->setEnabled(false); useAccelerationCheckBox->setChecked(false); } // The combobox holds a list of [handle name, handle index] - int indexOfCurrentType = waveformTypeComboBox->findData(factory->getType()); + int indexOfCurrentType = waveformTypeComboBox->findData(pFactory->getType()); if (indexOfCurrentType != -1 && waveformTypeComboBox->currentIndex() != indexOfCurrentType) { waveformTypeComboBox->setCurrentIndex(indexOfCurrentType); } - auto type = factory->getType(); + auto type = pFactory->getType(); bool useWaveform = type != WaveformWidgetType::Empty; useWaveformCheckBox->setChecked(useWaveform); @@ -284,34 +283,34 @@ void DlgPrefWaveform::slotUpdate() { updateWaveformGeneralOptionsEnabled(); updateStemOptionsEnabled(); - frameRateSpinBox->setValue(factory->getFrameRate()); - frameRateSlider->setValue(factory->getFrameRate()); - endOfTrackWarningTimeSpinBox->setValue(factory->getEndOfTrackWarningTime()); - endOfTrackWarningTimeSlider->setValue(factory->getEndOfTrackWarningTime()); - synchronizeZoomCheckBox->setChecked(factory->isZoomSync()); - allVisualGain->setValue(factory->getVisualGain(BandIndex::AllBand)); - lowVisualGain->setValue(factory->getVisualGain(BandIndex::Low)); - midVisualGain->setValue(factory->getVisualGain(BandIndex::Mid)); - highVisualGain->setValue(factory->getVisualGain(BandIndex::High)); + frameRateSpinBox->setValue(pFactory->getFrameRate()); + frameRateSlider->setValue(pFactory->getFrameRate()); + endOfTrackWarningTimeSpinBox->setValue(pFactory->getEndOfTrackWarningTime()); + endOfTrackWarningTimeSlider->setValue(pFactory->getEndOfTrackWarningTime()); + synchronizeZoomCheckBox->setChecked(pFactory->isZoomSync()); + allVisualGain->setValue(pFactory->getVisualGain(BandIndex::AllBand)); + lowVisualGain->setValue(pFactory->getVisualGain(BandIndex::Low)); + midVisualGain->setValue(pFactory->getVisualGain(BandIndex::Mid)); + highVisualGain->setValue(pFactory->getVisualGain(BandIndex::High)); // Round zoom to int to get a default zoom index. - defaultZoomComboBox->setCurrentIndex(static_cast(factory->getDefaultZoom()) - 1); - playMarkerPositionSlider->setValue(static_cast(factory->getPlayMarkerPosition() * 100)); - beatGridAlphaSpinBox->setValue(factory->getBeatGridAlpha()); - beatGridAlphaSlider->setValue(factory->getBeatGridAlpha()); + defaultZoomComboBox->setCurrentIndex(static_cast(pFactory->getDefaultZoom()) - 1); + playMarkerPositionSlider->setValue(static_cast(pFactory->getPlayMarkerPosition() * 100)); + beatGridAlphaSpinBox->setValue(pFactory->getBeatGridAlpha()); + beatGridAlphaSlider->setValue(pFactory->getBeatGridAlpha()); - untilMarkShowBeatsCheckBox->setChecked(factory->getUntilMarkShowBeats()); - untilMarkShowTimeCheckBox->setChecked(factory->getUntilMarkShowTime()); + untilMarkShowBeatsCheckBox->setChecked(pFactory->getUntilMarkShowBeats()); + untilMarkShowTimeCheckBox->setChecked(pFactory->getUntilMarkShowTime()); untilMarkAlignComboBox->setCurrentIndex( WaveformWidgetFactory::toUntilMarkAlignIndex( - factory->getUntilMarkAlign())); - untilMarkTextPointSizeSpinBox->setValue(factory->getUntilMarkTextPointSize()); + pFactory->getUntilMarkAlign())); + untilMarkTextPointSizeSpinBox->setValue(pFactory->getUntilMarkTextPointSize()); untilMarkTextHeightLimitComboBox->setCurrentIndex( WaveformWidgetFactory::toUntilMarkTextHeightLimitIndex( - factory->getUntilMarkTextHeightLimit())); + pFactory->getUntilMarkTextHeightLimit())); - stemReorderLayerOnChangedCheckBox->setChecked(factory->isStemReorderOnChange()); - stemOpacitySpinBox->setValue(factory->getStemOpacity()); - stemOutlineOpacitySpinBox->setValue(factory->getStemOutlineOpacity()); + stemReorderLayerOnChangedCheckBox->setChecked(pFactory->isStemReorderOnChange()); + stemOpacitySpinBox->setValue(pFactory->getStemOpacity()); + stemOutlineOpacitySpinBox->setValue(pFactory->getStemOutlineOpacity()); OverviewType cfgOverviewType = m_pConfig->getValue(kOverviewTypeCfgKey, OverviewType::RGB); @@ -322,7 +321,7 @@ void DlgPrefWaveform::slotUpdate() { waveformOverviewComboBox->setCurrentIndex(cfgOverviewTypeIndex); } - if (factory->isOverviewNormalized()) { + if (pFactory->isOverviewNormalized()) { overview_scale_normalize->setChecked(true); } else { overview_scale_allReplayGain->setChecked(true); @@ -349,23 +348,23 @@ void DlgPrefWaveform::slotApply() { } void DlgPrefWaveform::slotResetToDefaults() { - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); int defaultIndex = waveformTypeComboBox->findData( WaveformWidgetFactory::defaultType()); if (defaultIndex != -1 && waveformTypeComboBox->currentIndex() != defaultIndex) { waveformTypeComboBox->setCurrentIndex(defaultIndex); } - factory->setDefaultBackend(); + pFactory->setDefaultBackend(); useWaveformCheckBox->setChecked(true); waveformTypeComboBox->setEnabled(true); - updateWaveformAcceleration(factory->defaultType()); + updateWaveformAcceleration(pFactory->defaultType()); // Restore waveform backend and option setting instantly - factory->resetWaveformOptions(); + pFactory->resetWaveformOptions(); updateWaveformTypeOptions(true); - factory->setWidgetTypeFromHandle( - factory->findHandleIndexFromType( + pFactory->setWidgetTypeFromHandle( + pFactory->findHandleIndexFromType( WaveformWidgetFactory::defaultType()), true); @@ -420,7 +419,7 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { } auto type = static_cast( waveformTypeComboBox->itemData(index).toInt()); - auto* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); // When setting the type, factory uses current 'use acceleration' state, // which may currently be off. However, with QOpenGL there are Simple and Stacked @@ -431,10 +430,10 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { // Store the value so it's available in factory. Same as // slotSetWaveformAcceleration(useAccelerationCheckBox->isChecked()) just // without the redundant actions - factory->setAcceleration(useAccelerationCheckBox->isChecked()); + pFactory->setAcceleration(useAccelerationCheckBox->isChecked()); // Now set the new type - factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type)); + pFactory->setWidgetTypeFromHandle(pFactory->findHandleIndexFromType(type)); updateWaveformTypeOptions(true); updateEnableUntilMark(); @@ -442,35 +441,35 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { } void DlgPrefWaveform::slotSetWaveformEnabled(bool checked) { - auto* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); if (!checked) { - factory->setWidgetTypeFromHandle( - factory->findHandleIndexFromType(WaveformWidgetType::Empty), + pFactory->setWidgetTypeFromHandle( + pFactory->findHandleIndexFromType(WaveformWidgetType::Empty), true); } else { auto type = static_cast( waveformTypeComboBox->currentData().toInt()); - factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); + pFactory->setWidgetTypeFromHandle(pFactory->findHandleIndexFromType(type), true); } slotUpdate(); } void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { - auto* factory = WaveformWidgetFactory::instance(); - factory->setAcceleration(checked); + auto* pFactory = WaveformWidgetFactory::instance(); + pFactory->setAcceleration(checked); auto type = static_cast(waveformTypeComboBox->currentData().toInt()); - factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); + pFactory->setWidgetTypeFromHandle(pFactory->findHandleIndexFromType(type), true); updateWaveformTypeOptions(true); updateEnableUntilMark(); updateStemOptionsEnabled(); } void DlgPrefWaveform::updateWaveformAcceleration(WaveformWidgetType::Type type) { - auto* factory = WaveformWidgetFactory::instance(); - auto backend = factory->getBackendFromConfig(); + auto* pFactory = WaveformWidgetFactory::instance(); + auto backend = pFactory->getBackendFromConfig(); - bool supportAcceleration = factory->widgetTypeSupportsAcceleration(type); - bool supportSoftware = factory->widgetTypeSupportsSoftware(type); + bool supportAcceleration = pFactory->widgetTypeSupportsAcceleration(type); + bool supportSoftware = pFactory->widgetTypeSupportsSoftware(type); useAccelerationCheckBox->blockSignals(true); @@ -493,17 +492,17 @@ void DlgPrefWaveform::updateWaveformTypeOptions(bool useWaveform) { highDetailCheckBox->blockSignals(true); #ifdef MIXXX_USE_QOPENGL - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); auto type = static_cast(waveformTypeComboBox->currentData().toInt()); - auto backend = factory->getBackendFromConfig(); - auto currentOptions = factory->getWaveformOptions(); - auto supportedOptions = factory->getWaveformOptionsSupportedByType(type, backend); + auto backend = pFactory->getBackendFromConfig(); + auto currentOptions = pFactory->getWaveformOptions(); + auto supportedOptions = pFactory->getWaveformOptionsSupportedByType(type, backend); splitLeftRightCheckBox->setEnabled(useWaveform && - supportedOptions & allshader::WaveformRendererSignalBase::Option::SplitStereoSignal); + (supportedOptions & allshader::WaveformRendererSignalBase::Option::SplitStereoSignal)); highDetailCheckBox->setEnabled(useWaveform && - supportedOptions & allshader::WaveformRendererSignalBase::Option::HighDetail); + (supportedOptions & allshader::WaveformRendererSignalBase::Option::HighDetail)); splitLeftRightCheckBox->setChecked(splitLeftRightCheckBox->isEnabled() && (currentOptions & allshader::WaveformRendererSignalBase::Option::SplitStereoSignal)); @@ -522,10 +521,10 @@ void DlgPrefWaveform::updateEnableUntilMark() { #ifndef MIXXX_USE_QOPENGL const bool enabled = false; #else - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); const bool enabled = - factory->widgetTypeSupportsUntilMark() && - factory->getBackendFromConfig() != WaveformWidgetBackend::None; + pFactory->widgetTypeSupportsUntilMark() && + pFactory->getBackendFromConfig() != WaveformWidgetBackend::None; #endif untilMarkShowBeatsCheckBox->setEnabled(enabled); untilMarkShowTimeCheckBox->setEnabled(enabled); @@ -560,10 +559,10 @@ void DlgPrefWaveform::updateStemOptionsEnabled() { #ifndef MIXXX_USE_QOPENGL const bool stemsSupported = false; #else - WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + auto* pFactory = WaveformWidgetFactory::instance(); const bool stemsSupported = - factory->widgetTypeSupportsStems() && - factory->getBackendFromConfig() == WaveformWidgetBackend::AllShader; + pFactory->widgetTypeSupportsStems() && + pFactory->getBackendFromConfig() == WaveformWidgetBackend::AllShader; #endif bool enabled = useWaveformCheckBox->isChecked(); stemOpacityMainLabel->setEnabled(stemsSupported && enabled); From 8870237aff7d5e12760e5980cae3a3405cafb9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 12 Jul 2026 16:37:17 +0200 Subject: [PATCH 08/13] Always handle all WaveformWidgetBackend values --- src/waveform/waveformwidgetfactory.cpp | 31 +++++++++++++++++------ src/waveform/widgets/waveformwidgettype.h | 2 -- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index bd10815c5f45..1a43cea4c1d8 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -1118,11 +1118,13 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createFilteredWaveformWidget( WaveformWidgetBackend backend = getBackendFromConfig(); switch (backend) { + case WaveformWidgetBackend::AllShader: #ifdef MIXXX_USE_QOPENGL - case WaveformWidgetBackend::AllShader: { return createAllshaderWaveformWidget(WaveformWidgetType::Type::Filtered, viewer); - } #endif + case WaveformWidgetBackend::None: + case WaveformWidgetBackend::GL: + case WaveformWidgetBackend::GLSL: default: return new SoftwareWaveformWidget(viewer->getGroup(), viewer); } @@ -1132,10 +1134,13 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createHSVWaveformWidget(WWaveform WaveformWidgetBackend backend = getBackendFromConfig(); switch (backend) { -#ifdef MIXXX_USE_QOPENGL case WaveformWidgetBackend::AllShader: +#ifdef MIXXX_USE_QOPENGL return createAllshaderWaveformWidget(WaveformWidgetType::HSV, viewer); #endif + case WaveformWidgetBackend::None: + case WaveformWidgetBackend::GL: + case WaveformWidgetBackend::GLSL: default: return new HSVWaveformWidget(viewer->getGroup(), viewer); } @@ -1145,10 +1150,13 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createRGBWaveformWidget(WWaveform WaveformWidgetBackend backend = getBackendFromConfig(); switch (backend) { -#ifdef MIXXX_USE_QOPENGL case WaveformWidgetBackend::AllShader: +#ifdef MIXXX_USE_QOPENGL return createAllshaderWaveformWidget(WaveformWidgetType::Type::RGB, viewer); #endif + case WaveformWidgetBackend::None: + case WaveformWidgetBackend::GL: + case WaveformWidgetBackend::GLSL: default: return new RGBWaveformWidget(viewer->getGroup(), viewer); } @@ -1156,12 +1164,16 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createRGBWaveformWidget(WWaveform WaveformWidgetAbstract* WaveformWidgetFactory::createStackedWaveformWidget( WWaveformViewer* viewer) { -#ifdef MIXXX_USE_QOPENGL WaveformWidgetBackend backend = getBackendFromConfig(); + switch (backend) { case WaveformWidgetBackend::AllShader: +#ifdef MIXXX_USE_QOPENGL return createAllshaderWaveformWidget(WaveformWidgetType::Type::Stacked, viewer); #endif + case WaveformWidgetBackend::None: + case WaveformWidgetBackend::GL: + case WaveformWidgetBackend::GLSL: default: return new EmptyWaveformWidget(viewer->getGroup(), viewer); } @@ -1171,10 +1183,13 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createSimpleWaveformWidget(WWavef WaveformWidgetBackend backend = getBackendFromConfig(); switch (backend) { -#ifdef MIXXX_USE_QOPENGL case WaveformWidgetBackend::AllShader: +#ifdef MIXXX_USE_QOPENGL return createAllshaderWaveformWidget(WaveformWidgetType::Type::Simple, viewer); #endif + case WaveformWidgetBackend::None: + case WaveformWidgetBackend::GL: + case WaveformWidgetBackend::GLSL: default: return new SimpleSignalWaveformWidget(viewer->getGroup(), viewer); } @@ -1349,13 +1364,13 @@ WaveformWidgetBackend WaveformWidgetFactory::getBackendFromConfig() const { backend = WaveformWidgetBackend::None; } break; -#ifdef MIXXX_USE_QOPENGL case WaveformWidgetBackend::AllShader: +#ifdef MIXXX_USE_QOPENGL if (!m_openGlAvailable && !m_openGlesAvailable) { backend = WaveformWidgetBackend::None; } - break; #endif + break; } return backend; }; diff --git a/src/waveform/widgets/waveformwidgettype.h b/src/waveform/widgets/waveformwidgettype.h index 6ed90df786e8..7d65677366b4 100644 --- a/src/waveform/widgets/waveformwidgettype.h +++ b/src/waveform/widgets/waveformwidgettype.h @@ -35,7 +35,5 @@ enum class WaveformWidgetBackend { None = 0, GL, GLSL, -#ifdef MIXXX_USE_QOPENGL AllShader, -#endif }; From ebc6f4c7b4a3bff11aafada2f2e8dcc3e95e6efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 12 Jul 2026 16:45:25 +0200 Subject: [PATCH 09/13] Verify in setAcceleration() that GL or GLES is available --- src/waveform/waveformwidgetfactory.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index 1a43cea4c1d8..dc017908a997 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -699,14 +699,12 @@ bool WaveformWidgetFactory::setWidgetTypeFromHandle(int handleIndex, bool force) WaveformWidgetBackend WaveformWidgetFactory::setAcceleration(bool enabled) { WaveformWidgetBackend backend = WaveformWidgetBackend::None; - if (enabled) { - backend = + if (enabled && (isOpenGlAvailable() || isOpenGlesAvailable())) { #ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader + backend = WaveformWidgetBackend::AllShader; #else - WaveformWidgetBackend::GL + backend = WaveformWidgetBackend::GL; #endif - ; } m_config->setValue(kHardwareAccelerationKey, backend); return backend; From 17782069441b3e853417562bc594089beca82ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 12 Jul 2026 17:13:08 +0200 Subject: [PATCH 10/13] Introduce kBeatGridAlpha for de-duplication --- src/waveform/waveformwidgetfactory.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index dc017908a997..e0a87c93028f 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -83,6 +83,7 @@ const ConfigKey kDefaultZoomKey = const ConfigKey kFrameRateKey = ConfigKey(kWaveformGroup, QStringLiteral("FrameRate")); const ConfigKey kVSyncKey = ConfigKey(kWaveformGroup, QStringLiteral("VSync")); +const ConfigKey kBeatGridAlpha = ConfigKey(kWaveformGroup, QStringLiteral("beatGridAlpha")); ConfigKey visualGainKey(int index) { return ConfigKey(kWaveformGroup, QStringLiteral("VisualGain_") + QString::number(index)); @@ -390,9 +391,7 @@ bool WaveformWidgetFactory::setConfig(UserSettingsPointer config) { bool zoomSync = m_config->getValue(kZoomSyncKey, m_zoomSync); setZoomSync(zoomSync); - int beatGridAlpha = - m_config->getValue(ConfigKey(kWaveformGroup, QStringLiteral("beatGridAlpha")), - m_beatGridAlpha); + int beatGridAlpha = m_config->getValue(kBeatGridAlpha, m_beatGridAlpha); setDisplayBeatGridAlpha(beatGridAlpha); WaveformWidgetType::Type type = static_cast( @@ -747,7 +746,7 @@ void WaveformWidgetFactory::setDisplayBeatGridAlpha(int alpha) { for (const auto& holder : std::as_const(m_waveformWidgetHolders)) { holder.m_waveformWidget->setDisplayBeatGridAlpha(m_beatGridAlpha); } - m_config->setValue(ConfigKey(kWaveformGroup, QStringLiteral("beatGridAlpha")), alpha); + m_config->setValue(kBeatGridAlpha, alpha); } void WaveformWidgetFactory::setVisualGain(BandIndex index, double gain) { From 5e7366a0967b34a2809ece5b0d03afd6ce4a7de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 17 Jul 2026 08:33:41 +0200 Subject: [PATCH 11/13] Reqires that the generic overload is not an enum type --- src/preferences/configobject.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/preferences/configobject.h b/src/preferences/configobject.h index c277295ed945..84aaed94bebf 100644 --- a/src/preferences/configobject.h +++ b/src/preferences/configobject.h @@ -177,7 +177,8 @@ template class ConfigObject { // Returns the value for key, converted to ResultType. If key is not present // or the value cannot be converted to ResultType, returns default_value. - template + template + requires(!std::is_enum_v) ResultType getValue(const ConfigKey& key, const ResultType& default_value) const; QString getValue(const ConfigKey& key, const char* default_value) const; template From 0f31d858e6e0c2707e7dc1079160a19ff0d122de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 12 Jul 2026 17:05:41 +0200 Subject: [PATCH 12/13] Add overload setValue(const ConfigKey& key, QFlagsType& value) --- src/preferences/configobject.h | 26 +++++++++++++++++++++----- src/waveform/waveformwidgetfactory.cpp | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/preferences/configobject.h b/src/preferences/configobject.h index 84aaed94bebf..3849108d60bd 100644 --- a/src/preferences/configobject.h +++ b/src/preferences/configobject.h @@ -154,16 +154,27 @@ template class ConfigObject { // returns QString(). QString getValueString(const ConfigKey& key) const; + template + struct is_qflags : std::false_type {}; + template + struct is_qflags> : std::true_type {}; + // Sets the value for key to ValueType(value), over-writing pre-existing // values. ResultType is serialized to string on a per-type basis. - template + template + requires(!std::is_enum_v && !is_qflags::value) void setValue(const ConfigKey& key, const ResultType& value); template - requires std::is_enum_v + requires(std::is_enum_v && !is_qflags::value) // we need to take value as const ref otherwise the overload is ambiguous void setValue(const ConfigKey& key, const EnumType& value) { setValue(key, static_cast(value)); }; + template + requires(is_qflags::value) + void setValue(const ConfigKey& key, const QFlagsType& value) { + setValue(key, value.toInt()); + } // Returns the value for key, converted to ResultType. If key is not present // or the value cannot be converted to ResultType, returns ResultType(). @@ -177,16 +188,21 @@ template class ConfigObject { // Returns the value for key, converted to ResultType. If key is not present // or the value cannot be converted to ResultType, returns default_value. - template - requires(!std::is_enum_v) + template + requires(!std::is_enum_v && !is_qflags::value) ResultType getValue(const ConfigKey& key, const ResultType& default_value) const; QString getValue(const ConfigKey& key, const char* default_value) const; template - requires std::is_enum_v + requires(std::is_enum_v && !is_qflags::value) EnumType getValue(const ConfigKey& key, const EnumType& default_value) const { // we need to take default_value as const ref otherwise the overload is ambiguous return static_cast(getValue(key, static_cast(default_value))); } + template + requires(is_qflags::value) + QFlagsType getValue(const ConfigKey& key, const QFlagsType& default_value) const { + return QFlagsType::fromInt(getValue(key, default_value.toInt())); + } QMultiHash transpose() const; diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index e0a87c93028f..a4ebfdee4f3a 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -1421,7 +1421,7 @@ void WaveformWidgetFactory::setWaveformOption( currentOptions.setFlag(option, enabled); // clear unsupported options currentOptions &= supportedOptions; - m_config->setValue(kWaveformOptionsKey, currentOptions); + m_config->setValue(kWaveformOptionsKey, currentOptions); } void WaveformWidgetFactory::resetWaveformOptions() { From b08f4a896fd3153b860b9b66118356dd82c1ea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 12 Jul 2026 17:08:58 +0200 Subject: [PATCH 13/13] Fix reading allshader::WaveformRendererSignalBase::Options as single Option --- src/waveform/waveformwidgetfactory.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index a4ebfdee4f3a..a6cf3e7b4bb5 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -1104,9 +1104,10 @@ void WaveformWidgetFactory::evaluateWidgets() { WaveformWidgetAbstract* WaveformWidgetFactory::createAllshaderWaveformWidget( WaveformWidgetType::Type type, WWaveformViewer* viewer) { - allshader::WaveformRendererSignalBase::Options options = - m_config->getValue(ConfigKey("[Waveform]", "waveform_options"), - allshader::WaveformRendererSignalBase::Option::None); + allshader::WaveformRendererSignalBase::Options options = m_config->getValue( + ConfigKey("[Waveform]", "waveform_options"), + allshader::WaveformRendererSignalBase::Options( + allshader::WaveformRendererSignalBase::Option::None)); return new allshader::WaveformWidget(viewer, type, viewer->getGroup(), options); } @@ -1391,9 +1392,9 @@ void WaveformWidgetFactory::setDefaultBackend() { } allshader::WaveformRendererSignalBase::Options WaveformWidgetFactory::getWaveformOptions() { - auto options = m_config->getValue( - kWaveformOptionsKey, - allshader::WaveformRendererSignalBase::Option::None); + auto options = m_config->getValue(kWaveformOptionsKey, + allshader::WaveformRendererSignalBase::Options( + allshader::WaveformRendererSignalBase::Option::None)); return options; }