Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effect Button Parameters #281

Merged
merged 8 commits into from
Jul 21, 2014
4 changes: 4 additions & 0 deletions build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,9 @@ def sources(self, build):
"effects/effectrack.cpp",
"effects/effectchainslot.cpp",
"effects/effectslot.cpp",
"effects/effectparameterslotbase.cpp",
"effects/effectparameterslot.cpp",
"effects/effectbuttonparameterslot.cpp",

"effects/effectsmanager.cpp",
"effects/effectchainmanager.cpp",
Expand Down Expand Up @@ -709,6 +711,8 @@ def sources(self, build):
"widget/weffectchain.cpp",
"widget/weffect.cpp",
"widget/weffectparameter.cpp",
"widget/weffectbuttonparameter.cpp",
"widget/weffectparameterbase.cpp",
"widget/wtime.cpp",
"widget/wkey.cpp",
"widget/wcombobox.cpp",
Expand Down
60 changes: 60 additions & 0 deletions src/effects/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ Effect::Effect(QObject* pParent, EffectsManager* pEffectsManager,
}
m_parametersById[parameter.id()] = pParameter;
}

foreach (const EffectManifestParameter& parameter, m_manifest.buttonParameters()) {
EffectParameter* pParameter = new EffectParameter(
this, pEffectsManager, m_buttonParameters.size(), parameter);
m_buttonParameters.append(pParameter);
if (m_buttonParametersById.contains(parameter.id())) {
qWarning() << debugString() << "WARNING: Loaded EffectManifest that had parameters with duplicate IDs. Dropping one of them.";
}
m_buttonParametersById[parameter.id()] = pParameter;
}
}

Effect::~Effect() {
Expand All @@ -37,6 +47,11 @@ Effect::~Effect() {
m_parameters[i] = NULL;
delete pParameter;
}
for (int i = 0; i < m_buttonParameters.size(); ++i) {
EffectParameter* pParameter = m_buttonParameters.at(i);
m_buttonParameters[i] = NULL;
delete pParameter;
}
}

