diff --git a/src/control/controleffectknob.cpp b/src/control/controleffectknob.cpp index 7f76e102f67d..b42d1ed83634 100644 --- a/src/control/controleffectknob.cpp +++ b/src/control/controleffectknob.cpp @@ -13,10 +13,10 @@ void ControlEffectKnob::setBehaviour(EffectManifestParameter::ControlHint type, return; } - if (type == EffectManifestParameter::CONTROL_KNOB_LINEAR) { + if (type == EffectManifestParameter::ControlHint::KNOB_LINEAR) { m_pControl->setBehavior(new ControlLinPotmeterBehavior( dMinValue, dMaxValue, false)); - } else if (type == EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC) { + } else if (type == EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC) { if (dMinValue == 0) { if (dMaxValue == 1.0) { // Volume like control diff --git a/src/control/controlpotmeter.cpp b/src/control/controlpotmeter.cpp index 83c75db82f28..5100fc12a14f 100644 --- a/src/control/controlpotmeter.cpp +++ b/src/control/controlpotmeter.cpp @@ -23,8 +23,9 @@ ControlPotmeter::ControlPotmeter(ConfigKey key, double dMinValue, double dMaxVal bool allowOutOfBounds, bool bIgnoreNops, bool bTrack, - bool bPersist) - : ControlObject(key, bIgnoreNops, bTrack, bPersist), + bool bPersist, + double defaultValue) + : ControlObject(key, bIgnoreNops, bTrack, bPersist, defaultValue), m_controls(key) { setRange(dMinValue, dMaxValue, allowOutOfBounds); double default_value = dMinValue + 0.5 * (dMaxValue - dMinValue); diff --git a/src/control/controlpotmeter.h b/src/control/controlpotmeter.h index 30fcab06c9e1..ef56a8eb2a7b 100644 --- a/src/control/controlpotmeter.h +++ b/src/control/controlpotmeter.h @@ -77,7 +77,8 @@ class ControlPotmeter : public ControlObject { bool allowOutOfBounds = false, bool bIgnoreNops = true, bool bTrack = false, - bool bPersist = false); + bool bPersist = false, + double defaultValue = 0.0); virtual ~ControlPotmeter(); // Sets the step count of the associated PushButtons. diff --git a/src/effects/effect.cpp b/src/effects/effect.cpp index 0eef4287cdb8..36cb9d41d5c9 100644 --- a/src/effects/effect.cpp +++ b/src/effects/effect.cpp @@ -3,6 +3,7 @@ #include "effects/effect.h" #include "effects/effectprocessor.h" #include "effects/effectsmanager.h" +#include "effects/effectxmlelements.h" #include "engine/effects/engineeffectchain.h" #include "engine/effects/engineeffect.h" #include "util/xml.h" @@ -111,7 +112,7 @@ void Effect::sendParameterUpdate() { unsigned int Effect::numKnobParameters() const { unsigned int num = 0; foreach(const EffectParameter* parameter, m_parameters) { - if (parameter->manifest().controlHint() != EffectManifestParameter::CONTROL_TOGGLE_STEPPING) { + if (parameter->manifest().controlHint() != EffectManifestParameter::ControlHint::TOGGLE_STEPPING) { ++num; } } @@ -121,7 +122,7 @@ unsigned int Effect::numKnobParameters() const { unsigned int Effect::numButtonParameters() const { unsigned int num = 0; foreach(const EffectParameter* parameter, m_parameters) { - if (parameter->manifest().controlHint() == EffectManifestParameter::CONTROL_TOGGLE_STEPPING) { + if (parameter->manifest().controlHint() == EffectManifestParameter::ControlHint::TOGGLE_STEPPING) { ++num; } } @@ -140,7 +141,7 @@ EffectParameter* Effect::getParameterById(const QString& id) const { // static bool Effect::isButtonParameter(EffectParameter* parameter) { return parameter->manifest().controlHint() == - EffectManifestParameter::CONTROL_TOGGLE_STEPPING; + EffectManifestParameter::ControlHint::TOGGLE_STEPPING; } // static @@ -172,32 +173,15 @@ EffectParameter* Effect::getButtonParameterForSlot(unsigned int slotNumber) { return getFilteredParameterForSlot(isButtonParameter, slotNumber); } -QDomElement Effect::toXML(QDomDocument* doc) const { - QDomElement element = doc->createElement("Effect"); - XmlParse::addElement(*doc, element, "Id", m_manifest.id()); - XmlParse::addElement(*doc, element, "Version", m_manifest.version()); - - QDomElement parameters = doc->createElement("Parameters"); - foreach (EffectParameter* pParameter, m_parameters) { - const EffectManifestParameter& parameterManifest = - pParameter->manifest(); - QDomElement parameter = doc->createElement("Parameter"); - XmlParse::addElement(*doc, parameter, "Id", parameterManifest.id()); - // TODO(rryan): Do smarter QVariant formatting? - XmlParse::addElement(*doc, parameter, "Value", QString::number(pParameter->getValue())); - // TODO(rryan): Output link state, etc. - parameters.appendChild(parameter); - } - element.appendChild(parameters); - - return element; -} - // static -EffectPointer Effect::fromXML(EffectsManager* pEffectsManager, +EffectPointer Effect::createFromXml(EffectsManager* pEffectsManager, const QDomElement& element) { - QString effectId = XmlParse::selectNodeQString(element, "Id"); + // Empty elements are used to preserve chain order + // when there are empty slots at the beginning of the chain. + if (!element.hasChildNodes()) { + return EffectPointer(); + } + QString effectId = XmlParse::selectNodeQString(element, EffectXml::EffectId); EffectPointer pEffect = pEffectsManager->instantiateEffect(effectId); - // TODO(rryan): Load parameter values / etc. from element. return pEffect; } diff --git a/src/effects/effect.h b/src/effects/effect.h index fbfa75a6a144..2d6c57f474f9 100644 --- a/src/effects/effect.h +++ b/src/effects/effect.h @@ -55,8 +55,7 @@ class Effect : public QObject { void removeFromEngine(EngineEffectChain* pChain, int iIndex); void updateEngineState(); - QDomElement toXML(QDomDocument* doc) const; - static EffectPointer fromXML(EffectsManager* pEffectsManager, + static EffectPointer createFromXml(EffectsManager* pEffectsManager, const QDomElement& element); signals: diff --git a/src/effects/effectbuttonparameterslot.cpp b/src/effects/effectbuttonparameterslot.cpp index 51a9964230cb..629c47eb5b55 100644 --- a/src/effects/effectbuttonparameterslot.cpp +++ b/src/effects/effectbuttonparameterslot.cpp @@ -2,9 +2,11 @@ #include "control/controleffectknob.h" #include "effects/effectbuttonparameterslot.h" +#include "effects/effectxmlelements.h" #include "control/controlobject.h" #include "control/controlpushbutton.h" #include "util/math.h" +#include "util/xml.h" EffectButtonParameterSlot::EffectButtonParameterSlot(const QString& group, const unsigned int iParameterSlotNumber) @@ -31,6 +33,7 @@ EffectButtonParameterSlot::EffectButtonParameterSlot(const QString& group, EffectButtonParameterSlot::~EffectButtonParameterSlot() { //qDebug() << debugString() << "destroyed"; + // m_pControlLoaded and m_pControlType are deleted by ~EffectParameterSlotBase delete m_pControlValue; } @@ -107,3 +110,34 @@ void EffectButtonParameterSlot::slotValueChanged(double v) { m_pEffectParameter->setValue(v); } } + +QDomElement EffectButtonParameterSlot::toXml(QDomDocument* doc) const { + QDomElement parameterElement; + if (m_pEffectParameter != nullptr) { + parameterElement = doc->createElement(EffectXml::Parameter); + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterValue, + QString::number(m_pControlValue->get())); + } + + return parameterElement; +} + +void EffectButtonParameterSlot::loadParameterSlotFromXml(const QDomElement& + parameterElement) { + if (m_pEffectParameter == nullptr) { + return; + } + if (!parameterElement.hasChildNodes()) { + m_pControlValue->reset(); + } else { + bool conversionWorked = false; + double value = XmlParse::selectNodeDouble(parameterElement, + EffectXml::ParameterValue, + &conversionWorked); + if (conversionWorked) { + m_pControlValue->set(value); + } + // If the conversion failed, the default value is kept. + } +} diff --git a/src/effects/effectbuttonparameterslot.h b/src/effects/effectbuttonparameterslot.h index c537034b8970..faa81c138aeb 100644 --- a/src/effects/effectbuttonparameterslot.h +++ b/src/effects/effectbuttonparameterslot.h @@ -32,6 +32,9 @@ class EffectButtonParameterSlot : public EffectParameterSlotBase { // Clear the currently loaded effect void clear(); + QDomElement toXml(QDomDocument* doc) const override; + void loadParameterSlotFromXml(const QDomElement& parameterElement) override; + private slots: // Solely for handling control changes void slotParameterValueChanged(double value); diff --git a/src/effects/effectchain.cpp b/src/effects/effectchain.cpp index fdabe4ae4891..89435c76b97a 100644 --- a/src/effects/effectchain.cpp +++ b/src/effects/effectchain.cpp @@ -2,6 +2,7 @@ #include "effects/effectchainmanager.h" #include "effects/effectsmanager.h" +#include "effects/effectxmlelements.h" #include "engine/effects/engineeffectchain.h" #include "engine/effects/engineeffectrack.h" #include "engine/effects/message.h" @@ -96,8 +97,14 @@ EffectChainPointer EffectChain::clone(EffectChainPointer pChain) { // Do not set the state of the chain because that information belongs // to the EffectChainSlot. Leave that to EffectChainSlot::loadEffectChain. for (const auto& pEffect : pChain->effects()) { - EffectPointer pClonedEffect = pChain->m_pEffectsManager - ->instantiateEffect(pEffect->getManifest().id()); + EffectPointer pClonedEffect; + if (pEffect == nullptr) { + // Insert empty effect to preserve chain order + pClonedEffect = EffectPointer(); + } else { + pClonedEffect = pChain->m_pEffectsManager + ->instantiateEffect(pEffect->getManifest().id()); + } pClone->addEffect(pClonedEffect); } return EffectChainPointer(pClone); @@ -196,6 +203,9 @@ void EffectChain::setInsertionType(InsertionType insertionType) { void EffectChain::addEffect(EffectPointer pEffect) { //qDebug() << debugString() << "addEffect"; if (!pEffect) { + // Insert empty effects to preserve chain order + // when loading chains with empty effects + m_effects.append(pEffect); return; } @@ -214,7 +224,7 @@ void EffectChain::addEffect(EffectPointer pEffect) { void EffectChain::replaceEffect(unsigned int effectSlotNumber, EffectPointer pEffect) { - //qDebug() << debugString() << "replaceEffect" << iEffectNumber << pEffect; + //qDebug() << debugString() << "replaceEffect" << effectSlotNumber << pEffect; while (effectSlotNumber >= static_cast(m_effects.size())) { if (pEffect.isNull()) { return; @@ -222,7 +232,6 @@ void EffectChain::replaceEffect(unsigned int effectSlotNumber, m_effects.append(EffectPointer()); } - EffectPointer pOldEffect = m_effects[effectSlotNumber]; if (!pOldEffect.isNull()) { if (m_bAddedToEngine) { @@ -269,34 +278,17 @@ void EffectChain::sendParameterUpdate() { m_pEffectsManager->writeRequest(pRequest); } -QDomElement EffectChain::toXML(QDomDocument* doc) const { - QDomElement element = doc->createElement("EffectChain"); - - XmlParse::addElement(*doc, element, "Id", m_id); - XmlParse::addElement(*doc, element, "Name", m_name); - XmlParse::addElement(*doc, element, "Description", m_description); - XmlParse::addElement(*doc, element, "InsertionType", - insertionTypeToString(m_insertionType)); - - QDomElement effectsNode = doc->createElement("Effects"); - foreach (EffectPointer pEffect, m_effects) { - if (pEffect) { - QDomElement effectNode = pEffect->toXML(doc); - effectsNode.appendChild(effectNode); - } - } - element.appendChild(effectsNode); - - return element; -} - // static -EffectChainPointer EffectChain::fromXML(EffectsManager* pEffectsManager, +EffectChainPointer EffectChain::createFromXml(EffectsManager* pEffectsManager, const QDomElement& element) { - QString id = XmlParse::selectNodeQString(element, "Id"); - QString name = XmlParse::selectNodeQString(element, "Name"); - QString description = XmlParse::selectNodeQString(element, "Description"); - QString insertionTypeStr = XmlParse::selectNodeQString(element, "InsertionType"); + QString id = XmlParse::selectNodeQString(element, + EffectXml::ChainId); + QString name = XmlParse::selectNodeQString(element, + EffectXml::ChainName); + QString description = XmlParse::selectNodeQString(element, + EffectXml::ChainDescription); + QString insertionTypeStr = XmlParse::selectNodeQString(element, + EffectXml::ChainInsertionType); EffectChain* pChain = new EffectChain(pEffectsManager, id); pChain->setName(name); @@ -309,17 +301,15 @@ EffectChainPointer EffectChain::fromXML(EffectsManager* pEffectsManager, EffectChainPointer pChainWrapped(pChain); pEffectsManager->getEffectChainManager()->addEffectChain(pChainWrapped); - QDomElement effects = XmlParse::selectElement(element, "Effects"); + QDomElement effects = XmlParse::selectElement(element, EffectXml::EffectsRoot); QDomNodeList effectChildren = effects.childNodes(); for (int i = 0; i < effectChildren.count(); ++i) { QDomNode effect = effectChildren.at(i); if (effect.isElement()) { - EffectPointer pEffect = Effect::fromXML( + EffectPointer pEffect = Effect::createFromXml( pEffectsManager, effect.toElement()); - if (pEffect) { - pChain->addEffect(pEffect); - } + pChain->addEffect(pEffect); } } diff --git a/src/effects/effectchain.h b/src/effects/effectchain.h index 204b7a8012f3..66a41d4300b2 100644 --- a/src/effects/effectchain.h +++ b/src/effects/effectchain.h @@ -93,8 +93,7 @@ class EffectChain : public QObject { EngineEffectChain* getEngineEffectChain(); - QDomElement toXML(QDomDocument* doc) const; - static EffectChainPointer fromXML(EffectsManager* pEffectsManager, + static EffectChainPointer createFromXml(EffectsManager* pEffectsManager, const QDomElement& element); static EffectChainPointer clone(EffectChainPointer pChain); diff --git a/src/effects/effectchainmanager.cpp b/src/effects/effectchainmanager.cpp index f37bf759dcad..f196fda1aab4 100644 --- a/src/effects/effectchainmanager.cpp +++ b/src/effects/effectchainmanager.cpp @@ -1,13 +1,12 @@ #include "effects/effectchainmanager.h" +#include "effects/effectsmanager.h" +#include "effects/effectxmlelements.h" #include #include #include #include -#include "effects/effectsmanager.h" -#include "util/xml.h" - EffectChainManager::EffectChainManager(UserSettingsPointer pConfig, EffectsManager* pEffectsManager) : QObject(pEffectsManager), @@ -128,22 +127,23 @@ EffectChainPointer EffectChainManager::getPrevEffectChain(EffectChainPointer pEf } bool EffectChainManager::saveEffectChains() { - //qDebug() << debugString() << "saveEffectChains"; QDomDocument doc("MixxxEffects"); QString blank = "\n" - "\n" - "\n"; + "<" + EffectXml::Root + " schemaVersion=\"" + + QString::number(EffectXml::kXmlSchemaVersion) + "\">\n" + "\n"; doc.setContent(blank); QDomElement rootNode = doc.documentElement(); - QDomElement chains = doc.createElement("EffectChains"); - foreach (EffectChainPointer pChain, m_effectChains) { - QDomElement chain = pChain->toXML(&doc); - chains.appendChild(chain); + for (EffectRackPointer pRack : m_standardEffectRacks) { + rootNode.appendChild(pRack->toXml(&doc)); } - rootNode.appendChild(chains); + // TODO? Save QuickEffects in effects.xml too, or keep stored in ConfigObjects? +// foreach(EffectRackPointer pRack, m_quickEffectRacks) { +// rootNode.appendChild(pRack->toXML(&doc)); +// } QDir settingsPath(m_pConfig->getSettingsPath()); @@ -164,37 +164,58 @@ bool EffectChainManager::saveEffectChains() { return true; } -bool EffectChainManager::loadEffectChains() { - //qDebug() << debugString() << "loadEffectChains"; +QList> EffectChainManager::loadEffectChains() { + // StandardEffectRack::addEffectChainSlot uses both the EffectChainPointer + // and the saved state from the XML to initialize the respective + // EffectChain/Effect/EffectParameter/EffectButtonParameter Slots + QList> loadedChains; QDir settingsPath(m_pConfig->getSettingsPath()); QFile file(settingsPath.absoluteFilePath("effects.xml")); + QDomDocument doc; if (!file.open(QIODevice::ReadOnly)) { - return false; + EffectChainPointer pEmptyChain; + QDomElement emptyChainElement = doc.createElement(EffectXml::Chain); + for (int i = 0; i < kNumEffectsPerUnit; ++i) { + pEmptyChain = EffectChainPointer(new EffectChain(m_pEffectsManager, + QString(), + EffectChainPointer())); + loadedChains.append(std::make_pair(pEmptyChain, emptyChainElement)); + } + return loadedChains; } - QDomDocument doc; if (!doc.setContent(&file)) { file.close(); - return false; + EffectChainPointer pEmptyChain; + QDomElement emptyChainElement = doc.createElement(EffectXml::Chain); + for (int i = 0; i < kNumEffectsPerUnit; ++i) { + pEmptyChain = EffectChainPointer(new EffectChain(m_pEffectsManager, + QString(), + EffectChainPointer())); + loadedChains.append(std::make_pair(pEmptyChain, emptyChainElement)); + } + return loadedChains; } file.close(); QDomElement root = doc.documentElement(); + QDomElement rackElement = XmlParse::selectElement(root, EffectXml::Rack); + QDomElement chainsElement = XmlParse::selectElement(rackElement, EffectXml::ChainsRoot); + QDomNodeList chainsList = chainsElement.elementsByTagName(EffectXml::Chain); - QDomElement effectChains = XmlParse::selectElement(root, "EffectChains"); - QDomNodeList chains = effectChains.childNodes(); - - for (int i = 0; i < chains.count(); ++i) { - QDomNode chainNode = chains.at(i); + for (int i = 0; i < chainsList.count(); ++i) { + QDomNode chainNode = chainsList.at(i); if (chainNode.isElement()) { - EffectChainPointer pChain = EffectChain::fromXML( - m_pEffectsManager, chainNode.toElement()); + QDomElement chainElement = chainNode.toElement(); + EffectChainPointer pChain = EffectChain::createFromXml( + m_pEffectsManager, chainElement); + loadedChains.append(std::make_pair(pChain, chainElement)); m_effectChains.append(pChain); } } - return true; + return loadedChains; } diff --git a/src/effects/effectchainmanager.h b/src/effects/effectchainmanager.h index 0e648aee1327..7401b7239d07 100644 --- a/src/effects/effectchainmanager.h +++ b/src/effects/effectchainmanager.h @@ -10,6 +10,7 @@ #include "effects/effectrack.h" #include "engine/channelhandle.h" #include "util/class.h" +#include "util/xml.h" class EffectsManager; @@ -50,7 +51,9 @@ class EffectChainManager : public QObject { EffectChainPointer getPrevEffectChain(EffectChainPointer pEffectChain); bool saveEffectChains(); - bool loadEffectChains(); + QList> loadEffectChains(); + + static const int kNumEffectsPerUnit = 4; private: QString debugString() const { diff --git a/src/effects/effectchainslot.cpp b/src/effects/effectchainslot.cpp index a30521a6e2c0..a9417f5becd5 100644 --- a/src/effects/effectchainslot.cpp +++ b/src/effects/effectchainslot.cpp @@ -1,10 +1,12 @@ #include "effects/effectchainslot.h" #include "effects/effectrack.h" +#include "effects/effectxmlelements.h" #include "control/controlpotmeter.h" #include "control/controlpushbutton.h" #include "mixer/playermanager.h" #include "util/math.h" +#include "util/xml.h" EffectChainSlot::EffectChainSlot(EffectRack* pRack, const QString& group, unsigned int iChainNumber) @@ -34,10 +36,10 @@ EffectChainSlot::EffectChainSlot(EffectRack* pRack, const QString& group, connect(m_pControlChainEnabled, SIGNAL(valueChanged(double)), this, SLOT(slotControlChainEnabled(double))); - m_pControlChainMix = new ControlPotmeter(ConfigKey(m_group, "mix"), 0.0, 1.0); + m_pControlChainMix = new ControlPotmeter(ConfigKey(m_group, "mix"), 0.0, 1.0, + false, true, false, true, 1.0); connect(m_pControlChainMix, SIGNAL(valueChanged(double)), this, SLOT(slotControlChainMix(double))); - m_pControlChainMix->set(1.0); m_pControlChainSuperParameter = new ControlPotmeter(ConfigKey(m_group, "super1"), 0.0, 1.0); connect(m_pControlChainSuperParameter, SIGNAL(valueChanged(double)), @@ -430,3 +432,64 @@ void EffectChainSlot::slotChannelStatusChanged(const QString& group) { unsigned int EffectChainSlot::getChainSlotNumber() const { return m_iChainSlotNumber; } + +QDomElement EffectChainSlot::toXml(QDomDocument* doc) const { + QDomElement chainElement = doc->createElement(EffectXml::Chain); + if (m_pEffectChain == nullptr) { + return chainElement; + } + + XmlParse::addElement(*doc, chainElement, EffectXml::ChainId, + m_pEffectChain->id()); + XmlParse::addElement(*doc, chainElement, EffectXml::ChainName, + m_pEffectChain->name()); + XmlParse::addElement(*doc, chainElement, EffectXml::ChainDescription, + m_pEffectChain->description()); + XmlParse::addElement(*doc, chainElement, EffectXml::ChainInsertionType, + EffectChain::insertionTypeToString( + static_cast( + static_cast(m_pControlChainInsertionType->get())))); + XmlParse::addElement(*doc, chainElement, EffectXml::ChainSuperParameter, + QString::number(m_pControlChainSuperParameter->get())); + + QDomElement effectsElement = doc->createElement(EffectXml::EffectsRoot); + for (const auto& pEffectSlot : m_slots) { + QDomElement effectNode; + if (pEffectSlot->getEffect()) { + effectNode = pEffectSlot->toXml(doc); + } else { + // Create empty element to ensure effects stay in order + // if there are empty slots before loaded slots. + effectNode = doc->createElement(EffectXml::Effect); + } + effectsElement.appendChild(effectNode); + } + chainElement.appendChild(effectsElement); + + return chainElement; +} + +void EffectChainSlot::loadChainSlotFromXml(const QDomElement& effectChainElement) { + if (!effectChainElement.hasChildNodes()) { + return; + } + + // Note: insertion type is set in EffectChain::createFromXml + + m_pControlChainSuperParameter->set(XmlParse::selectNodeDouble( + effectChainElement, + EffectXml::ChainSuperParameter)); + + QDomElement effectsElement = XmlParse::selectElement(effectChainElement, + EffectXml::EffectsRoot); + QDomNodeList effectsNodeList = effectsElement.childNodes(); + for (int i = 0; i < m_slots.size(); ++i) { + if (m_slots[i] != nullptr) { + QDomNode effectNode = effectsNodeList.at(i); + if (effectNode.isElement()) { + QDomElement effectElement = effectNode.toElement(); + m_slots[i]->loadEffectSlotFromXml(effectElement); + } + } + } +} diff --git a/src/effects/effectchainslot.h b/src/effects/effectchainslot.h index bc0ecd642f2c..d1777c0ec4a1 100644 --- a/src/effects/effectchainslot.h +++ b/src/effects/effectchainslot.h @@ -51,6 +51,9 @@ class EffectChainSlot : public QObject { return m_group; } + QDomElement toXml(QDomDocument* doc) const; + void loadChainSlotFromXml(const QDomElement& effectChainElement); + signals: // Indicates that the effect pEffect has been loaded into slotNumber of // EffectChainSlot chainNumber. pEffect may be an invalid pointer, which diff --git a/src/effects/effectmanifestparameter.h b/src/effects/effectmanifestparameter.h index ec99cf154889..623b6b2ee12a 100644 --- a/src/effects/effectmanifestparameter.h +++ b/src/effects/effectmanifestparameter.h @@ -7,49 +7,77 @@ class EffectManifestParameter { public: - enum ControlHint { - CONTROL_UNKNOWN = 0, - CONTROL_KNOB_LINEAR, - CONTROL_KNOB_LOGARITHMIC, - CONTROL_KNOB_STEPPING, // A step rotary, steps given by m_steps - // are arranged with equal distance on scale - CONTROL_TOGGLE_STEPPING // For button and enum controls, not accessible - // form many controllers, no linking to super knob + enum class ControlHint { + UNKNOWN = 0, + KNOB_LINEAR, + KNOB_LOGARITHMIC, + KNOB_STEPPING, // A step rotary, steps given by m_steps + // are arranged with equal distance on scale + TOGGLE_STEPPING // For button and enum controls, not accessible + // from many controllers, no linking to meta knob }; - enum SemanticHint { - SEMANTIC_UNKNOWN = 0, - SEMANTIC_SAMPLES, - SEMANTIC_NOTE, + enum class SemanticHint { + UNKNOWN = 0, + SAMPLES, + NOTE, }; - enum UnitsHint { - UNITS_UNKNOWN = 0, - UNITS_TIME, - UNITS_HERTZ, - UNITS_SAMPLERATE, // fraction of the samplerate - UNITS_BEATS, // multiples of a beat + enum class UnitsHint { + UNKNOWN = 0, + TIME, + HERTZ, + SAMPLERATE, // fraction of the samplerate + BEATS, // multiples of a beat }; - enum LinkType { - LINK_NONE = 0, // Not controlled by the super knob - LINK_LINKED, // Controlled by the super knob as it is - LINK_LINKED_LEFT, // Controlled by the left side of the super knob - LINK_LINKED_RIGHT, // Controlled by the right side of the super knob - LINK_LINKED_LEFT_RIGHT, // Controlled by both sides of the super knob + enum class LinkType { + NONE = 0, // Not controlled by the meta knob + LINKED, // Controlled by the meta knob as it is + LINKED_LEFT, // Controlled by the left side of the meta knob + LINKED_RIGHT, // Controlled by the right side of the meta knob + LINKED_LEFT_RIGHT, // Controlled by both sides of the meta knob NUM_LINK_TYPES }; + static QString LinkTypeToString (LinkType type) { + if (type == LinkType::LINKED) { + return "LINKED"; + } else if (type == LinkType::LINKED_LEFT) { + return "LINKED_LEFT"; + } else if (type == LinkType::LINKED_RIGHT) { + return "LINKED_RIGHT"; + } else if (type == LinkType::LINKED_LEFT_RIGHT) { + return "LINKED_LEFT_RIGHT"; + } else { + return "NONE"; + } + } + + static LinkType LinkTypeFromString (const QString& string) { + if (string == "LINKED") { + return LinkType::LINKED; + } else if (string == "LINKED_LEFT") { + return LinkType::LINKED_LEFT; + } else if (string == "LINKED_RIGHT") { + return LinkType::LINKED_RIGHT; + } else if (string == "LINKED_LEFT_RIGHT") { + return LinkType::LINKED_LEFT_RIGHT; + } else { + return LinkType::NONE; + } + } + enum class LinkInversion { NOT_INVERTED = 0, INVERTED = 1 }; EffectManifestParameter() - : m_controlHint(CONTROL_UNKNOWN), - m_semanticHint(SEMANTIC_UNKNOWN), - m_unitsHint(UNITS_UNKNOWN), - m_defaultLinkType(LINK_NONE), + : m_controlHint(ControlHint::UNKNOWN), + m_semanticHint(SemanticHint::UNKNOWN), + m_unitsHint(UnitsHint::UNKNOWN), + m_defaultLinkType(LinkType::NONE), m_defaultLinkInversion(LinkInversion::NOT_INVERTED), m_neutralPointOnScale(0.0), m_default(0), @@ -135,13 +163,13 @@ class EffectManifestParameter { // Neutral Point On Scale is the parameter in the range 0 .. 1 on the knob that - // is adopted as neutral when controlled by the super knob. - // This is allows to link the super knob in a way that two effects are - // cranked in simultaneous, or in case of a split filter like super knob, - // both effects are neutral at super knob center. + // is adopted as neutral when controlled by the meta knob. + // This is allows to link the meta knob in a way that two effects are + // cranked in simultaneous, or in case of a split filter like meta knob, + // both effects are neutral at meta knob center. // A EQ Gain has usually a neutral point of 0.5 (0 dB) while a delay knob // has a neutral point of 0.0 (no delay) - // A EQ Gain knob cannot be used on a split super knob. + // A EQ Gain knob cannot be used on a split meta knob. virtual double neutralPointOnScale() const { return m_neutralPointOnScale; } diff --git a/src/effects/effectparameterslot.cpp b/src/effects/effectparameterslot.cpp index b988132adff8..9cf84ddceb58 100644 --- a/src/effects/effectparameterslot.cpp +++ b/src/effects/effectparameterslot.cpp @@ -2,37 +2,42 @@ #include "control/controleffectknob.h" #include "effects/effectparameterslot.h" +#include "effects/effectxmlelements.h" #include "control/controlobject.h" #include "control/controlpushbutton.h" #include "controllers/softtakeover.h" +#include "util/xml.h" EffectParameterSlot::EffectParameterSlot(const QString& group, const unsigned int iParameterSlotNumber) : EffectParameterSlotBase(group, iParameterSlotNumber) { QString itemPrefix = formatItemPrefix(iParameterSlotNumber); + + m_pControlValue = new ControlEffectKnob( + ConfigKey(m_group, itemPrefix)); + connect(m_pControlValue, SIGNAL(valueChanged(double)), + this, SLOT(slotValueChanged(double))); + m_pControlLoaded = new ControlObject( ConfigKey(m_group, itemPrefix + QString("_loaded"))); + m_pControlLoaded->setReadOnly(); + + m_pControlType = new ControlObject( + ConfigKey(m_group, itemPrefix + QString("_type"))); + m_pControlType->setReadOnly(); + m_pControlLinkType = new ControlPushButton( ConfigKey(m_group, itemPrefix + QString("_link_type"))); m_pControlLinkType->setButtonMode(ControlPushButton::TOGGLE); - m_pControlLinkType->setStates(EffectManifestParameter::NUM_LINK_TYPES); + m_pControlLinkType->setStates( + static_cast(EffectManifestParameter::LinkType::NUM_LINK_TYPES)); + m_pControlLinkType->connectValueChangeRequest( + this, SLOT(slotLinkTypeChanging(double))); + m_pControlLinkInverse = new ControlPushButton( ConfigKey(m_group, itemPrefix + QString("_link_inverse"))); m_pControlLinkInverse->setButtonMode(ControlPushButton::TOGGLE); - m_pControlValue = new ControlEffectKnob( - ConfigKey(m_group, itemPrefix)); - m_pControlType = new ControlObject( - ConfigKey(m_group, itemPrefix + QString("_type"))); - - m_pControlLinkType->connectValueChangeRequest( - this, SLOT(slotLinkTypeChanging(double))); connect(m_pControlLinkInverse, SIGNAL(valueChanged(double)), this, SLOT(slotLinkInverseChanged(double))); - connect(m_pControlValue, SIGNAL(valueChanged(double)), - this, SLOT(slotValueChanged(double))); - - // Read-only controls. - m_pControlType->setReadOnly(); - m_pControlLoaded->setReadOnly(); m_pSoftTakeover = new SoftTakeover(); @@ -42,9 +47,10 @@ EffectParameterSlot::EffectParameterSlot(const QString& group, const unsigned in EffectParameterSlot::~EffectParameterSlot() { //qDebug() << debugString() << "destroyed"; delete m_pControlValue; - delete m_pSoftTakeover; + // m_pControlLoaded and m_pControlType are deleted by ~EffectParameterSlotBase delete m_pControlLinkType; delete m_pControlLinkInverse; + delete m_pSoftTakeover; } void EffectParameterSlot::loadEffect(EffectPointer pEffect) { @@ -82,7 +88,8 @@ void EffectParameterSlot::loadEffect(EffectPointer pEffect) { // Default loaded parameters to loaded and unlinked m_pControlLoaded->forceSet(1.0); - m_pControlLinkType->set(m_pEffectParameter->getDefaultLinkType()); + m_pControlLinkType->set( + static_cast(m_pEffectParameter->getDefaultLinkType())); m_pControlLinkInverse->set( static_cast(m_pEffectParameter->getDefaultLinkInversion())); @@ -104,7 +111,8 @@ void EffectParameterSlot::clear() { m_pControlValue->set(0.0); m_pControlValue->setDefaultValue(0.0); m_pControlType->forceSet(0.0); - m_pControlLinkType->setAndConfirm(EffectManifestParameter::LINK_NONE); + m_pControlLinkType->setAndConfirm( + static_cast(EffectManifestParameter::LinkType::NONE)); m_pSoftTakeover->setThreshold(SoftTakeover::kDefaultTakeoverThreshold); m_pControlLinkInverse->set(0.0); emit(updated()); @@ -117,24 +125,29 @@ void EffectParameterSlot::slotParameterValueChanged(double value) { void EffectParameterSlot::slotLinkTypeChanging(double v) { m_pSoftTakeover->ignoreNext(); - if (v > EffectManifestParameter::LINK_LINKED) { + EffectManifestParameter::LinkType newType = + static_cast( + static_cast(v)); + if (newType == EffectManifestParameter::LinkType::LINKED_LEFT || + newType == EffectManifestParameter::LinkType::LINKED_RIGHT || + newType == EffectManifestParameter::LinkType::LINKED_LEFT_RIGHT) { double neutral = m_pEffectParameter->getNeutralPointOnScale(); if (neutral > 0.0 && neutral < 1.0) { // Knob is already a split knob, meaning it has a positive and // negative effect if it's twisted above the neutral point or // below the neutral point. // Toggle back to 0 - v = EffectManifestParameter::LINK_NONE; + newType = EffectManifestParameter::LinkType::NONE; } } - if (static_cast(v) == EffectManifestParameter::LINK_LINKED_LEFT || - static_cast(v) == EffectManifestParameter::LINK_LINKED_RIGHT) { + if (newType == EffectManifestParameter::LinkType::LINKED_LEFT || + newType == EffectManifestParameter::LinkType::LINKED_RIGHT) { m_pSoftTakeover->setThreshold( SoftTakeover::kDefaultTakeoverThreshold * 2.0); } else { m_pSoftTakeover->setThreshold(SoftTakeover::kDefaultTakeoverThreshold); } - m_pControlLinkType->setAndConfirm(v); + m_pControlLinkType->setAndConfirm(static_cast(newType)); } void EffectParameterSlot::slotLinkInverseChanged(double v) { @@ -153,7 +166,7 @@ void EffectParameterSlot::onEffectMetaParameterChanged(double parameter, bool fo bool inverse = m_pControlLinkInverse->toBool(); switch (type) { - case EffectManifestParameter::LINK_LINKED: + case EffectManifestParameter::LinkType::LINKED: if (parameter < 0.0 || parameter > 1.0) { return; } @@ -178,7 +191,7 @@ void EffectParameterSlot::onEffectMetaParameterChanged(double parameter, bool fo } } break; - case EffectManifestParameter::LINK_LINKED_LEFT: + case EffectManifestParameter::LinkType::LINKED_LEFT: if (parameter >= 0.5 && parameter <= 1.0) { parameter = 1; } else if (parameter >= 0.0 && parameter <= 0.5) { @@ -187,7 +200,7 @@ void EffectParameterSlot::onEffectMetaParameterChanged(double parameter, bool fo return; } break; - case EffectManifestParameter::LINK_LINKED_RIGHT: + case EffectManifestParameter::LinkType::LINKED_RIGHT: if (parameter >= 0.5 && parameter <= 1.0) { parameter -= 0.5; parameter *= 2; @@ -197,7 +210,7 @@ void EffectParameterSlot::onEffectMetaParameterChanged(double parameter, bool fo return; } break; - case EffectManifestParameter::LINK_LINKED_LEFT_RIGHT: + case EffectManifestParameter::LinkType::LINKED_LEFT_RIGHT: if (parameter >= 0.5 && parameter <= 1.0) { parameter -= 0.5; parameter *= 2; @@ -208,7 +221,7 @@ void EffectParameterSlot::onEffectMetaParameterChanged(double parameter, bool fo return; } break; - case EffectManifestParameter::LINK_NONE: + case EffectManifestParameter::LinkType::NONE: default: return; } @@ -242,3 +255,62 @@ void EffectParameterSlot::slotValueChanged(double v) { m_pEffectParameter->setValue(v); } } + +QDomElement EffectParameterSlot::toXml(QDomDocument* doc) const { + QDomElement parameterElement; + if (m_pEffectParameter != nullptr) { + parameterElement = doc->createElement(EffectXml::Parameter); + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterValue, + QString::number(m_pControlValue->getParameter())); + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterLinkType, + EffectManifestParameter::LinkTypeToString( + static_cast( + static_cast(m_pControlLinkType->get())))); + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterLinkInversion, + QString::number(m_pControlLinkInverse->get())); + } + + return parameterElement; +} + +void EffectParameterSlot::loadParameterSlotFromXml(const QDomElement& parameterElement) { + if (m_pEffectParameter == nullptr) { + return; + } + if (!parameterElement.hasChildNodes()) { + m_pControlValue->reset(); + m_pControlLinkType->set( + static_cast(m_pEffectParameter->getDefaultLinkType())); + m_pControlLinkInverse->set( + static_cast(m_pEffectParameter->getDefaultLinkInversion())); + } else { + // Need to use setParameterFrom(..., nullptr) here to + // trigger valueChanged() signal emission and execute slotValueChanged() + bool conversionWorked = false; + double value = XmlParse::selectNodeDouble(parameterElement, + EffectXml::ParameterValue, &conversionWorked); + if (conversionWorked) { + // Need to use setParameterFrom(..., nullptr) here to + // trigger valueChanged() signal emission and execute slotValueChanged() + m_pControlValue->setParameterFrom(value, nullptr); + } + // If the conversion failed, the default value is kept. + + QString linkTypeString = XmlParse::selectNodeQString(parameterElement, + EffectXml::ParameterLinkType); + if (!linkTypeString.isEmpty()) { + m_pControlLinkType->set(static_cast( + EffectManifestParameter::LinkTypeFromString(linkTypeString))); + } + + conversionWorked = false; + double linkInversion = XmlParse::selectNodeDouble(parameterElement, + EffectXml::ParameterLinkInversion, &conversionWorked); + if (conversionWorked) { + m_pControlLinkInverse->set(linkInversion); + } + } +} diff --git a/src/effects/effectparameterslot.h b/src/effects/effectparameterslot.h index 25d7474f8f34..3d99960218dc 100644 --- a/src/effects/effectparameterslot.h +++ b/src/effects/effectparameterslot.h @@ -43,6 +43,9 @@ class EffectParameterSlot : public EffectParameterSlotBase { // Clear the currently loaded effect void clear(); + QDomElement toXml(QDomDocument* doc) const override; + void loadParameterSlotFromXml(const QDomElement& parameterElement) override; + private slots: // Solely for handling control changes void slotParameterValueChanged(double value); diff --git a/src/effects/effectparameterslotbase.h b/src/effects/effectparameterslotbase.h index 1b0939db0813..ce21d6a105ca 100644 --- a/src/effects/effectparameterslotbase.h +++ b/src/effects/effectparameterslotbase.h @@ -26,6 +26,9 @@ class EffectParameterSlotBase : public QObject { QString description() const; const EffectManifestParameter getManifest(); + virtual QDomElement toXml(QDomDocument* doc) const = 0; + virtual void loadParameterSlotFromXml(const QDomElement& parameterElement) = 0; + signals: // Signal that indicates that the EffectParameterSlotBase has been updated. void updated(); diff --git a/src/effects/effectrack.cpp b/src/effects/effectrack.cpp index ea9226fdb184..0238f90c53bb 100644 --- a/src/effects/effectrack.cpp +++ b/src/effects/effectrack.cpp @@ -202,6 +202,22 @@ void EffectRack::loadPrevEffect(const unsigned int iChainSlotNumber, pChain->replaceEffect(iEffectSlotNumber, pPrevEffect); } +QDomElement EffectRack::toXml(QDomDocument* doc) const { + QDomElement rackElement = doc->createElement("Rack"); + QDomElement groupElement = doc->createElement("Group"); + QDomText groupText = doc->createTextNode(m_group); + groupElement.appendChild(groupText); + rackElement.appendChild(groupElement); + + QDomElement chainsElement = doc->createElement("Chains"); + for (EffectChainSlotPointer pChainSlot : m_effectChainSlots) { + QDomElement chain = pChainSlot->toXml(doc); + chainsElement.appendChild(chain); + } + rackElement.appendChild(chainsElement); + return rackElement; +} + StandardEffectRack::StandardEffectRack(EffectsManager* pEffectsManager, EffectChainManager* pChainManager, const unsigned int iRackNumber) @@ -209,7 +225,8 @@ StandardEffectRack::StandardEffectRack(EffectsManager* pEffectsManager, formatGroupString(iRackNumber)) { } -EffectChainSlotPointer StandardEffectRack::addEffectChainSlot() { +EffectChainSlotPointer StandardEffectRack::addEffectChainSlot(EffectChainPointer pChain, + const QDomElement& effectChainElement) { int iChainSlotNumber = numEffectChainSlots(); QString group = formatEffectChainSlotGroupString(getRackNumber(), @@ -217,10 +234,7 @@ EffectChainSlotPointer StandardEffectRack::addEffectChainSlot() { EffectChainSlot* pChainSlot = new EffectChainSlot(this, group, iChainSlotNumber); - // TODO(rryan) How many should we make default? They create controls that - // the GUI may rely on, so the choice is important to communicate to skin - // designers. - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < EffectChainManager::kNumEffectsPerUnit; ++i) { pChainSlot->addEffectSlot( StandardEffectRack::formatEffectSlotGroupString( getRackNumber(), iChainSlotNumber, i)); @@ -239,18 +253,17 @@ EffectChainSlotPointer StandardEffectRack::addEffectChainSlot() { // Register all the existing channels with the new EffectChain. const QSet& registeredChannels = m_pEffectChainManager->registeredChannels(); - foreach (const ChannelHandleAndGroup& handle_group, registeredChannels) { + for (const ChannelHandleAndGroup& handle_group : registeredChannels) { pChainSlot->registerChannel(handle_group); } EffectChainSlotPointer pChainSlotPointer = EffectChainSlotPointer(pChainSlot); addEffectChainSlotInternal(pChainSlotPointer); - // Now load an empty effect chain into the slot so that users can edit - // effect slots on the fly without having to load a chain. - EffectChainPointer pChain = makeEmptyChain(); pChainSlotPointer->loadEffectChain(pChain); + pChainSlot->loadChainSlotFromXml(effectChainElement); + return pChainSlotPointer; } diff --git a/src/effects/effectrack.h b/src/effects/effectrack.h index f1e57a7fd42c..7512a28a06ab 100644 --- a/src/effects/effectrack.h +++ b/src/effects/effectrack.h @@ -52,6 +52,8 @@ class EffectRack : public QObject { return m_group; } + QDomElement toXml(QDomDocument* doc) const; + public slots: void slotClearRack(double v); @@ -114,7 +116,8 @@ class StandardEffectRack : public EffectRack { .arg(QString::number(iEffectSlotNumber + 1)); } - EffectChainSlotPointer addEffectChainSlot(); + EffectChainSlotPointer addEffectChainSlot(EffectChainPointer pChain, + const QDomElement& effectChainElement); }; class PerGroupRack : public EffectRack { diff --git a/src/effects/effectslot.cpp b/src/effects/effectslot.cpp index 1a8482b54921..c73b9c1e9f6a 100644 --- a/src/effects/effectslot.cpp +++ b/src/effects/effectslot.cpp @@ -1,9 +1,11 @@ #include "effects/effectslot.h" +#include "effects/effectxmlelements.h" #include #include "control/controlpushbutton.h" #include "control/controlproxy.h" +#include "util/xml.h" // The maximum number of effect parameters we're going to support. const unsigned int kDefaultMaxParameters = 16; @@ -176,7 +178,6 @@ void EffectSlot::loadEffect(EffectPointer pEffect) { for (const auto& pParameter : m_parameters) { pParameter->loadEffect(pEffect); } - for (const auto& pParameter : m_buttonParameters) { pParameter->loadEffect(pEffect); } @@ -268,3 +269,91 @@ void EffectSlot::slotEffectMetaParameter(double v, bool force) { pParameterSlot->onEffectMetaParameterChanged(v, force); } } + +QDomElement EffectSlot::toXml(QDomDocument* doc) const { + QDomElement effectElement = doc->createElement(EffectXml::Effect); + if (m_pEffect == nullptr) { + return effectElement; + } + + QDomElement metaKnobElement = doc->createElement(EffectXml::EffectMetaParameter); + XmlParse::addElement(*doc, effectElement, + EffectXml::EffectMetaParameter, + QString::number(m_pControlMetaParameter->get())); + EffectManifest manifest = m_pEffect->getManifest(); + XmlParse::addElement(*doc, effectElement, + EffectXml::EffectId, manifest.id()); + XmlParse::addElement(*doc, effectElement, + EffectXml::EffectVersion, manifest.version()); + + QDomElement parametersElement = doc->createElement(EffectXml::ParametersRoot); + + for (const auto& pParameter : m_parameters) { + QDomElement parameterElement = pParameter->toXml(doc); + if (!parameterElement.hasChildNodes()) { + continue; + } + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterId, + pParameter->getManifest().id()); + parametersElement.appendChild(parameterElement); + } + for (const auto& pParameter : m_buttonParameters) { + QDomElement parameterElement = pParameter->toXml(doc); + if (!parameterElement.hasChildNodes()) { + continue; + } + XmlParse::addElement(*doc, parameterElement, + EffectXml::ParameterId, + pParameter->getManifest().id()); + parametersElement.appendChild(parameterElement); + } + + effectElement.appendChild(parametersElement); + + return effectElement; +} + +void EffectSlot::loadEffectSlotFromXml(const QDomElement& effectElement) { + if (!effectElement.hasChildNodes()) { + return; + } + + QDomElement effectIdElement = XmlParse::selectElement(effectElement, + EffectXml::EffectId); + if (m_pEffect->getManifest().id() != effectIdElement.text()) { + qWarning() << "EffectSlot::loadEffectSlotFromXml" + << "effect ID in XML does not match presently loaded effect, ignoring."; + return; + } + + m_pControlMetaParameter->set(XmlParse::selectNodeDouble(effectElement, + EffectXml::EffectMetaParameter)); + + QDomElement parametersElement = XmlParse::selectElement(effectElement, + EffectXml::ParametersRoot); + if (!parametersElement.hasChildNodes()) { + return; + } + + QMap parametersById; + for (const auto& pParameter : m_parameters) { + parametersById.insert(pParameter->getManifest().id(), pParameter); + } + for (const auto& pParameter : m_buttonParameters) { + parametersById.insert(pParameter->getManifest().id(), pParameter); + } + + QDomNodeList parametersNodeList = parametersElement.childNodes(); + for (int i = 0; i < parametersNodeList.size(); ++i) { + QDomNode parameterNode = parametersNodeList.at(i); + if (parameterNode.isElement()) { + const QString id = XmlParse::selectNodeQString(parameterNode, + EffectXml::ParameterId); + EffectParameterSlotBasePointer pParameterSlot = parametersById.value(id); + if (pParameterSlot != nullptr) { + pParameterSlot->loadParameterSlotFromXml(parameterNode.toElement()); + } + } + } +} diff --git a/src/effects/effectslot.h b/src/effects/effectslot.h index 1b149b4e3c30..504d12ae0143 100644 --- a/src/effects/effectslot.h +++ b/src/effects/effectslot.h @@ -61,6 +61,9 @@ class EffectSlot : public QObject { return m_group; } + QDomElement toXml(QDomDocument* doc) const; + void loadEffectSlotFromXml(const QDomElement& effectElement); + public slots: // Request that this EffectSlot load the given Effect void loadEffect(EffectPointer pEffect); diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 263143b98175..788f27b9e8b2 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -33,7 +33,7 @@ EffectsManager::EffectsManager(QObject* pParent, UserSettingsPointer pConfig) EffectsManager::~EffectsManager() { m_underDestruction = true; - //m_pEffectChainManager->saveEffectChains(); + m_pEffectChainManager->saveEffectChains(); delete m_pEffectChainManager; // This must be done here, since the engineRacks are deleted via // the queue @@ -218,15 +218,15 @@ EffectRackPointer EffectsManager::getEffectRack(const QString& group) { return m_pEffectChainManager->getEffectRack(group); } -void EffectsManager::setupDefaults() { - //m_pEffectChainManager->loadEffectChains(); - +void EffectsManager::setup() { // Add a general purpose rack + QList> savedChains; + savedChains = m_pEffectChainManager->loadEffectChains(); + StandardEffectRackPointer pStandardRack = addStandardEffectRack(); - pStandardRack->addEffectChainSlot(); - pStandardRack->addEffectChainSlot(); - pStandardRack->addEffectChainSlot(); - pStandardRack->addEffectChainSlot(); + for (auto chain : savedChains) { + pStandardRack->addEffectChainSlot(chain.first, chain.second); + } EffectChainPointer pChain = EffectChainPointer(new EffectChain( this, "org.mixxx.effectchain.flanger")); diff --git a/src/effects/effectsmanager.h b/src/effects/effectsmanager.h index 3fbfa20d91c1..a9a5643be14f 100644 --- a/src/effects/effectsmanager.h +++ b/src/effects/effectsmanager.h @@ -73,7 +73,7 @@ class EffectsManager : public QObject { EffectPointer instantiateEffect(const QString& effectId); // Temporary, but for setting up all the default EffectChains and EffectRacks - void setupDefaults(); + void setup(); // Write an EffectsRequest to the EngineEffectsManager. EffectsManager takes // ownership of request and deletes it once a response is received. diff --git a/src/effects/effectxmlelements.h b/src/effects/effectxmlelements.h new file mode 100644 index 000000000000..68b90ad42bf5 --- /dev/null +++ b/src/effects/effectxmlelements.h @@ -0,0 +1,32 @@ +namespace EffectXml { +// Version history: +// 0 (Mixxx 2.1.0): initial support for saving state of effects +const int kXmlSchemaVersion = 0; + +const QString Root("MixxxEffects"); +const QString SchemaVersion("SchemaVersion"); + +const QString Rack("Rack"); +const QString RackGroup("Group"); + +const QString ChainsRoot("Chains"); +const QString Chain("EffectChain"); +const QString ChainSuperParameter("SuperParameterValue"); +const QString ChainId("Id"); +const QString ChainName("Name"); +const QString ChainDescription("Description"); +const QString ChainInsertionType("InsertionType"); + +const QString EffectsRoot("Effects"); +const QString Effect("Effect"); +const QString EffectMetaParameter("MetaParameterValue"); +const QString EffectId("Id"); +const QString EffectVersion("Version"); + +const QString ParametersRoot("Parameters"); +const QString Parameter("Parameter"); +const QString ParameterId("Id"); +const QString ParameterValue("Value"); +const QString ParameterLinkType("LinkType"); +const QString ParameterLinkInversion("LinkInversion"); +} diff --git a/src/effects/native/autopaneffect.cpp b/src/effects/native/autopaneffect.cpp index a5b385675589..54e2737627a5 100644 --- a/src/effects/native/autopaneffect.cpp +++ b/src/effects/native/autopaneffect.cpp @@ -34,9 +34,9 @@ EffectManifest AutoPanEffect::getManifest() { period->setName(QObject::tr("Period")); period->setDescription(QObject::tr("How fast the sound goes from a side to another," " following a logarithmic scale")); - period->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - period->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - period->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + period->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + period->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + period->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); period->setMinimum(0.0625); // 1 / 16 period->setMaximum(129.0); // 128 + 1 period->setDefault(3.0); @@ -48,9 +48,9 @@ EffectManifest AutoPanEffect::getManifest() { smoothing->setShortName(QObject::tr("Smooth")); smoothing->setDescription( QObject::tr("How fast the signal goes from a channel to another")); - smoothing->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - smoothing->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - smoothing->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + smoothing->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + smoothing->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + smoothing->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); smoothing->setMinimum(0.0); smoothing->setMaximum(0.5); // there are two steps per period so max is half smoothing->setDefault(0.5); @@ -62,10 +62,10 @@ EffectManifest AutoPanEffect::getManifest() { width->setId("width"); width->setName(QObject::tr("Width")); width->setDescription("How far the signal goes on the left or on the right"); - width->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - width->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - width->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - width->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + width->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + width->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + width->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + width->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); width->setMinimum(0.0); width->setMaximum(1.0); // 0.02 * sampleRate => 20ms width->setDefault(0.5); @@ -75,9 +75,9 @@ EffectManifest AutoPanEffect::getManifest() { periodUnit->setId("periodUnit"); periodUnit->setName(QObject::tr("Sync")); periodUnit->setDescription(QObject::tr("Synchronizes the period with the BPM if it can be retrieved")); - periodUnit->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - periodUnit->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - periodUnit->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + periodUnit->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + periodUnit->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + periodUnit->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); periodUnit->setDefault(1); periodUnit->setMinimum(0); periodUnit->setMaximum(1); diff --git a/src/effects/native/bitcrushereffect.cpp b/src/effects/native/bitcrushereffect.cpp index 564e2942e41a..35e5c37dbd9c 100644 --- a/src/effects/native/bitcrushereffect.cpp +++ b/src/effects/native/bitcrushereffect.cpp @@ -23,10 +23,10 @@ EffectManifest BitCrusherEffect::getManifest() { depth->setId("bit_depth"); depth->setName(QObject::tr("Bit Depth")); depth->setDescription(QObject::tr("Adjusts the bit depth of the samples.")); - depth->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - depth->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - depth->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - depth->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); depth->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::INVERTED); depth->setNeutralPointOnScale(1.0); depth->setDefault(16); @@ -40,10 +40,10 @@ EffectManifest BitCrusherEffect::getManifest() { frequency->setName(QObject::tr("Downsampling")); frequency->setShortName(QObject::tr("Down")); frequency->setDescription(QObject::tr("Adjusts the sample rate, to which the signal is downsampled.")); - frequency->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - frequency->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - frequency->setUnitsHint(EffectManifestParameter::UNITS_SAMPLERATE); - frequency->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + frequency->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + frequency->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + frequency->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE); + frequency->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); frequency->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::INVERTED); frequency->setNeutralPointOnScale(1.0); frequency->setDefault(1.0); diff --git a/src/effects/native/echoeffect.cpp b/src/effects/native/echoeffect.cpp index 2e6b86bdd659..3afa7451bf09 100644 --- a/src/effects/native/echoeffect.cpp +++ b/src/effects/native/echoeffect.cpp @@ -28,9 +28,9 @@ EffectManifest EchoEffect::getManifest() { delay->setId("delay_time"); delay->setName(QObject::tr("Delay")); delay->setDescription(QObject::tr("Delay time (seconds)")); - delay->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - delay->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - delay->setUnitsHint(EffectManifestParameter::UNITS_TIME); + delay->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + delay->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + delay->setUnitsHint(EffectManifestParameter::UnitsHint::TIME); delay->setMinimum(0.1); delay->setDefault(1.0); delay->setMaximum(EchoGroupState::kMaxDelaySeconds); @@ -40,9 +40,9 @@ EffectManifest EchoEffect::getManifest() { feedback->setName(QObject::tr("Feedback")); feedback->setDescription( QObject::tr("Amount the echo fades each time it loops")); - feedback->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - feedback->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - feedback->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + feedback->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + feedback->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + feedback->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); feedback->setMinimum(0.00); feedback->setDefault(0.5); feedback->setMaximum(1.0); @@ -54,9 +54,9 @@ EffectManifest EchoEffect::getManifest() { QObject::tr("As the ping-pong amount increases, increasing amounts " "of the echoed signal is bounced between the left and " "right speakers.")); - pingpong->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - pingpong->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - pingpong->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + pingpong->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + pingpong->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + pingpong->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); pingpong->setMinimum(0.0); pingpong->setDefault(0.0); pingpong->setMaximum(1.0); @@ -66,10 +66,10 @@ EffectManifest EchoEffect::getManifest() { send->setName(QObject::tr("Send")); send->setDescription( QObject::tr("How much of the signal to send into the delay buffer")); - send->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - send->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - send->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - send->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + send->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + send->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + send->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + send->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); send->setMinimum(0.0); send->setDefault(1.0); send->setMaximum(1.0); diff --git a/src/effects/native/equalizer_util.h b/src/effects/native/equalizer_util.h index eb37aab8d08e..a1a5e3842d53 100644 --- a/src/effects/native/equalizer_util.h +++ b/src/effects/native/equalizer_util.h @@ -13,9 +13,9 @@ class EqualizerUtil { low->setId("low"); low->setName(QObject::tr("Low")); low->setDescription(QObject::tr("Gain for Low Filter")); - low->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - low->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - low->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + low->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); low->setNeutralPointOnScale(0.5); low->setDefault(1.0); low->setMinimum(0); @@ -25,9 +25,9 @@ class EqualizerUtil { killLow->setId("killLow"); killLow->setName(QObject::tr("Kill Low")); killLow->setDescription(QObject::tr("Kill the Low Filter")); - killLow->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - killLow->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - killLow->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + killLow->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + killLow->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + killLow->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); killLow->setDefault(0); killLow->setMinimum(0); killLow->setMaximum(1); @@ -36,9 +36,9 @@ class EqualizerUtil { mid->setId("mid"); mid->setName(QObject::tr("Mid")); mid->setDescription(QObject::tr("Gain for Mid Filter")); - mid->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - mid->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - mid->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + mid->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + mid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + mid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); mid->setNeutralPointOnScale(0.5); mid->setDefault(1.0); mid->setMinimum(0); @@ -48,9 +48,9 @@ class EqualizerUtil { killMid->setId("killMid"); killMid->setName(QObject::tr("Kill Mid")); killMid->setDescription(QObject::tr("Kill the Mid Filter")); - killMid->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - killMid->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - killMid->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + killMid->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + killMid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + killMid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); killMid->setDefault(0); killMid->setMinimum(0); killMid->setMaximum(1); @@ -59,9 +59,9 @@ class EqualizerUtil { high->setId("high"); high->setName(QObject::tr("High")); high->setDescription(QObject::tr("Gain for High Filter")); - high->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - high->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - high->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + high->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + high->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + high->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); high->setNeutralPointOnScale(0.5); high->setDefault(1.0); high->setMinimum(0); @@ -71,9 +71,9 @@ class EqualizerUtil { killHigh->setId("killHigh"); killHigh->setName(QObject::tr("Kill High")); killHigh->setDescription(QObject::tr("Kill the High Filter")); - killHigh->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - killHigh->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - killHigh->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + killHigh->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + killHigh->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + killHigh->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); killHigh->setDefault(0); killHigh->setMinimum(0); killHigh->setMaximum(1); diff --git a/src/effects/native/filtereffect.cpp b/src/effects/native/filtereffect.cpp index ddf5fff934b0..00ff1d40c752 100644 --- a/src/effects/native/filtereffect.cpp +++ b/src/effects/native/filtereffect.cpp @@ -25,10 +25,10 @@ EffectManifest FilterEffect::getManifest() { lpf->setId("lpf"); lpf->setName(QObject::tr("LPF")); lpf->setDescription(QObject::tr("Corner frequency ratio of the low pass filter")); - lpf->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - lpf->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - lpf->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - lpf->setDefaultLinkType(EffectManifestParameter::LINK_LINKED_LEFT); + lpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + lpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + lpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_LEFT); lpf->setNeutralPointOnScale(1); lpf->setDefault(kMaxCorner); lpf->setMinimum(kMinCorner); @@ -39,9 +39,9 @@ EffectManifest FilterEffect::getManifest() { q->setName(QObject::tr("Resonance")); q->setShortName(QObject::tr("Q")); q->setDescription(QObject::tr("Resonance of the filters, default = Flat top")); - q->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - q->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - q->setUnitsHint(EffectManifestParameter::UNITS_SAMPLERATE); + q->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + q->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + q->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE); q->setDefault(0.707106781); // 0.707106781 = Butterworth q->setMinimum(0.4); q->setMaximum(4.0); @@ -50,10 +50,10 @@ EffectManifest FilterEffect::getManifest() { hpf->setId("hpf"); hpf->setName(QObject::tr("HPF")); hpf->setDescription(QObject::tr("Corner frequency ratio of the high pass filter")); - hpf->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - hpf->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - hpf->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - hpf->setDefaultLinkType(EffectManifestParameter::LINK_LINKED_RIGHT); + hpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + hpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + hpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_RIGHT); hpf->setNeutralPointOnScale(0.0); hpf->setDefault(kMinCorner); hpf->setMinimum(kMinCorner); diff --git a/src/effects/native/flangereffect.cpp b/src/effects/native/flangereffect.cpp index 079cb436349a..b54a42363700 100644 --- a/src/effects/native/flangereffect.cpp +++ b/src/effects/native/flangereffect.cpp @@ -28,9 +28,9 @@ EffectManifest FlangerEffect::getManifest() { delay->setId("delay"); delay->setName(QObject::tr("Delay")); delay->setDescription(QObject::tr("Sets the value for the delay length.")); - delay->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - delay->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - delay->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + delay->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + delay->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + delay->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); delay->setDefault(3333.3); delay->setMinimum(50.0); delay->setMaximum(10000.0); @@ -39,9 +39,9 @@ EffectManifest FlangerEffect::getManifest() { period->setId("period"); period->setName(QObject::tr("Period")); period->setDescription(QObject::tr("Controls the speed of the effect.")); - period->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - period->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - period->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + period->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + period->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + period->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); period->setDefault(666666.6); period->setMinimum(50000.0); period->setMaximum(2000000.0); @@ -50,10 +50,10 @@ EffectManifest FlangerEffect::getManifest() { depth->setId("depth"); depth->setName(QObject::tr("Depth")); depth->setDescription(QObject::tr("Controls the intensity of the effect.")); - depth->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - depth->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - depth->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - depth->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); depth->setDefault(0.0); depth->setMinimum(0.0); depth->setMaximum(1.0); diff --git a/src/effects/native/graphiceqeffect.cpp b/src/effects/native/graphiceqeffect.cpp index edbb3ce95bb0..2279af1d5bd6 100644 --- a/src/effects/native/graphiceqeffect.cpp +++ b/src/effects/native/graphiceqeffect.cpp @@ -29,9 +29,9 @@ EffectManifest GraphicEQEffect::getManifest() { low->setId(QString("low")); low->setName(QString("%1 Hz").arg(centerFrequencies[0])); low->setDescription(QObject::tr("Gain for Low Filter")); - low->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - low->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - low->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + low->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); low->setNeutralPointOnScale(0.5); low->setDefault(0); low->setMinimum(-12); @@ -49,9 +49,9 @@ EffectManifest GraphicEQEffect::getManifest() { mid->setId(QString("mid%1").arg(i)); mid->setName(paramName); mid->setDescription(QObject::tr("Gain for Band Filter %1").arg(i)); - mid->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - mid->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - mid->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + mid->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + mid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + mid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); mid->setNeutralPointOnScale(0.5); mid->setDefault(0); mid->setMinimum(-12); @@ -62,9 +62,9 @@ EffectManifest GraphicEQEffect::getManifest() { high->setId(QString("high")); high->setName(QString("%1 kHz").arg(centerFrequencies[7] / 1000)); high->setDescription(QObject::tr("Gain for High Filter")); - high->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - high->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - high->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + high->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + high->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + high->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); high->setDefault(0); high->setMinimum(-12); high->setMaximum(12); diff --git a/src/effects/native/loudnesscontoureffect.cpp b/src/effects/native/loudnesscontoureffect.cpp index d945fdec3d72..c180938287fc 100644 --- a/src/effects/native/loudnesscontoureffect.cpp +++ b/src/effects/native/loudnesscontoureffect.cpp @@ -37,10 +37,10 @@ EffectManifest LoudnessContourEffect::getManifest() { loudness->setName(QObject::tr("Loudness")); loudness->setDescription( QObject::tr("Set the gain of the applied loudness contour")); - loudness->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - loudness->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - loudness->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - loudness->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + loudness->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + loudness->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + loudness->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + loudness->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); loudness->setNeutralPointOnScale(1); loudness->setDefault(-kMaxLoGain / 2); loudness->setMinimum(-kMaxLoGain); @@ -50,9 +50,9 @@ EffectManifest LoudnessContourEffect::getManifest() { useGain->setId("useGain"); useGain->setName(QObject::tr("Use Gain")); useGain->setDescription(QObject::tr("Follow Gain Knob")); - useGain->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - useGain->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - useGain->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + useGain->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + useGain->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + useGain->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); useGain->setDefault(0); useGain->setMinimum(0); useGain->setMaximum(1); diff --git a/src/effects/native/moogladder4filtereffect.cpp b/src/effects/native/moogladder4filtereffect.cpp index 1807922228cc..01272d09f288 100644 --- a/src/effects/native/moogladder4filtereffect.cpp +++ b/src/effects/native/moogladder4filtereffect.cpp @@ -27,10 +27,10 @@ EffectManifest MoogLadder4FilterEffect::getManifest() { lpf->setId("lpf"); lpf->setName(QObject::tr("LPF")); lpf->setDescription(QObject::tr("Corner frequency ratio of the low pass filter")); - lpf->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - lpf->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - lpf->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - lpf->setDefaultLinkType(EffectManifestParameter::LINK_LINKED_LEFT); + lpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + lpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + lpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_LEFT); lpf->setNeutralPointOnScale(1); lpf->setDefault(kMaxCorner); lpf->setMinimum(kMinCorner); @@ -41,9 +41,9 @@ EffectManifest MoogLadder4FilterEffect::getManifest() { q->setName(QObject::tr("Resonance")); q->setShortName(QObject::tr("Res")); q->setDescription(QObject::tr("Resonance of the filters. 4 = self oscillating")); - q->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - q->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - q->setUnitsHint(EffectManifestParameter::UNITS_SAMPLERATE); + q->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + q->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + q->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE); q->setMinimum(0.0); q->setMaximum(4.0); q->setDefault(1.0); @@ -52,10 +52,10 @@ EffectManifest MoogLadder4FilterEffect::getManifest() { hpf->setId("hpf"); hpf->setName(QObject::tr("HPF")); hpf->setDescription(QObject::tr("Corner frequency ratio of the high pass filter")); - hpf->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC); - hpf->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - hpf->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - hpf->setDefaultLinkType(EffectManifestParameter::LINK_LINKED_RIGHT); + hpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC); + hpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + hpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_RIGHT); hpf->setNeutralPointOnScale(0.0); hpf->setDefault(kMinCorner); hpf->setMinimum(kMinCorner); diff --git a/src/effects/native/phasereffect.cpp b/src/effects/native/phasereffect.cpp index 529d4b5d635b..e767d7263569 100644 --- a/src/effects/native/phasereffect.cpp +++ b/src/effects/native/phasereffect.cpp @@ -27,9 +27,9 @@ EffectManifest PhaserEffect::getManifest() { frequency->setId("lfo_frequency"); frequency->setName(QObject::tr("Rate")); frequency->setDescription(QObject::tr("Controls the speed of the low frequency oscilator.")); - frequency->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - frequency->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - frequency->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + frequency->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + frequency->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + frequency->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); frequency->setMinimum(0.0); frequency->setMaximum(5.0); frequency->setDefault(2.5); @@ -38,9 +38,9 @@ EffectManifest PhaserEffect::getManifest() { range->setId("range"); range->setName(QObject::tr("Range")); range->setDescription(QObject::tr("Controls the frequency range across which the notches sweep.")); - range->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - range->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - range->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + range->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + range->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + range->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); range->setMinimum(0.05); range->setMaximum(0.95); range->setDefault(0.05); @@ -49,9 +49,9 @@ EffectManifest PhaserEffect::getManifest() { stages->setId("stages"); stages->setName(QObject::tr("Stages")); stages->setDescription(QObject::tr("Sets number of stages.")); - stages->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - stages->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - stages->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + stages->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + stages->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + stages->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); stages->setMinimum(1.0); stages->setMaximum(6.0); stages->setDefault(3.5); @@ -60,9 +60,9 @@ EffectManifest PhaserEffect::getManifest() { fb->setId("feedback"); fb->setName(QObject::tr("Feedback")); fb->setDescription(QObject::tr("Controls how much of the output signal is looped")); - fb->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - fb->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - fb->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + fb->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + fb->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + fb->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); fb->setMinimum(-0.95); fb->setMaximum(0.95); fb->setDefault(0.0); @@ -71,10 +71,10 @@ EffectManifest PhaserEffect::getManifest() { depth->setId("depth"); depth->setName(QObject::tr("Depth")); depth->setDescription("Controls the intensity of the effect."); - depth->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - depth->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - depth->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - depth->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); depth->setMinimum(0.5); depth->setMaximum(1.0); depth->setDefault(0.0); @@ -83,9 +83,9 @@ EffectManifest PhaserEffect::getManifest() { stereo->setId("stereo"); stereo->setName(QObject::tr("Stereo")); stereo->setDescription(QObject::tr("Enables/disables stereo")); - stereo->setControlHint(EffectManifestParameter::CONTROL_TOGGLE_STEPPING); - stereo->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - stereo->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + stereo->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING); + stereo->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + stereo->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); stereo->setMinimum(0); stereo->setMaximum(1); stereo->setDefault(0); diff --git a/src/effects/native/reverbeffect.cpp b/src/effects/native/reverbeffect.cpp index 8e3f606bc900..e946d7d21caf 100644 --- a/src/effects/native/reverbeffect.cpp +++ b/src/effects/native/reverbeffect.cpp @@ -28,9 +28,9 @@ EffectManifest ReverbEffect::getManifest() { decay->setId("decay"); decay->setName(QObject::tr("Decay")); decay->setDescription(QObject::tr("Lower decay values cause reverberations to die out more quickly.")); - decay->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - decay->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - decay->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + decay->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + decay->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + decay->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); decay->setMinimum(0); decay->setDefault(0.5); decay->setMaximum(1); @@ -41,9 +41,9 @@ EffectManifest ReverbEffect::getManifest() { bandwidth->setShortName(QObject::tr("BW")); bandwidth->setDescription(QObject::tr("Bandwidth of the low pass filter at the input. " "Higher values result in less attenuation of high frequencies.")); - bandwidth->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - bandwidth->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - bandwidth->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + bandwidth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + bandwidth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + bandwidth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); bandwidth->setMinimum(0); bandwidth->setDefault(1); bandwidth->setMaximum(1); @@ -53,9 +53,9 @@ EffectManifest ReverbEffect::getManifest() { damping->setName(QObject::tr("Damping")); damping->setDescription(QObject::tr("Higher damping values cause " "high frequencies to decay more quickly than low frequencies.")); - damping->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - damping->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - damping->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + damping->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + damping->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + damping->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); damping->setMinimum(0); damping->setDefault(0); damping->setMaximum(1); @@ -64,10 +64,10 @@ EffectManifest ReverbEffect::getManifest() { send->setId("send_amount"); send->setName(QObject::tr("Send")); send->setDescription(QObject::tr("How much of the signal to send to the effect")); - send->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - send->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - send->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - send->setDefaultLinkType(EffectManifestParameter::LINK_LINKED); + send->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + send->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + send->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + send->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED); send->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::NOT_INVERTED); send->setMinimum(0); send->setDefault(0); diff --git a/src/effects/native/threebandbiquadeqeffect.cpp b/src/effects/native/threebandbiquadeqeffect.cpp index 2e30cf31c1bb..200c16b1b390 100644 --- a/src/effects/native/threebandbiquadeqeffect.cpp +++ b/src/effects/native/threebandbiquadeqeffect.cpp @@ -69,7 +69,7 @@ EffectManifest ThreeBandBiquadEQEffect::getManifest() { for (auto&& parameter : manifest.parameters()) { if (parameter.id() == "low" || parameter.id() == "mid" || parameter.id() == "high") { - parameter.setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); + parameter.setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); parameter.setMaximum(2.0); } } diff --git a/src/mixxx.cpp b/src/mixxx.cpp index f901c9424f1d..e88c7fc547dc 100644 --- a/src/mixxx.cpp +++ b/src/mixxx.cpp @@ -187,8 +187,8 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) { NativeBackend* pNativeBackend = new NativeBackend(m_pEffectsManager); m_pEffectsManager->addEffectsBackend(pNativeBackend); - // Sets up the default EffectChains and EffectRacks (long) - m_pEffectsManager->setupDefaults(); + // Sets up the EffectChains and EffectRacks (long) + m_pEffectsManager->setup(); launchProgress(8); diff --git a/src/preferences/dialog/dlgprefeq.cpp b/src/preferences/dialog/dlgprefeq.cpp index 01ebfe26d8e4..cc8621061c6e 100644 --- a/src/preferences/dialog/dlgprefeq.cpp +++ b/src/preferences/dialog/dlgprefeq.cpp @@ -184,7 +184,8 @@ static bool isMasterEQ(const EffectManifest& pManifest) { static bool hasSuperKnobLinking(const EffectManifest& pManifest) { for (const auto& pParameterManifest : pManifest.parameters()) { - if (pParameterManifest.defaultLinkType() != EffectManifestParameter::LINK_NONE) { + if (pParameterManifest.defaultLinkType() != + EffectManifestParameter::LinkType::NONE) { return true; } } diff --git a/src/test/effectchainslottest.cpp b/src/test/effectchainslottest.cpp index 7b44e8e39e1d..7258e90985da 100644 --- a/src/test/effectchainslottest.cpp +++ b/src/test/effectchainslottest.cpp @@ -36,7 +36,7 @@ TEST_F(EffectChainSlotTest, ChainSlotMirrorsLoadedChain) { int iChainNumber = 0; StandardEffectRackPointer pRack = m_pEffectsManager->addStandardEffectRack(); - EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(); + EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(pChain, QDomElement()); pSlot->clear(); QString group = StandardEffectRack::formatEffectChainSlotGroupString( @@ -89,7 +89,7 @@ TEST_F(EffectChainSlotTest, ChainSlotMirrorsLoadedChain_StartsWithChainLoaded) { int iChainNumber = 0; StandardEffectRackPointer pRack = m_pEffectsManager->addStandardEffectRack(); - EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(); + EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(pChain, QDomElement()); QString group = StandardEffectRack::formatEffectChainSlotGroupString( iRackNumber, iChainNumber); EXPECT_DOUBLE_EQ(1.0, ControlObject::get(ConfigKey(group, "loaded"))); @@ -103,7 +103,7 @@ TEST_F(EffectChainSlotTest, ChainSlotMirrorsLoadedChain_Clear) { int iChainNumber = 0; StandardEffectRackPointer pRack = m_pEffectsManager->addStandardEffectRack(); - EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(); + EffectChainSlotPointer pSlot = pRack->addEffectChainSlot(pChain, QDomElement()); // Clear the default chain. pSlot->clear(); diff --git a/src/test/effectslottest.cpp b/src/test/effectslottest.cpp index 1346e32ad433..8a4f27c4e532 100644 --- a/src/test/effectslottest.cpp +++ b/src/test/effectslottest.cpp @@ -39,7 +39,7 @@ TEST_F(EffectSlotTest, ControlsReflectSlotState) { int iEffectNumber = 0; StandardEffectRackPointer pRack = m_pEffectsManager->addStandardEffectRack(); - EffectChainSlotPointer pChainSlot = pRack->addEffectChainSlot(); + EffectChainSlotPointer pChainSlot = pRack->addEffectChainSlot(pChain, QDomElement()); // StandardEffectRack::addEffectChainSlot automatically adds 4 effect // slots. In the future we will probably remove this so this will just start // segfaulting. diff --git a/src/test/metaknob_link_test.cpp b/src/test/metaknob_link_test.cpp index ee92cf018455..ce6dc813d98c 100644 --- a/src/test/metaknob_link_test.cpp +++ b/src/test/metaknob_link_test.cpp @@ -29,7 +29,7 @@ class MetaLinkTest : public BaseEffectTest { int iEffectNumber = 0; StandardEffectRackPointer pRack = m_pEffectsManager->addStandardEffectRack(); - m_pChainSlot = pRack->addEffectChainSlot(); + m_pChainSlot = pRack->addEffectChainSlot(pChain, QDomElement()); // StandardEffectRack::addEffectChainSlot automatically adds 4 effect // slots. In the future we will probably remove this so this will just // start segfaulting. @@ -46,9 +46,9 @@ class MetaLinkTest : public BaseEffectTest { low->setId("low"); low->setName(QObject::tr("Low")); low->setDescription(QObject::tr("Gain for Low Filter")); - low->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - low->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - low->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + low->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); low->setNeutralPointOnScale(0.25); low->setDefault(1.0); low->setMinimum(0); @@ -97,7 +97,8 @@ TEST_F(MetaLinkTest, LinkDefault) { TEST_F(MetaLinkTest, LinkLinked) { m_pEffectSlot->syncSofttakeover(); - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED)); m_pEffectSlot->slotEffectMetaParameter(1.0); EXPECT_EQ(1.0, m_pControlValue->get()); m_pEffectSlot->slotEffectMetaParameter(0.5); @@ -106,7 +107,8 @@ TEST_F(MetaLinkTest, LinkLinked) { TEST_F(MetaLinkTest, LinkLinkedInverse) { m_pEffectSlot->syncSofttakeover(); - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED)); m_pControlLinkInverse->set(1.0); m_pEffectSlot->slotEffectMetaParameter(0.0); EXPECT_EQ(1.0, m_pControlValue->get()); @@ -115,7 +117,8 @@ TEST_F(MetaLinkTest, LinkLinkedInverse) { } TEST_F(MetaLinkTest, MetaToParameter_Softtakeover_EffectEnabled) { - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED)); // Soft takeover should only occur when the effect is enabled. m_pEffectSlot->slotEnabled(1.0); @@ -139,7 +142,8 @@ TEST_F(MetaLinkTest, MetaToParameter_Softtakeover_EffectDisabled) { // Soft takeover should not occur when the effect is disabled; // parameter values should always jump to match the metaknob. // Effects are disabled by default. - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED)); m_pEffectSlot->slotEffectMetaParameter(1.0); EXPECT_EQ(1.0, m_pControlValue->get()); @@ -208,9 +212,9 @@ TEST_F(MetaLinkTest, HalfLinkTakeover) { low->setId("low"); low->setName(QObject::tr("Low")); low->setDescription(QObject::tr("Gain for Low Filter (neutral at 1.0)")); - low->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); - low->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); - low->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + low->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); low->setNeutralPointOnScale(1.0); low->setDefault(1.0); low->setMinimum(0); @@ -239,7 +243,8 @@ TEST_F(MetaLinkTest, HalfLinkTakeover) { // we should see the control change as expected. m_pEffectSlot->slotEffectMetaParameter(0.5); m_pControlValue->set(1.0); - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED_LEFT); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED_LEFT)); m_pEffectSlot->syncSofttakeover(); m_pEffectSlot->slotEffectMetaParameter(newParam); EXPECT_EQ(newParam * 2.0, m_pControlValue->get()); @@ -247,7 +252,8 @@ TEST_F(MetaLinkTest, HalfLinkTakeover) { // This tolerance change should also work for linked-right controls. m_pEffectSlot->slotEffectMetaParameter(0.5); m_pControlValue->set(1.0); - m_pControlLinkType->set(EffectManifestParameter::LINK_LINKED_RIGHT); + m_pControlLinkType->set( + static_cast(EffectManifestParameter::LinkType::LINKED_RIGHT)); m_pEffectSlot->syncSofttakeover(); newParam = 0.5 + SoftTakeover::kDefaultTakeoverThreshold * 1.5; m_pEffectSlot->slotEffectMetaParameter(newParam); diff --git a/src/util/xml.cpp b/src/util/xml.cpp index 32ae840e4389..98f8b51062eb 100644 --- a/src/util/xml.cpp +++ b/src/util/xml.cpp @@ -4,13 +4,19 @@ #include "util/xml.h" #include "errordialoghandler.h" -int XmlParse::selectNodeInt(const QDomNode& nodeHeader, const QString& sNode) { - return selectNode(nodeHeader, sNode).toElement().text().toInt(); +int XmlParse::selectNodeInt(const QDomNode& nodeHeader, + const QString& sNode, bool* ok) { + return selectNode(nodeHeader, sNode).toElement().text().toInt(ok); } float XmlParse::selectNodeFloat(const QDomNode& nodeHeader, - const QString& sNode) { - return selectNode(nodeHeader, sNode).toElement().text().toFloat(); + const QString& sNode, bool* ok) { + return selectNode(nodeHeader, sNode).toElement().text().toFloat(ok); +} + +double XmlParse::selectNodeDouble(const QDomNode& nodeHeader, + const QString& sNode, bool* ok) { + return selectNode(nodeHeader, sNode).toElement().text().toDouble(ok); } QDomNode XmlParse::selectNode(const QDomNode& nodeHeader, diff --git a/src/util/xml.h b/src/util/xml.h index d9420c3a15b2..b736edb6fe5d 100644 --- a/src/util/xml.h +++ b/src/util/xml.h @@ -21,13 +21,19 @@ class XmlParse { // parses the text value of its children as an integer. Returns 0 if sNode // is not found in nodeHeader's children. static int selectNodeInt(const QDomNode& nodeHeader, - const QString& sNode); + const QString& sNode, bool* ok = 0); // Searches for an element named sNode in the children of nodeHeader and // parses the text value of its children as a float. Returns 0.0f if sNode // is not found in nodeHeader's children. static float selectNodeFloat(const QDomNode& nodeHeader, - const QString& sNode); + const QString& sNode, bool* ok = 0); + + // Searches for an element named sNode in the children of nodeHeader and + // parses the text value of its children as a double. Returns 0.0 if sNode + // is not found in nodeHeader's children. + static double selectNodeDouble(const QDomNode& nodeHeader, + const QString& sNode, bool* ok = 0); // Searches for an element named sNode in the children of nodeHeader and // returns the text value of its children. Returns the empty string if sNode