From b936aaef89c92f46f230f3038de97896dcaba63b Mon Sep 17 00:00:00 2001 From: ronso0 Date: Wed, 15 Nov 2023 16:22:50 +0100 Subject: [PATCH 01/12] Effects: store deck EQ effects in effects.xml --- src/effects/chains/equalizereffectchain.cpp | 1 - src/effects/effectsmanager.cpp | 45 +++++++++- .../presets/effectchainpresetmanager.cpp | 83 +++++++++++++++++- .../presets/effectchainpresetmanager.h | 9 +- src/effects/presets/effectxmlelements.h | 1 + src/preferences/dialog/dlgprefmixer.cpp | 85 +++++++++++-------- 6 files changed, 178 insertions(+), 46 deletions(-) diff --git a/src/effects/chains/equalizereffectchain.cpp b/src/effects/chains/equalizereffectchain.cpp index ccf341c6b6c..d7f56208ce3 100644 --- a/src/effects/chains/equalizereffectchain.cpp +++ b/src/effects/chains/equalizereffectchain.cpp @@ -29,7 +29,6 @@ EqualizerEffectChain::EqualizerEffectChain( setFilterWaveform( m_effectSlots.at(0)->getManifest()->isMixingEQ()); }); - // DlgPrefEq loads the Effect with loadEffectToGroup setupLegacyAliasesForGroup(handleAndGroup.name()); } diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index ec75b814a89..e8e37aff895 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -7,6 +7,7 @@ #include "effects/chains/outputeffectchain.h" #include "effects/chains/quickeffectchain.h" #include "effects/chains/standardeffectchain.h" +#include "effects/effectslot.h" #include "effects/effectsmessenger.h" #include "effects/presets/effectchainpreset.h" #include "effects/presets/effectpresetmanager.h" @@ -190,7 +191,7 @@ void EffectsManager::readEffectsXml() { } file.close(); - // Note: QuickEffect chains are created only for existing main decks + // Note: QuickEffect and EQ chains are created only for existing main decks, // thus only for those the configured presets are requested QStringList deckStrings; for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { @@ -202,6 +203,19 @@ void EffectsManager::readEffectsXml() { m_standardEffectChains.value(i)->loadChainPreset(data.standardEffectChainPresets.at(i)); } + for (auto it = data.eqEffectManifests.begin(); + it != data.eqEffectManifests.end(); + it++) { + auto pChainSlot = m_equalizerEffectChains.value(it.key()); + if (pChainSlot) { + const auto pEffectSlot = pChainSlot->getEffectSlot(0); + VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { + return; + } + pEffectSlot->loadEffectWithDefaults(it.value()); + } + } + for (auto it = data.quickEffectChainPresets.begin(); it != data.quickEffectChainPresets.end(); it++) { @@ -224,12 +238,23 @@ void EffectsManager::readEffectsXmlSingleDeck(const QString& deckGroup) { } file.close(); - EffectChainPresetPointer pQuickEffectChainPreset = + EffectXmlDataSingleDeck data = m_pChainPresetManager->readEffectsXmlSingleDeck(doc, deckGroup); + // Load EQ effect + auto pEqChainSlot = m_equalizerEffectChains.value(deckGroup); + if (pEqChainSlot) { + const auto pEffectSlot = pEqChainSlot->getEffectSlot(0); + VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { + return; + } + pEffectSlot->loadEffectWithDefaults(data.eqEffectManifest); + } + + // Load Quick Effect auto pQuickEffectChainSlot = m_quickEffectChains.value(deckGroup); if (pQuickEffectChainSlot) { - pQuickEffectChainSlot->loadChainPreset(pQuickEffectChainPreset); + pQuickEffectChainSlot->loadChainPreset(data.quickEffectChainPreset); } } @@ -241,6 +266,16 @@ void EffectsManager::saveEffectsXml() { "schemaVersion", QString::number(EffectXml::kXmlSchemaVersion)); doc.appendChild(rootElement); + QHash eqEffectManifests; + for (auto it = m_equalizerEffectChains.begin(); it != m_equalizerEffectChains.end(); it++) { + const auto pEffectSlot = it.value().data()->getEffectSlot(0); + VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { + return; + } + auto pManifest = pEffectSlot->getManifest(); + eqEffectManifests.insert(it.key(), pManifest); + } + QHash quickEffectChainPresets; for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { auto pPreset = EffectChainPresetPointer::create(it.value().data()); @@ -255,7 +290,9 @@ void EffectsManager::saveEffectsXml() { m_pChainPresetManager->saveEffectsXml(&doc, EffectsXmlData{ - quickEffectChainPresets, standardEffectChainPresets}); + eqEffectManifests, + quickEffectChainPresets, + standardEffectChainPresets}); m_pVisibleEffectsList->saveEffectsXml(&doc); QDir settingsPath(m_pConfig->getSettingsPath()); diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index 011f5a76c69..556e8ece9c5 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -5,6 +5,7 @@ #include #include +#include "effects/backends/builtin/biquadfullkilleqeffect.h" #include "effects/backends/builtin/filtereffect.h" #include "effects/backends/effectmanifest.h" #include "effects/effectchain.h" @@ -660,6 +661,14 @@ bool EffectChainPresetManager::savePresetXml(EffectChainPresetPointer pPreset) { return success; } +EffectManifestPointer EffectChainPresetManager::getDefaultEqEffect() { + EffectManifestPointer pDefaultEqEffect = m_pBackendManager->getManifest( + BiquadFullKillEQEffect::getId(), EffectBackendType::BuiltIn); + VERIFY_OR_DEBUG_ASSERT(!pDefaultEqEffect.isNull()) { + } + return pDefaultEqEffect; +} + EffectChainPresetPointer EffectChainPresetManager::getDefaultQuickEffectPreset() { EffectManifestPointer pDefaultQuickEffectManifest = m_pBackendManager->getManifest( FilterEffect::getId(), EffectBackendType::BuiltIn); @@ -672,12 +681,16 @@ EffectChainPresetPointer EffectChainPresetManager::getDefaultQuickEffectPreset() EffectsXmlData EffectChainPresetManager::readEffectsXml( const QDomDocument& doc, const QStringList& deckStrings) { + auto pDefaultEqEffect = getDefaultEqEffect(); auto defaultQuickEffectChainPreset = getDefaultQuickEffectPreset(); QList standardEffectChainPresets; QHash quickEffectPresets; + QHash eqEffectManifests; + // configure default EQs and QuickEffects per deck for (const auto& deckString : deckStrings) { quickEffectPresets.insert(deckString, defaultQuickEffectChainPreset); + eqEffectManifests.insert(deckString, pDefaultEqEffect); } // Read state of standard chains @@ -769,6 +782,26 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( emit effectChainPresetListUpdated(); emit quickEffectChainPresetListUpdated(); + // Read ids of effects that were loaded into Equalizer slots on last shutdown + QDomElement eqEffectsElement = + XmlParse::selectElement(root, EffectXml::kEqualizerEffects); + QDomNodeList eqEffectNodeList = + eqEffectsElement.elementsByTagName( + EffectXml::kEffectId); + for (int i = 0; i < eqEffectNodeList.count(); ++i) { + QDomElement effectIdElement = eqEffectNodeList.at(i).toElement(); + if (!effectIdElement.isNull()) { + QString deckGroup = effectIdElement.attribute(QStringLiteral("group")); + QString uid = effectIdElement.text(); + auto pManifest = m_pBackendManager->getManifestFromUniqueId(uid); + // Replace default EQ effect with pManifest for this deck group. + // Also load empty manifests to restore empty EQ effects. + if (pManifest != nullptr || uid == kNoEffectString) { + eqEffectManifests.insert(deckGroup, pManifest); + } + } + } + // Read names of presets that were loaded into QuickEffects on last shutdown QDomElement quickEffectPresetsElement = XmlParse::selectElement(root, EffectXml::kQuickEffectChainPresets); @@ -788,13 +821,40 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( } } - return EffectsXmlData{quickEffectPresets, standardEffectChainPresets}; + return EffectsXmlData{ + eqEffectManifests, quickEffectPresets, standardEffectChainPresets}; } -EffectChainPresetPointer EffectChainPresetManager::readEffectsXmlSingleDeck( +EffectXmlDataSingleDeck EffectChainPresetManager::readEffectsXmlSingleDeck( const QDomDocument& doc, const QString& deckString) { QDomElement root = doc.documentElement(); + // EQ effect + auto pEqEffect = getDefaultEqEffect(); + + // Read id of last loaded EQ effect + QDomElement eqEffectsElement = + XmlParse::selectElement(root, EffectXml::kEqualizerEffects); + QDomNodeList eqEffectNodeList = + eqEffectsElement.elementsByTagName( + EffectXml::kEffectId); + for (int i = 0; i < eqEffectNodeList.count(); ++i) { + QDomElement effectIdElement = eqEffectNodeList.at(i).toElement(); + if (effectIdElement.isNull()) { + continue; + } + if (effectIdElement.attribute(QStringLiteral("group")) == deckString) { + QString uid = effectIdElement.text(); + auto pManifest = m_pBackendManager->getManifestFromUniqueId(uid); + // Replace the default EQ effect. + // Load empty effect if the slot was cleared explicitly ('---' preset) + if (pManifest != nullptr || uid == kNoEffectString) { + pEqEffect = pManifest; + } + } + } + + // Quick Effect auto pQuickEffectChainPreset = getDefaultQuickEffectPreset(); // Read name of last loaded QuickEffect preset @@ -818,7 +878,7 @@ EffectChainPresetPointer EffectChainPresetManager::readEffectsXmlSingleDeck( } } - return pQuickEffectChainPreset; + return EffectXmlDataSingleDeck{pEqEffect, pQuickEffectChainPreset}; } void EffectChainPresetManager::saveEffectsXml(QDomDocument* pDoc, const EffectsXmlData& data) { @@ -858,6 +918,23 @@ void EffectChainPresetManager::saveEffectsXml(QDomDocument* pDoc, const EffectsX } rootElement.appendChild(quickEffectChainPresetListElement); + // Save ids of effects loaded to slot 1 of EQ chains + QDomElement eqEffectsElement = + pDoc->createElement(EffectXml::kEqualizerEffects); + for (auto it = data.eqEffectManifests.begin(); + it != data.eqEffectManifests.end(); + it++) { + // Save element with '---' if no EQ is loaded + QString uid = it.value().isNull() ? kNoEffectString : it.value()->uniqueId(); + QDomElement eqEffectElement = XmlParse::addElement( + *pDoc, + eqEffectsElement, + EffectXml::kEffectId, + uid); + eqEffectElement.setAttribute(QStringLiteral("group"), it.key()); + } + rootElement.appendChild(eqEffectsElement); + // Save which presets are loaded to QuickEffects QDomElement quickEffectPresetsElement = pDoc->createElement(EffectXml::kQuickEffectChainPresets); diff --git a/src/effects/presets/effectchainpresetmanager.h b/src/effects/presets/effectchainpresetmanager.h index a20202137d9..447cd76ac05 100644 --- a/src/effects/presets/effectchainpresetmanager.h +++ b/src/effects/presets/effectchainpresetmanager.h @@ -7,10 +7,16 @@ #include "preferences/usersettings.h" struct EffectsXmlData { + QHash eqEffectManifests; QHash quickEffectChainPresets; QList standardEffectChainPresets; }; +struct EffectXmlDataSingleDeck { + EffectManifestPointer eqEffectManifest; + EffectChainPresetPointer quickEffectChainPreset; +}; + /// EffectChainPresetManager maintains a list of custom EffectChainPresets in the /// "effects/chains" folder in the user settings folder. The state of loaded /// effects are saved as EffectChainPresets in the effects.xml file in the user @@ -66,10 +72,11 @@ class EffectChainPresetManager : public QObject { bool savePreset(EffectChainPresetPointer pPreset); void updatePreset(EffectChainPointer pChainSlot); + EffectManifestPointer getDefaultEqEffect(); EffectChainPresetPointer getDefaultQuickEffectPreset(); EffectsXmlData readEffectsXml(const QDomDocument& doc, const QStringList& deckStrings); - EffectChainPresetPointer readEffectsXmlSingleDeck( + EffectXmlDataSingleDeck readEffectsXmlSingleDeck( const QDomDocument& doc, const QString& deckString); void saveEffectsXml(QDomDocument* pDoc, const EffectsXmlData& data); diff --git a/src/effects/presets/effectxmlelements.h b/src/effects/presets/effectxmlelements.h index 900948405a2..3ee86a7763e 100644 --- a/src/effects/presets/effectxmlelements.h +++ b/src/effects/presets/effectxmlelements.h @@ -15,6 +15,7 @@ const QString kRackGroup(QStringLiteral("Group")); const QString kChainPresetList(QStringLiteral("ChainPresetList")); const QString kQuickEffectList(QStringLiteral("QuickEffectPresetList")); const QString kQuickEffectChainPresets(QStringLiteral("QuickEffectChains")); +const QString kEqualizerEffects(QStringLiteral("EqualizerEffects")); const QString kChainPresetName(QStringLiteral("ChainPresetName")); const QString kVisibleEffects(QStringLiteral("VisibleEffects")); diff --git a/src/preferences/dialog/dlgprefmixer.cpp b/src/preferences/dialog/dlgprefmixer.cpp index dea3fbeb512..16a2487acdd 100644 --- a/src/preferences/dialog/dlgprefmixer.cpp +++ b/src/preferences/dialog/dlgprefmixer.cpp @@ -11,7 +11,7 @@ #include "effects/backends/builtin/filtereffect.h" #include "effects/chains/equalizereffectchain.h" #include "effects/chains/quickeffectchain.h" -#include "effects/effectparameterslotbase.h" +#include "effects/effectknobparameterslot.h" #include "effects/effectslot.h" #include "effects/effectsmanager.h" #include "effects/presets/effectchainpreset.h" @@ -182,38 +182,57 @@ DlgPrefMixer::DlgPrefMixer( // Create EQ & QuickEffect selectors and deck label for each added deck void DlgPrefMixer::slotNumDecksChanged(double numDecks) { while (m_deckEqEffectSelectors.size() < static_cast(numDecks)) { + // 1-based for display int deckNo = m_deckEqEffectSelectors.size() + 1; + // 0-based for engine QString deckGroup = PlayerManager::groupForDeck(deckNo - 1); - - auto pLabel = make_parented(QObject::tr("Deck %1").arg(deckNo), this); + QLabel* pLabel = new QLabel(QObject::tr("Deck %1").arg(deckNo), this); // Create the EQ selector ////////////////////////////////////////////// auto pEqComboBox = make_parented(this); setScrollSafeGuard(pEqComboBox); m_deckEqEffectSelectors.append(pEqComboBox); - // Load EQ from from mixxx.cfg, add and select it in the combobox(es). - // If the ConfigKey exists the EQ is loaded. If the value is empty no - // EQ was selected ('---'). - // If the key doesn't exist the default EQ is loaded. - QString configuredEffect = m_pConfig->getValue( - ConfigKey(kMixerProfile, kEffectForGroupPrefix + deckGroup), - kDefaultEqId); - const EffectManifestPointer pEQManifest = - m_pBackendManager->getManifestFromUniqueId(configuredEffect); - // We just add the one required item to the box so applyDeckEQs() can load it. - if (pEQManifest) { - pEqComboBox->addItem(pEQManifest->name(), QVariant(pEQManifest->uniqueId())); - } else { - // the previous EQ was 'none' or its uid can't be found - pEqComboBox->addItem(kNoEffectString); + // Migrate EQ from mixxx.cfg, add it to the combobox, remove keys + const ConfigKey groupKey = + ConfigKey(kMixerProfile, kEffectForGroupPrefix + deckGroup); + const QString configuredEffect = m_pConfig->getValueString(groupKey); + // If the EQ key doesn't exist (isNull()), we keeo the default EQ which + // has already been loaded by EffectsManager. Later on + // slotPopulateDeckEqSelectors() will read the effect, so nothing to do. + // Else, we use the uid from the config to load an EQ (or none). + bool loadEQ = false; + EffectManifestPointer pEqManifest; + if (!configuredEffect.isNull()) { + loadEQ = true; + pEqManifest = m_pBackendManager->getManifestFromUniqueId(configuredEffect); + + // remove key so we migrate only once + m_pConfig->remove(groupKey); } - pEqComboBox->setCurrentIndex(0); + auto pEqChain = m_pEffectsManager->getEqualizerEffectChain(deckGroup); + VERIFY_OR_DEBUG_ASSERT(pEqChain) { + return; + } + auto pEqEffectSlot = pEqChain->getEffectSlot(0); + VERIFY_OR_DEBUG_ASSERT(pEqEffectSlot) { + return; + } + if (loadEQ) { + pEqEffectSlot->loadEffectWithDefaults(pEqManifest); + } connect(pEqComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &DlgPrefMixer::slotEQEffectSelectionChanged); + // Update the combobox in case the effect was changed from anywhere else + connect(pEqEffectSlot.data(), + &EffectSlot::effectChanged, + this, + [this]() { + slotPopulateDeckEqSelectors(); + }); // Create the QuickEffect selector ///////////////////////////////////// auto pQuickEffectComboBox = make_parented(this); @@ -223,7 +242,7 @@ void DlgPrefMixer::slotNumDecksChanged(double numDecks) { QOverload::of(&QComboBox::currentIndexChanged), this, &DlgPrefMixer::slotQuickEffectSelectionChanged); - // Change the QuickEffect when it was changed in WEffectChainPresetSelector + // Update the combobox when the effect was changed in WEffectChainPresetSelector // or with controllers EffectChainPointer pChain = m_pEffectsManager->getQuickEffectChain(deckGroup); DEBUG_ASSERT(pChain); @@ -251,7 +270,6 @@ void DlgPrefMixer::slotNumDecksChanged(double numDecks) { 1, 1); } - applyDeckEQs(); // This also selects all currently loaded EQs and QuickEffects slotPopulateDeckEqSelectors(); @@ -526,8 +544,8 @@ void DlgPrefMixer::applyDeckEQs() { needLoad = effectIndex != m_eqIndiciesOnUpdate[deck]; } - QString deckGroup = PlayerManager::groupForDeck(deck); - auto pChainSlot = m_pEffectsManager->getEqualizerEffectChain(deckGroup); + auto pChainSlot = m_pEffectsManager->getEqualizerEffectChain( + PlayerManager::groupForDeck(deck)); DEBUG_ASSERT(pChainSlot); auto pEffectSlot = pChainSlot->getEffectSlot(0); DEBUG_ASSERT(pEffectSlot); @@ -535,14 +553,15 @@ void DlgPrefMixer::applyDeckEQs() { const EffectManifestPointer pManifest = m_pBackendManager->getManifestFromUniqueId( - pBox->itemData(effectIndex).toString()); + pBox->currentData().toString()); + if (pManifest != nullptr && pManifest->isMixingEQ() && !m_eqBypass) { + pChainSlot->setFilterWaveform(true); + } else { + pChainSlot->setFilterWaveform(false); + } + if (needLoad) { pEffectSlot->loadEffectWithDefaults(pManifest); - if (pManifest && pManifest->isMixingEQ() && !m_eqBypass) { - pChainSlot->setFilterWaveform(true); - } else { - pChainSlot->setFilterWaveform(false); - } } if (startingUp) { @@ -550,14 +569,6 @@ void DlgPrefMixer::applyDeckEQs() { } else { m_eqIndiciesOnUpdate[deck] = effectIndex; } - - QString effectId; - if (pManifest) { - effectId = pManifest->uniqueId(); - } - // TODO store this in effects.xml - m_pConfig->set(ConfigKey(kMixerProfile, kEffectForGroupPrefix + deckGroup), - effectId); } m_ignoreEqQuickEffectBoxSignals = false; } From cfb27040514d7078d4bc85c36a6dbfb7a9d6c850 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 14 Jul 2023 00:18:40 +0200 Subject: [PATCH 02/12] Effects: store main EQ effect in effects.xml --- src/effects/effectsmanager.cpp | 12 +- .../presets/effectchainpresetmanager.cpp | 18 ++- .../presets/effectchainpresetmanager.h | 1 + src/effects/presets/effectxmlelements.h | 1 + src/preferences/dialog/dlgprefmixer.cpp | 142 +++++++++++------- src/preferences/dialog/dlgprefmixer.h | 2 +- 6 files changed, 119 insertions(+), 57 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index e8e37aff895..05237545d7d 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -203,6 +203,10 @@ void EffectsManager::readEffectsXml() { m_standardEffectChains.value(i)->loadChainPreset(data.standardEffectChainPresets.at(i)); } + if (!data.outputChainPreset.isNull()) { + m_outputEffectChain->loadChainPreset(data.outputChainPreset); + } + for (auto it = data.eqEffectManifests.begin(); it != data.eqEffectManifests.end(); it++) { @@ -288,11 +292,17 @@ void EffectsManager::saveEffectsXml() { standardEffectChainPresets.append(pPreset); } + auto outputChainPreset = m_outputEffectChain.data() != nullptr + ? EffectChainPresetPointer::create(m_outputEffectChain.data()) + // required for tests + : EffectChainPresetPointer(new EffectChainPreset()); + m_pChainPresetManager->saveEffectsXml(&doc, EffectsXmlData{ eqEffectManifests, quickEffectChainPresets, - standardEffectChainPresets}); + standardEffectChainPresets, + outputChainPreset}); m_pVisibleEffectsList->saveEffectsXml(&doc); QDir settingsPath(m_pConfig->getSettingsPath()); diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index 556e8ece9c5..18f5eb1d2bf 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -711,6 +711,16 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( } } + QDomElement mainEqElement = XmlParse::selectElement(root, EffectXml::kMainEq); + QDomNodeList mainEqs = mainEqElement.elementsByTagName(EffectXml::kChain); + QDomNode mainEqChainNode = mainEqs.at(0); + EffectChainPresetPointer mainEqPreset; + if (mainEqChainNode.isElement()) { + QDomElement mainEqChainElement = mainEqChainNode.toElement(); + mainEqPreset = EffectChainPresetPointer( + new EffectChainPreset(mainEqChainElement)); + } + importUserPresets(); // Reload order of custom chain presets @@ -822,7 +832,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( } return EffectsXmlData{ - eqEffectManifests, quickEffectPresets, standardEffectChainPresets}; + eqEffectManifests, quickEffectPresets, standardEffectChainPresets, mainEqPreset}; } EffectXmlDataSingleDeck EffectChainPresetManager::readEffectsXmlSingleDeck( @@ -892,6 +902,12 @@ void EffectChainPresetManager::saveEffectsXml(QDomDocument* pDoc, const EffectsX chainsElement.appendChild(pPreset->toXml(pDoc)); } + // Save main EQ effect + QDomElement mainEqElement = pDoc->createElement(EffectXml::kMainEq); + rootElement.appendChild(mainEqElement); + const auto& mainEqPreset = data.outputChainPreset; + mainEqElement.appendChild(mainEqPreset->toXml(pDoc)); + // Save order of custom chain presets QDomElement chainPresetListElement = pDoc->createElement(EffectXml::kChainPresetList); diff --git a/src/effects/presets/effectchainpresetmanager.h b/src/effects/presets/effectchainpresetmanager.h index 447cd76ac05..b1657950d07 100644 --- a/src/effects/presets/effectchainpresetmanager.h +++ b/src/effects/presets/effectchainpresetmanager.h @@ -10,6 +10,7 @@ struct EffectsXmlData { QHash eqEffectManifests; QHash quickEffectChainPresets; QList standardEffectChainPresets; + EffectChainPresetPointer outputChainPreset; }; struct EffectXmlDataSingleDeck { diff --git a/src/effects/presets/effectxmlelements.h b/src/effects/presets/effectxmlelements.h index 3ee86a7763e..63f5607d128 100644 --- a/src/effects/presets/effectxmlelements.h +++ b/src/effects/presets/effectxmlelements.h @@ -10,6 +10,7 @@ const QString kRoot(QStringLiteral("MixxxEffects")); const QString kSchemaVersion(QStringLiteral("SchemaVersion")); const QString kRack(QStringLiteral("Rack")); +const QString kMainEq(QStringLiteral("MainEQ")); const QString kRackGroup(QStringLiteral("Group")); const QString kChainPresetList(QStringLiteral("ChainPresetList")); diff --git a/src/preferences/dialog/dlgprefmixer.cpp b/src/preferences/dialog/dlgprefmixer.cpp index 16a2487acdd..8630aa414de 100644 --- a/src/preferences/dialog/dlgprefmixer.cpp +++ b/src/preferences/dialog/dlgprefmixer.cpp @@ -97,7 +97,8 @@ DlgPrefMixer::DlgPrefMixer( m_eqAutoReset(false), m_gainAutoReset(false), m_eqBypass(false), - m_initializing(true) { + m_initializing(true), + m_updatingMainEQ(false) { setupUi(this); // Update the crossfader curve graph and other settings when the @@ -717,8 +718,6 @@ void DlgPrefMixer::slotApply() { applyQuickEffects(); storeEqShelves(); - - storeMainEQ(); } void DlgPrefMixer::storeEqShelves() { @@ -956,15 +955,8 @@ void DlgPrefMixer::setUpMainEQ() { DEBUG_ASSERT(pEffectSlot); m_pEffectMainEQ = pEffectSlot; - connect(pbResetMainEq, &QPushButton::clicked, this, &DlgPrefMixer::slotMainEQToDefault); - - connect(comboBoxMainEq, - QOverload::of(&QComboBox::currentIndexChanged), - this, - &DlgPrefMixer::slotMainEqEffectChanged); - + // Populate the effect combobox and connect widgets const QList availableMainEQEffects = getMainEqManifests(); - // Add empty '---' item at the top comboBoxMainEq->addItem(kNoEffectString); for (const auto& pManifest : availableMainEQEffects) { @@ -978,37 +970,105 @@ void DlgPrefMixer::setUpMainEQ() { Qt::ToolTipRole); } comboBoxMainEq->setCurrentIndex(0); -} + // slotMainEqEffectChanged() applies the effect immediately, so connect _after_ + // setting the index to not override the current EffectsManager state. + connect(pbResetMainEq, &QPushButton::clicked, this, &DlgPrefMixer::slotMainEQToDefault); + connect(comboBoxMainEq, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &DlgPrefMixer::slotMainEqEffectChanged); -void DlgPrefMixer::updateMainEQ() { + // Since 2.4 the main EQ is stored in effects.xml, so try to load settings + // from mixxx.cfg and apply immediately. + // If no settings were read, the state from EffectsManager is adopted when + // slotUpdate() is called later during initialization. const QString configuredEffectId = - m_pConfig->getValue(ConfigKey(kMixerProfile, kEffectGroupForMaster), - kDefaultMainEqId); + m_pConfig->getValueString(ConfigKey(kMixerProfile, kEffectGroupForMaster)); + if (configuredEffectId.isNull() || configuredEffectId.isEmpty()) { + // Effect key doesn't exist or effect uid is empty. Nothing to do, keep + // the state loaded from effects.xml + // Remove all main EQ key residues + const QList mixerKeys = m_pConfig->getKeysWithGroup(kMixerProfile); + for (const auto& key : mixerKeys) { + if (key.item.contains(kEffectGroupForMaster)) { + m_pConfig->remove(key); + } + } + return; + } + const EffectManifestPointer configuredEffectManifest = m_pBackendManager->getManifestFromUniqueId(configuredEffectId); - int mainEqIndex = 0; // selects '---' by default - if (configuredEffectManifest) { - mainEqIndex = comboBoxMainEq->findData(configuredEffectManifest->uniqueId()); + if (!configuredEffectManifest) { + return; + } + + int configuredIndex = comboBoxMainEq->findData(configuredEffectManifest->uniqueId()); + if (configuredIndex == -1) { + return; } // Set index and create required sliders and labels - comboBoxMainEq->setCurrentIndex(mainEqIndex); + comboBoxMainEq->setCurrentIndex(configuredIndex); // Load parameters from preferences and set sliders for (QSlider* pSlider : std::as_const(m_mainEQSliders)) { int paramIndex = pSlider->property("index").toInt(); - QString strValue = m_pConfig->getValueString(ConfigKey(kMixerProfile, - kMainEQParameterKey + QString::number(paramIndex + 1))); - + QString strValue = m_pConfig->getValueString( + ConfigKey(kMixerProfile, + kMainEQParameterKey + QString::number(paramIndex + 1))); bool ok; double paramValue = strValue.toDouble(&ok); if (!ok) { continue; } pSlider->setValue(static_cast(paramValue * 100)); - // Thelabel is updated in slotMainEQParameterSliderChanged() + // The label is updated in slotMainEQParameterSliderChanged() + } + // Remove all main EQ keys + const QList mixerKeys = m_pConfig->getKeysWithGroup(kMixerProfile); + for (const auto& key : mixerKeys) { + if (key.item.contains(kEffectGroupForMaster)) { + m_pConfig->remove(key); + } } } +void DlgPrefMixer::updateMainEQ() { + EffectSlotPointer pEffectSlot(m_pEffectMainEQ); + VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { + return; + } + + // Read loaded EQ from EffectsManager + const EffectManifestPointer pLoadedManifest = pEffectSlot->getManifest(); + int loadedIndex = pLoadedManifest ? comboBoxMainEq->findData(pLoadedManifest->uniqueId()) : 0; + if (loadedIndex != comboBoxMainEq->currentIndex()) { + m_updatingMainEQ = true; + } + // Set index and create required sliders and labels + comboBoxMainEq->setCurrentIndex(loadedIndex); + + for (QSlider* pSlider : std::as_const(m_mainEQSliders)) { + int paramIndex = pSlider->property("index").toInt(); + auto pParameterSlot = pEffectSlot->getEffectParameterSlot( + EffectManifestParameter::ParameterType::Knob, paramIndex); + VERIFY_OR_DEBUG_ASSERT(pParameterSlot && pParameterSlot->isLoaded()) { + return; + } + auto pKnobSlot = qobject_cast(pParameterSlot); + VERIFY_OR_DEBUG_ASSERT(pKnobSlot) { + return; + } + double pValue = pKnobSlot->getValueParameter(); + int sValue = static_cast( + pValue * (pSlider->maximum() - pSlider->minimum())) + + pSlider->minimum(); + pSlider->setValue(sValue); + // Label is updated in slotMainEQParameterSliderChanged() + } + m_updatingMainEQ = false; +} + void DlgPrefMixer::slotMainEqEffectChanged(int effectIndex) { EffectSlotPointer pEffectSlot(m_pEffectMainEQ); VERIFY_OR_DEBUG_ASSERT(!pEffectSlot.isNull()) { @@ -1027,7 +1087,9 @@ void DlgPrefMixer::slotMainEqEffectChanged(int effectIndex) { m_pBackendManager->getManifestFromUniqueId( comboBoxMainEq->itemData(effectIndex).toString()); - pEffectSlot->loadEffectWithDefaults(pManifest); + if (!m_updatingMainEQ) { + pEffectSlot->loadEffectWithDefaults(pManifest); + } if (pManifest) { pbResetMainEq->show(); @@ -1053,6 +1115,8 @@ void DlgPrefMixer::slotMainEqEffectChanged(int effectIndex) { auto pSlider = make_parented(this); setScrollSafeGuard(pSlider); + // Store the index as a property because we need it in + // slotMainEQParameterSliderChanged() and slotUpdate() pSlider->setProperty("index", QVariant(i)); pSlider->setMinimumHeight(90); pSlider->setMinimum(static_cast(param->getMinimum() * 100)); @@ -1072,8 +1136,6 @@ void DlgPrefMixer::slotMainEqEffectChanged(int effectIndex) { pSlider->setSingleStep(step); pSlider->setPageStep(step * 10); pSlider->setValue(static_cast(param->getDefault() * 100)); - // Store the index as a property because we need it in - // slotMainEQParameterSliderChanged() and storeMainEQ() slidersGridLayout->addWidget(pSlider, 1, i + 1, Qt::AlignCenter); m_mainEQSliders.append(pSlider); // catch drag event @@ -1152,34 +1214,6 @@ void DlgPrefMixer::slotMainEQToDefault() { } } -void DlgPrefMixer::storeMainEQ() { - // store effect - const EffectManifestPointer pManifest = - m_pBackendManager->getManifestFromUniqueId( - comboBoxMainEq->currentData().toString()); - - m_pConfig->set(ConfigKey(kMixerProfile, kEffectGroupForMaster), - ConfigValue(pManifest ? pManifest->uniqueId() : "")); - - // clear all previous parameter values so we have no residues - const QList mixerKeys = m_pConfig->getKeysWithGroup(kMixerProfile); - for (const auto& key : mixerKeys) { - if (key.item.contains(kMainEQParameterKey)) { - m_pConfig->remove(key); - } - } - - // store current parameters - for (QSlider* pSlider : std::as_const(m_mainEQSliders)) { - int paramIndex = pSlider->property("index").toInt(); - double dispValue = static_cast(pSlider->value()) / 100; - // TODO store this in effects.xml - m_pConfig->set(ConfigKey(kMixerProfile, - kMainEQParameterKey + QString::number(paramIndex + 1)), - ConfigValue(QString::number(dispValue))); - } -} - const QList DlgPrefMixer::getDeckEqManifests() const { QList allManifests = m_pBackendManager->getManifests(); diff --git a/src/preferences/dialog/dlgprefmixer.h b/src/preferences/dialog/dlgprefmixer.h index 908214d3584..1e314cca852 100644 --- a/src/preferences/dialog/dlgprefmixer.h +++ b/src/preferences/dialog/dlgprefmixer.h @@ -68,7 +68,6 @@ class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg { void setUpMainEQ(); void updateMainEQ(); - void storeMainEQ(); typedef bool (*EffectManifestFilterFnc)(EffectManifest* pManifest); const QList getDeckEqManifests() const; @@ -115,6 +114,7 @@ class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg { bool m_eqBypass; bool m_initializing; + bool m_updatingMainEQ; QList m_eqIndiciesOnUpdate; QList m_quickEffectIndiciesOnUpdate; From 987ea3321c8b051ebccf7ba0253338afa2dd0e3f Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 10 Nov 2023 15:13:47 +0100 Subject: [PATCH 03/12] Effects: reset to default EQ & Quick effect in EffectsManager, not DlgPrefMixer --- src/effects/effectsmanager.cpp | 21 +++++++++++++++++++++ src/effects/effectsmanager.h | 2 ++ src/preferences/dialog/dlgprefmixer.cpp | 16 ++-------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 05237545d7d..30a4f0ae9e8 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -172,6 +172,27 @@ void EffectsManager::addQuickEffectChain(const ChannelHandleAndGroup& deckHandle m_effectChainSlotsByGroup.insert(pChainSlot->group(), pChainSlot); } +void EffectsManager::loadDefaultEqsAndQuickEffects() { + auto pDefaultEqEffect = m_pChainPresetManager->getDefaultEqEffect(); + for (auto it = m_equalizerEffectChains.begin(); + it != m_equalizerEffectChains.end(); + it++) { + auto pEqChainSlot = it.value(); + const auto pEqEffectSlot = pEqChainSlot->getEffectSlot(0); + VERIFY_OR_DEBUG_ASSERT(pEqEffectSlot) { + return; + } + pEqEffectSlot->loadEffectWithDefaults(pDefaultEqEffect); + } + + auto pDefaultQuickEffectPreset = + m_pChainPresetManager->getDefaultQuickEffectPreset(); + for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { + auto pChainSlot = it.value(); + pChainSlot->loadChainPreset(pDefaultQuickEffectPreset); + } +} + EffectChainPointer EffectsManager::getEffectChain( const QString& group) const { return m_effectChainSlotsByGroup.value(group); diff --git a/src/effects/effectsmanager.h b/src/effects/effectsmanager.h index de5109ab331..f2b579e486a 100644 --- a/src/effects/effectsmanager.h +++ b/src/effects/effectsmanager.h @@ -28,6 +28,8 @@ class EffectsManager { void setup(); void addDeck(const ChannelHandleAndGroup& deckHandleGroup); + void loadDefaultEqsAndQuickEffects(); + EffectChainPointer getEffectChain(const QString& group) const; EqualizerEffectChainPointer getEqualizerEffectChain( const QString& deckGroupName) const { diff --git a/src/preferences/dialog/dlgprefmixer.cpp b/src/preferences/dialog/dlgprefmixer.cpp index 8630aa414de..37b29606857 100644 --- a/src/preferences/dialog/dlgprefmixer.cpp +++ b/src/preferences/dialog/dlgprefmixer.cpp @@ -7,8 +7,6 @@ #include "control/controlobject.h" #include "control/controlproxy.h" #include "defs_urls.h" -#include "effects/backends/builtin/biquadfullkilleqeffect.h" -#include "effects/backends/builtin/filtereffect.h" #include "effects/chains/equalizereffectchain.h" #include "effects/chains/quickeffectchain.h" #include "effects/effectknobparameterslot.h" @@ -30,9 +28,6 @@ const ConfigKey kEqsOnlyKey = ConfigKey(kMixerProfile, QStringLiteral("EQsOnly") const ConfigKey kSingleEqKey = ConfigKey(kMixerProfile, QStringLiteral("SingleEQEffect")); const ConfigKey kEqAutoResetKey = ConfigKey(kMixerProfile, QStringLiteral("EqAutoReset")); const ConfigKey kGainAutoResetKey = ConfigKey(kMixerProfile, QStringLiteral("GainAutoReset")); -const QString kDefaultEqId = BiquadFullKillEQEffect::getId() + " " + - EffectsBackend::backendTypeToString(EffectBackendType::BuiltIn); -const QString kDefaultQuickEffectChainName = FilterEffect::getManifest()->name(); const QString kDefaultMainEqId = QString(); const ConfigKey kHighEqFreqKey = ConfigKey(kMixerProfile, kHighEqFrequency); @@ -464,15 +459,8 @@ void DlgPrefMixer::slotResetToDefaults() { radioButtonAdditive->setChecked(true); checkBoxReverse->setChecked(false); - // EQ ////////////////////////////////// - for (const auto& pBox : std::as_const(m_deckEqEffectSelectors)) { - pBox->setCurrentIndex( - pBox->findData(kDefaultEqId)); - } - for (const auto& pBox : std::as_const(m_deckQuickEffectSelectors)) { - pBox->setCurrentIndex( - pBox->findText(kDefaultQuickEffectChainName)); - } + // EQ & QuickEffects ////////////////////////////////// + m_pEffectsManager->loadDefaultEqsAndQuickEffects(); CheckBoxBypass->setChecked(false); CheckBoxEqOnly->setChecked(true); CheckBoxSingleEqEffect->setChecked(true); From 3fffc291780214ae98db5c7d6d981e5eb6c6088f Mon Sep 17 00:00:00 2001 From: ronso0 Date: Thu, 9 Nov 2023 22:37:41 +0100 Subject: [PATCH 04/12] Effects: center Super knob when loading empty (QuickEffect) chain preset --- src/effects/presets/effectchainpresetmanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index 18f5eb1d2bf..2676a7e1f77 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -42,6 +42,8 @@ EffectChainPresetPointer loadPresetFromFile(const QString& filePath) { EffectChainPresetPointer createEmptyChainPreset() { EffectManifestPointer pEmptyManifest(new EffectManifest()); pEmptyManifest->setName(kNoEffectString); + // Center the Super knob, eliminates the colored (bipolar) knob ring + pEmptyManifest->setMetaknobDefault(0.5); // Required for the QuickEffect selector in DlgPrefEQ pEmptyManifest->setShortName(kNoEffectString); auto pEmptyChainPreset = From 0e85fb518b435011ccaa49c56f73556807d7185d Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 17 Nov 2023 13:01:47 +0100 Subject: [PATCH 05/12] DlgPrefMixer: revert deck label change --- src/preferences/dialog/dlgprefmixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preferences/dialog/dlgprefmixer.cpp b/src/preferences/dialog/dlgprefmixer.cpp index 37b29606857..5f0b5385958 100644 --- a/src/preferences/dialog/dlgprefmixer.cpp +++ b/src/preferences/dialog/dlgprefmixer.cpp @@ -182,7 +182,7 @@ void DlgPrefMixer::slotNumDecksChanged(double numDecks) { int deckNo = m_deckEqEffectSelectors.size() + 1; // 0-based for engine QString deckGroup = PlayerManager::groupForDeck(deckNo - 1); - QLabel* pLabel = new QLabel(QObject::tr("Deck %1").arg(deckNo), this); + auto pLabel = make_parented(QObject::tr("Deck %1").arg(deckNo), this); // Create the EQ selector ////////////////////////////////////////////// auto pEqComboBox = make_parented(this); From c93e5d87c89431e2230f7a980ac2854ba1822ba4 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 17 Nov 2023 00:48:22 +0100 Subject: [PATCH 06/12] Effects(Preset)Manager: use QHashIterator --- src/effects/effectsmanager.cpp | 53 ++++++++++--------- .../presets/effectchainpresetmanager.cpp | 23 ++++---- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 30a4f0ae9e8..4d386b7d30b 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -174,10 +174,9 @@ void EffectsManager::addQuickEffectChain(const ChannelHandleAndGroup& deckHandle void EffectsManager::loadDefaultEqsAndQuickEffects() { auto pDefaultEqEffect = m_pChainPresetManager->getDefaultEqEffect(); - for (auto it = m_equalizerEffectChains.begin(); - it != m_equalizerEffectChains.end(); - it++) { - auto pEqChainSlot = it.value(); + QHashIterator eqIt(m_equalizerEffectChains); + while (eqIt.hasNext()) { + auto pEqChainSlot = eqIt.next().value(); const auto pEqEffectSlot = pEqChainSlot->getEffectSlot(0); VERIFY_OR_DEBUG_ASSERT(pEqEffectSlot) { return; @@ -187,8 +186,9 @@ void EffectsManager::loadDefaultEqsAndQuickEffects() { auto pDefaultQuickEffectPreset = m_pChainPresetManager->getDefaultQuickEffectPreset(); - for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { - auto pChainSlot = it.value(); + QHashIterator qeIt(m_quickEffectChains); + while (qeIt.hasNext()) { + auto pChainSlot = qeIt.next().value(); pChainSlot->loadChainPreset(pDefaultQuickEffectPreset); } } @@ -215,8 +215,9 @@ void EffectsManager::readEffectsXml() { // Note: QuickEffect and EQ chains are created only for existing main decks, // thus only for those the configured presets are requested QStringList deckStrings; - for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { - deckStrings << it.key(); + QHashIterator qeIt(m_quickEffectChains); + while (qeIt.hasNext()) { + deckStrings << qeIt.next().key(); } EffectsXmlData data = m_pChainPresetManager->readEffectsXml(doc, deckStrings); @@ -228,25 +229,25 @@ void EffectsManager::readEffectsXml() { m_outputEffectChain->loadChainPreset(data.outputChainPreset); } - for (auto it = data.eqEffectManifests.begin(); - it != data.eqEffectManifests.end(); - it++) { - auto pChainSlot = m_equalizerEffectChains.value(it.key()); + QHashIterator eqIt(data.eqEffectManifests); + while (eqIt.hasNext()) { + eqIt.next(); + auto pChainSlot = m_equalizerEffectChains.value(eqIt.key()); if (pChainSlot) { const auto pEffectSlot = pChainSlot->getEffectSlot(0); VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { return; } - pEffectSlot->loadEffectWithDefaults(it.value()); + pEffectSlot->loadEffectWithDefaults(eqIt.value()); } } - for (auto it = data.quickEffectChainPresets.begin(); - it != data.quickEffectChainPresets.end(); - it++) { - auto pChainSlot = m_quickEffectChains.value(it.key()); + QHashIterator qeDataIt(data.quickEffectChainPresets); + while (qeDataIt.hasNext()) { + qeDataIt.next(); + auto pChainSlot = m_quickEffectChains.value(qeDataIt.key()); if (pChainSlot) { - pChainSlot->loadChainPreset(it.value()); + pChainSlot->loadChainPreset(qeDataIt.value()); } } @@ -292,19 +293,23 @@ void EffectsManager::saveEffectsXml() { doc.appendChild(rootElement); QHash eqEffectManifests; - for (auto it = m_equalizerEffectChains.begin(); it != m_equalizerEffectChains.end(); it++) { - const auto pEffectSlot = it.value().data()->getEffectSlot(0); + QHashIterator eqIt(m_equalizerEffectChains); + while (eqIt.hasNext()) { + eqIt.next(); + const auto pEffectSlot = eqIt.value().data()->getEffectSlot(0); VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { return; } auto pManifest = pEffectSlot->getManifest(); - eqEffectManifests.insert(it.key(), pManifest); + eqEffectManifests.insert(eqIt.key(), pManifest); } QHash quickEffectChainPresets; - for (auto it = m_quickEffectChains.begin(); it != m_quickEffectChains.end(); it++) { - auto pPreset = EffectChainPresetPointer::create(it.value().data()); - quickEffectChainPresets.insert(it.key(), pPreset); + QHashIterator qeIt(m_quickEffectChains); + while (qeIt.hasNext()) { + qeIt.next(); + auto pPreset = EffectChainPresetPointer::create(qeIt.value().data()); + quickEffectChainPresets.insert(qeIt.key(), pPreset); } QList standardEffectChainPresets; diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index 2676a7e1f77..dbbe024316a 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -666,8 +666,7 @@ bool EffectChainPresetManager::savePresetXml(EffectChainPresetPointer pPreset) { EffectManifestPointer EffectChainPresetManager::getDefaultEqEffect() { EffectManifestPointer pDefaultEqEffect = m_pBackendManager->getManifest( BiquadFullKillEQEffect::getId(), EffectBackendType::BuiltIn); - VERIFY_OR_DEBUG_ASSERT(!pDefaultEqEffect.isNull()) { - } + DEBUG_ASSERT(!pDefaultEqEffect.isNull()); return pDefaultEqEffect; } @@ -939,32 +938,32 @@ void EffectChainPresetManager::saveEffectsXml(QDomDocument* pDoc, const EffectsX // Save ids of effects loaded to slot 1 of EQ chains QDomElement eqEffectsElement = pDoc->createElement(EffectXml::kEqualizerEffects); - for (auto it = data.eqEffectManifests.begin(); - it != data.eqEffectManifests.end(); - it++) { + QHashIterator eqIt(data.eqEffectManifests); + while (eqIt.hasNext()) { + eqIt.next(); // Save element with '---' if no EQ is loaded - QString uid = it.value().isNull() ? kNoEffectString : it.value()->uniqueId(); + QString uid = eqIt.value().isNull() ? kNoEffectString : eqIt.value()->uniqueId(); QDomElement eqEffectElement = XmlParse::addElement( *pDoc, eqEffectsElement, EffectXml::kEffectId, uid); - eqEffectElement.setAttribute(QStringLiteral("group"), it.key()); + eqEffectElement.setAttribute(QStringLiteral("group"), eqIt.key()); } rootElement.appendChild(eqEffectsElement); // Save which presets are loaded to QuickEffects QDomElement quickEffectPresetsElement = pDoc->createElement(EffectXml::kQuickEffectChainPresets); - for (auto it = data.quickEffectChainPresets.begin(); - it != data.quickEffectChainPresets.end(); - it++) { + QHashIterator qeIt(data.quickEffectChainPresets); + while (qeIt.hasNext()) { + qeIt.next(); QDomElement quickEffectElement = XmlParse::addElement( *pDoc, quickEffectPresetsElement, EffectXml::kChainPresetName, - it.value()->name()); - quickEffectElement.setAttribute(QStringLiteral("group"), it.key()); + qeIt.value()->name()); + quickEffectElement.setAttribute(QStringLiteral("group"), qeIt.key()); } rootElement.appendChild(quickEffectPresetsElement); } From c5c8895241e4dcc87421267c9910ab98df0b7e50 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 17 Nov 2023 13:03:06 +0100 Subject: [PATCH 07/12] Effects(Preset)Mananger: improve pointer init/creation, add comments Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com> --- src/effects/effectsmanager.cpp | 10 ++++++---- src/effects/presets/effectchainpresetmanager.cpp | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 4d386b7d30b..432cc461b82 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -318,10 +318,12 @@ void EffectsManager::saveEffectsXml() { standardEffectChainPresets.append(pPreset); } - auto outputChainPreset = m_outputEffectChain.data() != nullptr - ? EffectChainPresetPointer::create(m_outputEffectChain.data()) - // required for tests - : EffectChainPresetPointer(new EffectChainPreset()); + const auto outputChainPreset = m_outputEffectChain.isNull() + // required for tests when no output effect chain exists + ? EffectChainPresetPointer::create() + // no ownership concerns apply because we're just calling + // EffectChainPreset::EffectChainPreset(const EffectChain* chain) + : EffectChainPresetPointer::create(m_outputEffectChain.data()); m_pChainPresetManager->saveEffectsXml(&doc, EffectsXmlData{ diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index dbbe024316a..0a09528d335 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -715,7 +715,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( QDomElement mainEqElement = XmlParse::selectElement(root, EffectXml::kMainEq); QDomNodeList mainEqs = mainEqElement.elementsByTagName(EffectXml::kChain); QDomNode mainEqChainNode = mainEqs.at(0); - EffectChainPresetPointer mainEqPreset; + EffectChainPresetPointer mainEqPreset = nullptr; if (mainEqChainNode.isElement()) { QDomElement mainEqChainElement = mainEqChainNode.toElement(); mainEqPreset = EffectChainPresetPointer( From 4c330a31c774f05aa6cebfdfd0f0de7952971513 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 17 Nov 2023 14:39:56 +0100 Subject: [PATCH 08/12] Effects(Preset)Manager: use 'create' for various Effect...Pointer --- src/effects/presets/effectchainpreset.cpp | 6 +++--- .../presets/effectchainpresetmanager.cpp | 18 +++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/effects/presets/effectchainpreset.cpp b/src/effects/presets/effectchainpreset.cpp index 35b6d5ab5e1..f89b5c44089 100644 --- a/src/effects/presets/effectchainpreset.cpp +++ b/src/effects/presets/effectchainpreset.cpp @@ -40,7 +40,7 @@ EffectChainPreset::EffectChainPreset(const QDomElement& chainElement) { QDomNode effectNode = effectList.at(i); if (effectNode.isElement()) { QDomElement effectElement = effectNode.toElement(); - EffectPresetPointer pPreset(new EffectPreset(effectElement)); + auto pPreset = EffectPresetPointer::create(effectElement); m_effectPresets.append(pPreset); } } @@ -55,7 +55,7 @@ EffectChainPreset::EffectChainPreset(const EffectChain* chain) m_dSuper(chain->getSuperParameter()), m_readOnly(false) { for (const auto& pEffectSlot : chain->getEffectSlots()) { - m_effectPresets.append(EffectPresetPointer(new EffectPreset(pEffectSlot))); + m_effectPresets.append(EffectPresetPointer::create(pEffectSlot)); } } @@ -64,7 +64,7 @@ EffectChainPreset::EffectChainPreset(EffectManifestPointer pManifest) m_mixMode(EffectChainMixMode::DrySlashWet), m_dSuper(pManifest->metaknobDefault()), m_readOnly(false) { - m_effectPresets.append(EffectPresetPointer(new EffectPreset(pManifest))); + m_effectPresets.append(EffectPresetPointer::create(pManifest)); } EffectChainPreset::EffectChainPreset(EffectPresetPointer pEffectPreset) diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index 0a09528d335..c122ef79a1e 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -33,8 +33,7 @@ EffectChainPresetPointer loadPresetFromFile(const QString& filePath) { qWarning() << "Could not read XML from chain preset file" << filePath; return nullptr; } - EffectChainPresetPointer pEffectChainPreset( - new EffectChainPreset(doc.documentElement())); + auto pEffectChainPreset = EffectChainPresetPointer::create(doc.documentElement()); file.close(); return pEffectChainPreset; } @@ -46,8 +45,7 @@ EffectChainPresetPointer createEmptyChainPreset() { pEmptyManifest->setMetaknobDefault(0.5); // Required for the QuickEffect selector in DlgPrefEQ pEmptyManifest->setShortName(kNoEffectString); - auto pEmptyChainPreset = - EffectChainPresetPointer(new EffectChainPreset(pEmptyManifest)); + auto pEmptyChainPreset = EffectChainPresetPointer::create(pEmptyManifest); pEmptyChainPreset->setReadOnly(); return pEmptyChainPreset; @@ -139,8 +137,7 @@ bool EffectChainPresetManager::importPreset() { } file.close(); - EffectChainPresetPointer pPreset( - new EffectChainPreset(doc.documentElement())); + auto pPreset = EffectChainPresetPointer::create(doc.documentElement()); if (!pPreset->isEmpty() && !pPreset->name().isEmpty()) { // Don't allow '---' because that's the name of the internal empty preset if (pPreset->name() == kNoEffectString) { @@ -578,7 +575,7 @@ void EffectChainPresetManager::generateDefaultQuickEffectPresets() { } std::sort(manifestList.begin(), manifestList.end(), EffectManifest::sortLexigraphically); for (const auto& pManifest : manifestList) { - auto pChainPreset = EffectChainPresetPointer(new EffectChainPreset(pManifest)); + auto pChainPreset = EffectChainPresetPointer::create(pManifest); pChainPreset->setName(pManifest->displayName()); m_effectChainPresets.insert(pChainPreset->name(), pChainPreset); m_quickEffectChainPresetsSorted.append(pChainPreset); @@ -706,8 +703,8 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( if (chainNode.isElement()) { QDomElement chainElement = chainNode.toElement(); - EffectChainPresetPointer pPreset( - new EffectChainPreset(chainElement)); + EffectChainPresetPointer pPreset = + EffectChainPresetPointer::create(chainElement); standardEffectChainPresets.append(pPreset); } } @@ -718,8 +715,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( EffectChainPresetPointer mainEqPreset = nullptr; if (mainEqChainNode.isElement()) { QDomElement mainEqChainElement = mainEqChainNode.toElement(); - mainEqPreset = EffectChainPresetPointer( - new EffectChainPreset(mainEqChainElement)); + mainEqPreset = EffectChainPresetPointer::create(mainEqChainElement); } importUserPresets(); From 892f5e5f3ab3a0aa5e076d7d5dbb2f5de99fa06f Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 12 Jan 2024 13:53:05 +0100 Subject: [PATCH 09/12] Effects: more const --- src/effects/effectsmanager.cpp | 5 +++-- src/effects/presets/effectchainpresetmanager.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 432cc461b82..9bd93b49823 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -184,7 +184,7 @@ void EffectsManager::loadDefaultEqsAndQuickEffects() { pEqEffectSlot->loadEffectWithDefaults(pDefaultEqEffect); } - auto pDefaultQuickEffectPreset = + const auto pDefaultQuickEffectPreset = m_pChainPresetManager->getDefaultQuickEffectPreset(); QHashIterator qeIt(m_quickEffectChains); while (qeIt.hasNext()) { @@ -293,10 +293,11 @@ void EffectsManager::saveEffectsXml() { doc.appendChild(rootElement); QHash eqEffectManifests; + eqEffectManifests.reserve(m_equalizerEffectChains.size()); QHashIterator eqIt(m_equalizerEffectChains); while (eqIt.hasNext()) { eqIt.next(); - const auto pEffectSlot = eqIt.value().data()->getEffectSlot(0); + const auto pEffectSlot = eqIt.value()->getEffectSlot(0); VERIFY_OR_DEBUG_ASSERT(pEffectSlot) { return; } diff --git a/src/effects/presets/effectchainpresetmanager.cpp b/src/effects/presets/effectchainpresetmanager.cpp index c122ef79a1e..637f43767ab 100644 --- a/src/effects/presets/effectchainpresetmanager.cpp +++ b/src/effects/presets/effectchainpresetmanager.cpp @@ -696,7 +696,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( QDomElement rackElement = XmlParse::selectElement(root, EffectXml::kRack); QDomElement chainsElement = XmlParse::selectElement(rackElement, EffectXml::kChainsRoot); - QDomNodeList chainsList = chainsElement.elementsByTagName(EffectXml::kChain); + const QDomNodeList chainsList = chainsElement.elementsByTagName(EffectXml::kChain); for (int i = 0; i < chainsList.count(); ++i) { QDomNode chainNode = chainsList.at(i); @@ -723,7 +723,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( // Reload order of custom chain presets QDomElement chainPresetsElement = XmlParse::selectElement(root, EffectXml::kChainPresetList); - QDomNodeList presetNameList = + const QDomNodeList presetNameList = chainPresetsElement.elementsByTagName(EffectXml::kChainPresetName); for (int i = 0; i < presetNameList.count(); ++i) { QDomNode presetNameNode = presetNameList.at(i); @@ -752,7 +752,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( // Reload order of QuickEffect chain presets QDomElement quickEffectChainPresetsElement = XmlParse::selectElement(root, EffectXml::kQuickEffectList); - QDomNodeList quickEffectPresetNameList = + const QDomNodeList quickEffectPresetNameList = quickEffectChainPresetsElement.elementsByTagName(EffectXml::kChainPresetName); for (int i = 0; i < quickEffectPresetNameList.count(); ++i) { QDomNode presetNameNode = quickEffectPresetNameList.at(i); @@ -792,7 +792,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( // Read ids of effects that were loaded into Equalizer slots on last shutdown QDomElement eqEffectsElement = XmlParse::selectElement(root, EffectXml::kEqualizerEffects); - QDomNodeList eqEffectNodeList = + const QDomNodeList eqEffectNodeList = eqEffectsElement.elementsByTagName( EffectXml::kEffectId); for (int i = 0; i < eqEffectNodeList.count(); ++i) { @@ -812,7 +812,7 @@ EffectsXmlData EffectChainPresetManager::readEffectsXml( // Read names of presets that were loaded into QuickEffects on last shutdown QDomElement quickEffectPresetsElement = XmlParse::selectElement(root, EffectXml::kQuickEffectChainPresets); - QDomNodeList quickEffectNodeList = + const QDomNodeList quickEffectNodeList = quickEffectPresetsElement.elementsByTagName( EffectXml::kChainPresetName); for (int i = 0; i < quickEffectNodeList.count(); ++i) { @@ -842,7 +842,7 @@ EffectXmlDataSingleDeck EffectChainPresetManager::readEffectsXmlSingleDeck( // Read id of last loaded EQ effect QDomElement eqEffectsElement = XmlParse::selectElement(root, EffectXml::kEqualizerEffects); - QDomNodeList eqEffectNodeList = + const QDomNodeList eqEffectNodeList = eqEffectsElement.elementsByTagName( EffectXml::kEffectId); for (int i = 0; i < eqEffectNodeList.count(); ++i) { @@ -867,7 +867,7 @@ EffectXmlDataSingleDeck EffectChainPresetManager::readEffectsXmlSingleDeck( // Read name of last loaded QuickEffect preset QDomElement quickEffectPresetsElement = XmlParse::selectElement(root, EffectXml::kQuickEffectChainPresets); - QDomNodeList quickEffectNodeList = + const QDomNodeList quickEffectNodeList = quickEffectPresetsElement.elementsByTagName( EffectXml::kChainPresetName); for (int i = 0; i < quickEffectNodeList.count(); ++i) { From d7bab9aec506eb546f8fbb912ecc43529ea9d9cd Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 12 Jan 2024 13:53:54 +0100 Subject: [PATCH 10/12] EffectsManager: explicit interators to range-based loops --- src/effects/effectsmanager.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 9bd93b49823..d51de2069a1 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -174,9 +174,7 @@ void EffectsManager::addQuickEffectChain(const ChannelHandleAndGroup& deckHandle void EffectsManager::loadDefaultEqsAndQuickEffects() { auto pDefaultEqEffect = m_pChainPresetManager->getDefaultEqEffect(); - QHashIterator eqIt(m_equalizerEffectChains); - while (eqIt.hasNext()) { - auto pEqChainSlot = eqIt.next().value(); + for (const auto& pEqChainSlot : std::as_const(m_equalizerEffectChains)) { const auto pEqEffectSlot = pEqChainSlot->getEffectSlot(0); VERIFY_OR_DEBUG_ASSERT(pEqEffectSlot) { return; @@ -186,9 +184,7 @@ void EffectsManager::loadDefaultEqsAndQuickEffects() { const auto pDefaultQuickEffectPreset = m_pChainPresetManager->getDefaultQuickEffectPreset(); - QHashIterator qeIt(m_quickEffectChains); - while (qeIt.hasNext()) { - auto pChainSlot = qeIt.next().value(); + for (const auto& pChainSlot : std::as_const(m_quickEffectChains)) { pChainSlot->loadChainPreset(pDefaultQuickEffectPreset); } } @@ -214,11 +210,7 @@ void EffectsManager::readEffectsXml() { // Note: QuickEffect and EQ chains are created only for existing main decks, // thus only for those the configured presets are requested - QStringList deckStrings; - QHashIterator qeIt(m_quickEffectChains); - while (qeIt.hasNext()) { - deckStrings << qeIt.next().key(); - } + const QStringList deckStrings = m_quickEffectChains.keys(); EffectsXmlData data = m_pChainPresetManager->readEffectsXml(doc, deckStrings); for (int i = 0; i < data.standardEffectChainPresets.size(); i++) { From 03f843bda14bbab97f19f286afad974039925235 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 12 Jan 2024 13:54:35 +0100 Subject: [PATCH 11/12] EffectsManager: pre-allocate memory for QLists --- src/effects/effectsmanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index d51de2069a1..10dfe9db4c7 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -298,6 +298,7 @@ void EffectsManager::saveEffectsXml() { } QHash quickEffectChainPresets; + quickEffectChainPresets.reserve(m_quickEffectChains.size()); QHashIterator qeIt(m_quickEffectChains); while (qeIt.hasNext()) { qeIt.next(); @@ -306,6 +307,7 @@ void EffectsManager::saveEffectsXml() { } QList standardEffectChainPresets; + standardEffectChainPresets.reserve(m_quickEffectChains.size()); for (const auto& pChainSlot : std::as_const(m_standardEffectChains)) { auto pPreset = EffectChainPresetPointer::create(pChainSlot.data()); standardEffectChainPresets.append(pPreset); From 2e9aa1d1163e9c3fe012af156fa0a10da1d21ea0 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 12 Jan 2024 13:55:35 +0100 Subject: [PATCH 12/12] EffectsManager: clarify ownership/type with explicit assignment --- src/effects/effectsmanager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 10dfe9db4c7..69c420f4926 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -302,14 +302,16 @@ void EffectsManager::saveEffectsXml() { QHashIterator qeIt(m_quickEffectChains); while (qeIt.hasNext()) { qeIt.next(); - auto pPreset = EffectChainPresetPointer::create(qeIt.value().data()); + auto* pQuickEffectChain = qeIt.value().data(); + auto pPreset = EffectChainPresetPointer::create(pQuickEffectChain); quickEffectChainPresets.insert(qeIt.key(), pPreset); } QList standardEffectChainPresets; standardEffectChainPresets.reserve(m_quickEffectChains.size()); for (const auto& pChainSlot : std::as_const(m_standardEffectChains)) { - auto pPreset = EffectChainPresetPointer::create(pChainSlot.data()); + auto* pChain = pChainSlot.data(); + auto pPreset = EffectChainPresetPointer::create(pChain); standardEffectChainPresets.append(pPreset); }