void Effect::addToEngine(EngineEffectChain* pChain, int iIndex) {
Expand All @@ -50,6 +65,10 @@ void Effect::addToEngine(EngineEffectChain* pChain, int iIndex) {
foreach (EffectParameter* pParameter, m_parameters) {
pParameter->addToEngine();
}

foreach (EffectParameter* pParameter, m_buttonParameters) {
pParameter->addToEngine();
}
}

void Effect::removeFromEngine(EngineEffectChain* pChain, int iIndex) {
Expand All @@ -63,6 +82,10 @@ void Effect::removeFromEngine(EngineEffectChain* pChain, int iIndex) {
foreach (EffectParameter* pParameter, m_parameters) {
pParameter->removeFromEngine();
}

foreach (EffectParameter* pParameter, m_buttonParameters) {
pParameter->removeFromEngine();
}
}

void Effect::updateEngineState() {
Expand All @@ -73,6 +96,10 @@ void Effect::updateEngineState() {
foreach (EffectParameter* pParameter, m_parameters) {
pParameter->updateEngineState();
}

foreach (EffectParameter* pParameter, m_buttonParameters) {
pParameter->updateEngineState();
}
}

EngineEffect* Effect::getEngineEffect() {
Expand Down Expand Up @@ -110,6 +137,10 @@ unsigned int Effect::numParameters() const {
return m_parameters.size();
}

unsigned int Effect::numButtonParameters() const {
return m_buttonParameters.size();
}

EffectParameter* Effect::getParameterById(const QString& id) const {
EffectParameter* pParameter = m_parametersById.value(id, NULL);
if (pParameter == NULL) {
Expand All @@ -119,12 +150,27 @@ EffectParameter* Effect::getParameterById(const QString& id) const {
return pParameter;
}

EffectParameter* Effect::getButtonParameterById(const QString& id) const {
EffectParameter* pParameter = m_buttonParametersById.value(id, NULL);
if (pParameter == NULL) {
qWarning() << debugString() << "getParameterById"
<< "WARNING: parameter for id does not exist:" << id;
}
return pParameter;
}

EffectParameter* Effect::getParameter(unsigned int parameterNumber) {
// It's normal to ask for a parameter that doesn't exist. Callers must check
// for NULL.
return m_parameters.value(parameterNumber, NULL);
}

EffectParameter* Effect::getButtonParameter(unsigned int parameterNumber) {
// It's normal to ask for a parameter that doesn't exist. Callers must check
// for NULL.
return m_buttonParameters.value(parameterNumber, NULL);
}

QDomElement Effect::toXML(QDomDocument* doc) const {
QDomElement element = doc->createElement("Effect");
XmlParse::addElement(*doc, element, "Id", m_manifest.id());
Expand All @@ -144,6 +190,20 @@ QDomElement Effect::toXML(QDomDocument* doc) const {
}
element.appendChild(parameters);

QDomElement buttonParameters = doc->createElement("ButtonParameters");
foreach (EffectParameter* pParameter, m_buttonParameters) {
const EffectManifestParameter& parameterManifest =
pParameter->manifest();
QDomElement parameter = doc->createElement("ButtonParameter");
XmlParse::addElement(*doc, parameter, "Id", parameterManifest.id());
// TODO(rryan): Do smarter QVariant formatting?
XmlParse::addElement(*doc, parameter, "Value",
pParameter->getValue().toString());
// TODO(rryan): Output link state, etc.
buttonParameters.appendChild(parameter);
}
element.appendChild(buttonParameters);

return element;
}

Expand Down
5 changes: 5 additions & 0 deletions src/effects/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ class Effect : public QObject {
const EffectManifest& getManifest() const;

unsigned int numParameters() const;
unsigned int numButtonParameters() const;
EffectParameter* getParameter(unsigned int parameterNumber);
EffectParameter* getButtonParameter(unsigned int parameterNumber);
EffectParameter* getParameterById(const QString& id) const;
EffectParameter* getButtonParameterById(const QString& id) const;

void setEnabled(bool enabled);
bool enabled() const;
Expand Down Expand Up @@ -65,6 +68,8 @@ class Effect : public QObject {
bool m_bEnabled;
QList<EffectParameter*> m_parameters;
QMap<QString, EffectParameter*> m_parametersById;
QList<EffectParameter*> m_buttonParameters;
QMap<QString, EffectParameter*> m_buttonParametersById;

DISALLOW_COPY_AND_ASSIGN(Effect);
};
Expand Down
132 changes: 132 additions & 0 deletions src/effects/effectbuttonparameterslot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include <QtDebug>

#include "controleffectknob.h"
#include "effects/effectbuttonparameterslot.h"
#include "controlobject.h"
#include "controlpushbutton.h"

EffectButtonParameterSlot::EffectButtonParameterSlot(const unsigned int iRackNumber,
const unsigned int iChainNumber,
const unsigned int iSlotNumber,
const unsigned int iParameterNumber)
: EffectParameterSlotBase(iRackNumber, iChainNumber, iSlotNumber,
iParameterNumber) {
QString itemPrefix = formatItemPrefix(iParameterNumber);
m_pControlLoaded = new ControlObject(
ConfigKey(m_group, itemPrefix + QString("_loaded")));
m_pControlLinkType = new ControlPushButton(
ConfigKey(m_group, itemPrefix + QString("_link_type")));
m_pControlLinkType->setButtonMode(ControlPushButton::TOGGLE);
m_pControlLinkType->setStates(EffectManifestParameter::NUM_LINK_TYPES);
m_pControlValue = new ControlPushButton(
ConfigKey(m_group, itemPrefix));
m_pControlValue->setButtonMode(ControlPushButton::POWERWINDOW);
m_pControlType = new ControlObject(
ConfigKey(m_group, itemPrefix + QString("_type")));

connect(m_pControlLinkType, SIGNAL(valueChanged(double)),
this, SLOT(slotLinkType(double)));
connect(m_pControlValue, SIGNAL(valueChanged(double)),
this, SLOT(slotValueChanged(double)));

// Read-only controls.
m_pControlType->connectValueChangeRequest(
this, SLOT(slotValueType(double)), Qt::AutoConnection);
m_pControlLoaded->connectValueChangeRequest(
this, SLOT(slotLoaded(double)), Qt::AutoConnection);

clear();
}

EffectButtonParameterSlot::~EffectButtonParameterSlot() {
//qDebug() << debugString() << "destroyed";
delete m_pControlValue;
}

void EffectButtonParameterSlot::loadEffect(EffectPointer pEffect) {
//qDebug() << debugString() << "loadEffect" << (pEffect ? pEffect->getManifest().name() : "(null)");
clear();
if (pEffect) {
m_pEffect = pEffect;
// Returns null if it doesn't have a parameter for that number
m_pEffectParameter = pEffect->getButtonParameter(m_iParameterNumber);

if (m_pEffectParameter) {
//qDebug() << debugString() << "Loading effect parameter" << m_pEffectParameter->name();
double dValue = m_pEffectParameter->getValue().toDouble();
double dMinimum = m_pEffectParameter->getMinimum().toDouble();
double dMinimumLimit = dMinimum; // TODO(rryan) expose limit from EffectParameter
double dMaximum = m_pEffectParameter->getMaximum().toDouble();
double dMaximumLimit = dMaximum; // TODO(rryan) expose limit from EffectParameter
double dDefault = m_pEffectParameter->getDefault().toDouble();

if (dValue > dMaximum || dValue < dMinimum ||
dMinimum < dMinimumLimit || dMaximum > dMaximumLimit ||
dDefault > dMaximum || dDefault < dMinimum) {
qWarning() << debugString() << "WARNING: EffectParameter does not satisfy basic sanity checks.";
}

// qDebug() << debugString()
// << QString("Val: %1 Min: %2 MinLimit: %3 Max: %4 MaxLimit: %5 Default: %6")
// .arg(dValue).arg(dMinimum).arg(dMinimumLimit).arg(dMaximum).arg(dMaximumLimit).arg(dDefault);

m_pControlValue->set(dValue);
m_pControlValue->setDefaultValue(dDefault);
EffectManifestParameter::ControlHint type = m_pEffectParameter->getControlHint();
// TODO(rryan) expose this from EffectParameter
m_pControlType->setAndConfirm(static_cast<double>(type));
// Default loaded parameters to loaded and unlinked
m_pControlLoaded->setAndConfirm(1.0);
m_pControlLinkType->set(m_pEffectParameter->getLinkType());

connect(m_pEffectParameter, SIGNAL(valueChanged(QVariant)),
this, SLOT(slotParameterValueChanged(QVariant)));
}

// Update the newly loaded parameter to match the current chain
// superknob if it is linked.
onChainParameterChanged(m_dChainParameter);
}
emit(updated());
}

void EffectButtonParameterSlot::clear() {
//qDebug() << debugString() << "clear";
if (m_pEffectParameter) {
m_pEffectParameter->disconnect(this);
m_pEffectParameter = NULL;
}

m_pEffect.clear();
m_pControlLoaded->setAndConfirm(0.0);
m_pControlValue->set(0.0);
m_pControlValue->setDefaultValue(0.0);
m_pControlType->setAndConfirm(0.0);
m_pControlLinkType->set(EffectManifestParameter::LINK_NONE);
emit(updated());
}

void EffectButtonParameterSlot::slotParameterValueChanged(QVariant value) {
//qDebug() << debugString() << "slotParameterValueChanged" << value.toDouble();
m_pControlValue->set(value.toDouble());
}

void EffectButtonParameterSlot::onChainParameterChanged(double parameter) {
m_dChainParameter = parameter;
if (m_pEffectParameter != NULL) {
switch (m_pEffectParameter->getLinkType()) {
case EffectManifestParameter::LINK_INVERSE:
parameter = 1.0 - parameter;
// Intentional fall-through.
case EffectManifestParameter::LINK_LINKED:
if (parameter < 0.0 || parameter > 1.0) {
return;
}
m_pControlValue->setParameterFrom(parameter, NULL);
break;
case EffectManifestParameter::LINK_NONE:
default:
break;
}
}
}
58 changes: 58 additions & 0 deletions src/effects/effectbuttonparameterslot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef EFFECTBUTTONPARAMETERSLOT_H
#define EFFECTBUTTONPARAMETERSLOT_H

#include <QObject>
#include <QVariant>
#include <QString>

#include "util.h"
#include "controlobject.h"
#include "effects/effect.h"
#include "effects/effectparameterslotbase.h"

class ControlObject;
class ControlPushButton;

class EffectButtonParameterSlot;
typedef QSharedPointer<EffectButtonParameterSlot> EffectButtonParameterSlotPointer;

class EffectButtonParameterSlot : public EffectParameterSlotBase {
Q_OBJECT
public:
EffectButtonParameterSlot(const unsigned int iRackNumber,
const unsigned int iChainNumber,
const unsigned int iSlotNumber,
const unsigned int iParameterNumber);
virtual ~EffectButtonParameterSlot();

static QString formatItemPrefix(const unsigned int iParameterNumber) {
return QString("button_parameter%1").arg(iParameterNumber + 1);
}

// Load the parameter of the given effect into this EffectButtonParameterSlot
void loadEffect(EffectPointer pEffect);

void onChainParameterChanged(double parameter);

private slots:
// Solely for handling control changes
void slotParameterValueChanged(QVariant value);

private:
QString debugString() const {
return QString("EffectButtonParameterSlot(%1,%2)").arg(m_group).arg(m_iParameterNumber);
}

// Clear the currently loaded effect
void clear();

////////////////////////////////////////////////////////////////////////////////
// Controls exposed to the rest of Mixxx
////////////////////////////////////////////////////////////////////////////////
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not use ASCII-arts in Mixxx code


ControlPushButton* m_pControlValue;

DISALLOW_COPY_AND_ASSIGN(EffectButtonParameterSlot);
};

#endif // EFFECTBUTTONPARAMETERSLOT_H
11 changes: 11 additions & 0 deletions src/effects/effectmanifest.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,21 @@ class EffectManifest {
return m_parameters;
}


virtual EffectManifestParameter* addParameter() {
m_parameters.append(EffectManifestParameter());
return &m_parameters.last();
}

virtual const QList<EffectManifestParameter>& buttonParameters() const {
return m_buttonParameters;
}

virtual EffectManifestParameter* addButtonParameter() {
m_buttonParameters.append(EffectManifestParameter());
return &m_buttonParameters.last();
}

private:
QString debugString() const {
return QString("EffectManifest(%1)").arg(m_id);
Expand All @@ -81,6 +91,7 @@ class EffectManifest {
QString m_version;
QString m_description;
QList<EffectManifestParameter> m_parameters;
QList<EffectManifestParameter> m_buttonParameters;
};

#endif /* EFFECTMANIFEST_H */
Loading