Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d7b45ea
implement effect saving to/loading from XML
Be-ing Dec 25, 2016
d826eca
save/load effect parameter state to XML on shutdown/startup
Be-ing Dec 25, 2016
50cc903
add Mixxx version to effects.xml
Be-ing Dec 27, 2016
3257996
fix effects tests
Be-ing Jan 19, 2017
49c3d74
make effect parameters loaded from XML actually change the sound
Be-ing Dec 28, 2016
211e875
organize EffectParameterSlot contructor
Be-ing Dec 28, 2016
b7bfd32
small code cleanup
Be-ing Dec 28, 2016
80a0e96
define a constant for the number of effects
Be-ing Jan 3, 2017
23273a0
version effects.xml on its own terms instead of by Mixxx version
Be-ing Jan 3, 2017
378d5b5
fix segfault when switching effect chains
Be-ing Jan 4, 2017
19d32e0
move effect XML element names to separate header file
Be-ing Jan 7, 2017
86ff6e4
save superknob value to XML
Be-ing Jan 7, 2017
9a665ed
save metaknob value to XML
Be-ing Jan 7, 2017
83b8eb6
save all parameter types as a generic <Parameter> element in XML
Be-ing Jan 28, 2017
a4eb460
Merge remote-tracking branch 'upstream/master' into effect_xml
Be-ing Feb 5, 2017
efa91e7
save metaknob link type as a string in XML
Be-ing Feb 5, 2017
4886ec5
save effect chain insertion type as a string in XML
Be-ing Feb 6, 2017
4d11f2e
make strings for LinkType match enum names used for LinkType
Be-ing Feb 6, 2017
e6df014
convert EffectManifestParameter LinkType to enum class
Be-ing Feb 6, 2017
9e705c0
save effect XML schema version as attribute of root element
Be-ing Feb 6, 2017
437d5ac
replace remaining enums in EffectManifestParameter with enum classes
Be-ing Feb 6, 2017
d71af08
Merge remote-tracking branch 'upstream/master' into effect_xml
Be-ing Feb 6, 2017
17d3d57
fix metaknob_link_test.cpp build
Be-ing Feb 6, 2017
9baae8e
avoid reusing loadValuesFromXml method name for slot classes at diffe…
Be-ing Feb 9, 2017
b687935
small refactor to make toXML/loadEffectSlotToXML symmetrical
Be-ing Feb 11, 2017
54fd98b
check for valid value in effect XML file, otherwise keep default
Be-ing Feb 11, 2017
494d36f
toXML -> toXml
Be-ing Feb 11, 2017
745d2bb
support default values for persistent ControlPotmeters
Be-ing Feb 12, 2017
ab35709
make dry/wet knob persistent
Be-ing Feb 12, 2017
ec03b67
fix Windows build
Be-ing Apr 3, 2017
f54a933
Merge remote-tracking branch 'upstream/master' into effect_xml
Be-ing Apr 3, 2017
dc8e1b1
fix Windows build
Be-ing Apr 9, 2017
3626ebe
Merge remote-tracking branch 'upstream/master' into effect_xml
Be-ing Apr 10, 2017
6fe1268
Merge remote-tracking branch 'upstream/master' into effect_xml
Be-ing Apr 18, 2017
94556ff
add missing function parameter
Be-ing Apr 18, 2017
7cd7a67
clarifying comment
Be-ing Apr 18, 2017
5ee27df
organize EffectParameterSlot constructor & destructor
Be-ing Apr 18, 2017
d132b18
efficiently check for empty XML elements
Be-ing Apr 18, 2017
841d5ab
keep effect parameters in order in XML file
Be-ing Apr 18, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/control/controleffectknob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions src/control/controlpotmeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/control/controlpotmeter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
38 changes: 11 additions & 27 deletions src/effects/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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 <Effect/> 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;
}
3 changes: 1 addition & 2 deletions src/effects/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
34 changes: 34 additions & 0 deletions src/effects/effectbuttonparameterslot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}

Expand Down Expand Up @@ -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.
}
}
3 changes: 3 additions & 0 deletions src/effects/effectbuttonparameterslot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
60 changes: 25 additions & 35 deletions src/effects/effectchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -214,15 +224,14 @@ 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<unsigned int>(m_effects.size())) {
if (pEffect.isNull()) {
return;
}
m_effects.append(EffectPointer());
}


EffectPointer pOldEffect = m_effects[effectSlotNumber];
if (!pOldEffect.isNull()) {
if (m_bAddedToEngine) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/effects/effectchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading