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"
+ "" + EffectXml::Root + ">\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