1 #include "effects/effectrack.h"
2 
3 #include "effects/effectchainmanager.h"
4 #include "effects/effectslot.h"
5 #include "effects/effectsmanager.h"
6 #include "engine/effects/engineeffectrack.h"
7 #include "moc_effectrack.cpp"
8 #include "util/assert.h"
9 
EffectRack(EffectsManager * pEffectsManager,EffectChainManager * pEffectChainManager,const unsigned int iRackNumber,const QString & group,SignalProcessingStage stage)10 EffectRack::EffectRack(EffectsManager* pEffectsManager,
11                        EffectChainManager* pEffectChainManager,
12                        const unsigned int iRackNumber,
13                        const QString& group, SignalProcessingStage stage)
14         : m_pEngineEffectRack(nullptr),
15           m_pEffectsManager(pEffectsManager),
16           m_pEffectChainManager(pEffectChainManager),
17           m_signalProcessingStage(stage),
18           m_iRackNumber(iRackNumber),
19           m_group(group),
20           m_controlNumEffectChainSlots(ConfigKey(m_group, "num_effectunits")),
21           m_controlClearRack(ConfigKey(m_group, "clear")) {
22     connect(&m_controlClearRack, &ControlObject::valueChanged, this, &EffectRack::slotClearRack);
23     m_controlNumEffectChainSlots.setReadOnly();
24     addToEngine();
25 }
26 
~EffectRack()27 EffectRack::~EffectRack() {
28     removeFromEngine();
29     //qDebug() << "EffectRack::~EffectRack()";
30 }
31 
getEngineEffectRack()32 EngineEffectRack* EffectRack::getEngineEffectRack() {
33     return m_pEngineEffectRack;
34 }
35 
addToEngine()36 void EffectRack::addToEngine() {
37     m_pEngineEffectRack = new EngineEffectRack(m_iRackNumber);
38     EffectsRequest* pRequest = new EffectsRequest();
39     pRequest->type = EffectsRequest::ADD_EFFECT_RACK;
40     pRequest->AddEffectRack.pRack = m_pEngineEffectRack;
41     pRequest->AddEffectRack.signalProcessingStage = m_signalProcessingStage;
42     m_pEffectsManager->writeRequest(pRequest);
43 
44     // Add all effect chains.
45     for (int i = 0; i < m_effectChainSlots.size(); ++i) {
46         EffectChainSlotPointer pSlot = m_effectChainSlots[i];
47         EffectChainPointer pChain = pSlot->getEffectChain();
48         if (pChain) {
49             // Add the effect to the engine.
50             pChain->addToEngine(m_pEngineEffectRack, i);
51             // Update its parameters in the engine.
52             pChain->updateEngineState();
53         }
54     }
55 }
56 
removeFromEngine()57 void EffectRack::removeFromEngine() {
58     // Order doesn't matter when removing.
59     for (int i = 0; i < m_effectChainSlots.size(); ++i) {
60         EffectChainSlotPointer pSlot = m_effectChainSlots[i];
61         EffectChainPointer pChain = pSlot->getEffectChain();
62         if (pChain) {
63             pChain->removeFromEngine(m_pEngineEffectRack, i);
64         }
65     }
66 
67     EffectsRequest* pRequest = new EffectsRequest();
68     pRequest->type = EffectsRequest::REMOVE_EFFECT_RACK;
69     pRequest->RemoveEffectRack.signalProcessingStage = m_signalProcessingStage;
70     pRequest->RemoveEffectRack.pRack = m_pEngineEffectRack;
71     m_pEffectsManager->writeRequest(pRequest);
72     m_pEngineEffectRack = nullptr;
73 }
74 
registerInputChannel(const ChannelHandleAndGroup & handle_group)75 void EffectRack::registerInputChannel(const ChannelHandleAndGroup& handle_group) {
76     foreach (EffectChainSlotPointer pChainSlot, m_effectChainSlots) {
77         pChainSlot->registerInputChannel(handle_group);
78     }
79 }
80 
slotClearRack(double v)81 void EffectRack::slotClearRack(double v) {
82     if (v > 0) {
83         foreach (EffectChainSlotPointer pChainSlot, m_effectChainSlots) {
84             pChainSlot->clear();
85         }
86     }
87 }
88 
numEffectChainSlots() const89 int EffectRack::numEffectChainSlots() const {
90     return m_effectChainSlots.size();
91 }
92 
addEffectChainSlotInternal(EffectChainSlotPointer pChainSlot)93 void EffectRack::addEffectChainSlotInternal(EffectChainSlotPointer pChainSlot) {
94     m_effectChainSlots.append(pChainSlot);
95     m_controlNumEffectChainSlots.forceSet(
96         m_controlNumEffectChainSlots.get() + 1);
97 }
98 
getEffectChainSlot(int i)99 EffectChainSlotPointer EffectRack::getEffectChainSlot(int i) {
100     if (i < 0 || i >= m_effectChainSlots.size()) {
101         qWarning() << "WARNING: Invalid index for getEffectChainSlot";
102         return EffectChainSlotPointer();
103     }
104     return m_effectChainSlots[i];
105 }
106 
loadNextChain(const unsigned int iChainSlotNumber,EffectChainPointer pLoadedChain)107 void EffectRack::loadNextChain(const unsigned int iChainSlotNumber,
108                                EffectChainPointer pLoadedChain) {
109     if (pLoadedChain) {
110         pLoadedChain = pLoadedChain->prototype();
111     }
112 
113     EffectChainPointer pNextChain = m_pEffectChainManager->getNextEffectChain(
114             pLoadedChain);
115 
116     pNextChain = EffectChain::clone(pNextChain);
117     pNextChain->addToEngine(m_pEngineEffectRack, iChainSlotNumber);
118     m_effectChainSlots[iChainSlotNumber]->loadEffectChainToSlot(pNextChain);
119     m_effectChainSlots[iChainSlotNumber]->updateRoutingSwitches();
120 }
121 
122 
loadPrevChain(const unsigned int iChainSlotNumber,EffectChainPointer pLoadedChain)123 void EffectRack::loadPrevChain(const unsigned int iChainSlotNumber,
124                                EffectChainPointer pLoadedChain) {
125     if (pLoadedChain) {
126         pLoadedChain = pLoadedChain->prototype();
127     }
128 
129     EffectChainPointer pPrevChain = m_pEffectChainManager->getPrevEffectChain(
130         pLoadedChain);
131 
132     pPrevChain = EffectChain::clone(pPrevChain);
133     pPrevChain->addToEngine(m_pEngineEffectRack, iChainSlotNumber);
134     m_effectChainSlots[iChainSlotNumber]->loadEffectChainToSlot(pPrevChain);
135     m_effectChainSlots[iChainSlotNumber]->updateRoutingSwitches();
136 }
137 
maybeLoadEffect(const unsigned int iChainSlotNumber,const unsigned int iEffectSlotNumber,const QString & id)138 void EffectRack::maybeLoadEffect(const unsigned int iChainSlotNumber,
139                                  const unsigned int iEffectSlotNumber,
140                                  const QString& id) {
141     if (iChainSlotNumber >= static_cast<unsigned int>(m_effectChainSlots.size())) {
142         return;
143     }
144 
145     EffectChainSlotPointer pChainSlot = m_effectChainSlots[iChainSlotNumber];
146     if (pChainSlot == nullptr) {
147         return;
148     }
149     EffectSlotPointer pEffectSlot = pChainSlot->getEffectSlot(iEffectSlotNumber);
150 
151     bool loadNew = false;
152     if (pEffectSlot == nullptr || pEffectSlot->getEffect() == nullptr) {
153         loadNew = true;
154     } else if (id != pEffectSlot->getEffect()->getManifest()->id()) {
155         loadNew = true;
156     }
157 
158     if (loadNew) {
159         EffectChainPointer pChain = pChainSlot->getOrCreateEffectChain(m_pEffectsManager);
160         EffectPointer pEffect = m_pEffectsManager->instantiateEffect(id);
161         pChain->replaceEffect(iEffectSlotNumber, pEffect);
162     }
163 }
164 
loadNextEffect(const unsigned int iChainSlotNumber,const unsigned int iEffectSlotNumber,EffectPointer pEffect)165 void EffectRack::loadNextEffect(const unsigned int iChainSlotNumber,
166                                 const unsigned int iEffectSlotNumber,
167                                 EffectPointer pEffect) {
168     if (iChainSlotNumber >= static_cast<unsigned int>(m_effectChainSlots.size())) {
169         return;
170     }
171 
172     QString effectId = pEffect ? pEffect->getManifest()->id() : QString();
173     QString nextEffectId = m_pEffectsManager->getNextEffectId(effectId);
174     EffectPointer pNextEffect = m_pEffectsManager->instantiateEffect(nextEffectId);
175 
176     EffectChainSlotPointer pChainSlot = m_effectChainSlots[iChainSlotNumber];
177     EffectChainPointer pChain = pChainSlot->getOrCreateEffectChain(m_pEffectsManager);
178     pChain->replaceEffect(iEffectSlotNumber, pNextEffect);
179 }
180 
181 
loadPrevEffect(const unsigned int iChainSlotNumber,const unsigned int iEffectSlotNumber,EffectPointer pEffect)182 void EffectRack::loadPrevEffect(const unsigned int iChainSlotNumber,
183                                 const unsigned int iEffectSlotNumber,
184                                 EffectPointer pEffect) {
185     if (iChainSlotNumber >= static_cast<unsigned int>(m_effectChainSlots.size())) {
186         return;
187     }
188 
189     QString effectId = pEffect ? pEffect->getManifest()->id() : QString();
190     QString prevEffectId = m_pEffectsManager->getPrevEffectId(effectId);
191     EffectPointer pPrevEffect = m_pEffectsManager->instantiateEffect(prevEffectId);
192 
193     EffectChainSlotPointer pChainSlot = m_effectChainSlots[iChainSlotNumber];
194     EffectChainPointer pChain = pChainSlot->getOrCreateEffectChain(m_pEffectsManager);
195     pChain->replaceEffect(iEffectSlotNumber, pPrevEffect);
196 }
197 
toXml(QDomDocument * doc) const198 QDomElement EffectRack::toXml(QDomDocument* doc) const {
199     QDomElement rackElement = doc->createElement("Rack");
200     QDomElement groupElement = doc->createElement("Group");
201     QDomText groupText = doc->createTextNode(m_group);
202     groupElement.appendChild(groupText);
203     rackElement.appendChild(groupElement);
204 
205     QDomElement chainsElement = doc->createElement("Chains");
206     for (const EffectChainSlotPointer& pChainSlot : m_effectChainSlots) {
207         QDomElement chain = pChainSlot->toXml(doc);
208         chainsElement.appendChild(chain);
209     }
210     rackElement.appendChild(chainsElement);
211     return rackElement;
212 }
213 
refresh()214 void EffectRack::refresh() {
215     for (const auto& pChainSlot : qAsConst(m_effectChainSlots)) {
216         EffectChainPointer pChain = pChainSlot->getOrCreateEffectChain(m_pEffectsManager);
217         pChain->refreshAllEffects();
218     }
219 }
220 
isAdoptMetaknobValueEnabled() const221 bool EffectRack::isAdoptMetaknobValueEnabled() const {
222     return m_pEffectChainManager->isAdoptMetaknobValueEnabled();
223 }
224 
StandardEffectRack(EffectsManager * pEffectsManager,EffectChainManager * pChainManager,const unsigned int iRackNumber)225 StandardEffectRack::StandardEffectRack(EffectsManager* pEffectsManager,
226                                        EffectChainManager* pChainManager,
227                                        const unsigned int iRackNumber)
228         : EffectRack(pEffectsManager, pChainManager, iRackNumber,
229                      formatGroupString(iRackNumber), SignalProcessingStage::Postfader) {
230     for (int i = 0; i < EffectChainManager::kNumStandardEffectChains; ++i) {
231         addEffectChainSlot();
232     }
233 }
234 
addEffectChainSlot()235 EffectChainSlotPointer StandardEffectRack::addEffectChainSlot() {
236     int iChainSlotNumber = numEffectChainSlots();
237 
238     QString group = formatEffectChainSlotGroupString(getRackNumber(),
239                                                      iChainSlotNumber);
240     EffectChainSlot* pChainSlot =
241             new EffectChainSlot(this, group, iChainSlotNumber);
242 
243     for (int i = 0; i < kNumEffectsPerUnit; ++i) {
244         pChainSlot->addEffectSlot(
245                 StandardEffectRack::formatEffectSlotGroupString(
246                         getRackNumber(), iChainSlotNumber, i));
247     }
248 
249     connect(pChainSlot, &EffectChainSlot::nextChain, this, &StandardEffectRack::loadNextChain);
250     connect(pChainSlot, &EffectChainSlot::prevChain, this, &StandardEffectRack::loadPrevChain);
251 
252     connect(pChainSlot, &EffectChainSlot::nextEffect, this, &StandardEffectRack::loadNextEffect);
253     connect(pChainSlot, &EffectChainSlot::prevEffect, this, &StandardEffectRack::loadPrevEffect);
254 
255     // Register all the existing channels with the new EffectChain.
256     const QSet<ChannelHandleAndGroup>& registeredChannels =
257             m_pEffectChainManager->registeredInputChannels();
258     for (const ChannelHandleAndGroup& handle_group : registeredChannels) {
259         pChainSlot->registerInputChannel(handle_group);
260     }
261 
262     EffectChainSlotPointer pChainSlotPointer = EffectChainSlotPointer(pChainSlot);
263     addEffectChainSlotInternal(pChainSlotPointer);
264 
265     return pChainSlotPointer;
266 }
267 
OutputEffectRack(EffectsManager * pEffectsManager,EffectChainManager * pChainManager)268 OutputEffectRack::OutputEffectRack(EffectsManager* pEffectsManager,
269                                    EffectChainManager* pChainManager)
270         : EffectRack(pEffectsManager, pChainManager, 0,
271                      "[OutputEffectRack]", SignalProcessingStage::Postfader) {
272 
273     const QString unitGroup = "[OutputEffectRack_[Master]]";
274     // Hard code only one EffectChainSlot
275     EffectChainSlot* pChainSlot = new EffectChainSlot(this, unitGroup, 0);
276     EffectChainPointer pChain(new EffectChain(m_pEffectsManager, unitGroup));
277     pChainSlot->loadEffectChainToSlot(pChain);
278     pChain->addToEngine(getEngineEffectRack(), 0);
279     // Add a single EffectSlot for the master EQ effect
280     pChainSlot->addEffectSlot("[OutputEffectRack_[Master]_Effect1]");
281 
282     connect(pChainSlot, &EffectChainSlot::nextChain, this, &OutputEffectRack::loadNextChain);
283     connect(pChainSlot, &EffectChainSlot::prevChain, this, &OutputEffectRack::loadPrevChain);
284 
285     connect(pChainSlot, &EffectChainSlot::nextEffect, this, &OutputEffectRack::loadNextEffect);
286     connect(pChainSlot, &EffectChainSlot::prevEffect, this, &OutputEffectRack::loadPrevEffect);
287 
288     // Register the master channel.
289     const ChannelHandleAndGroup* masterHandleAndGroup = nullptr;
290 
291     // TODO(Be): Remove this hideous hack to get the ChannelHandleAndGroup
292     const QSet<ChannelHandleAndGroup>& registeredChannels =
293             m_pEffectChainManager->registeredInputChannels();
294     for (const ChannelHandleAndGroup& handle_group : registeredChannels) {
295         if (handle_group.name() == "[MasterOutput]") {
296             masterHandleAndGroup = &handle_group;
297             break;
298         }
299     }
300     DEBUG_ASSERT(masterHandleAndGroup != nullptr);
301 
302     pChainSlot->registerInputChannel(*masterHandleAndGroup);
303     pChain->enableForInputChannel(*masterHandleAndGroup);
304     pChain->setMix(1.0);
305 
306     EffectChainSlotPointer pChainSlotPointer = EffectChainSlotPointer(pChainSlot);
307     addEffectChainSlotInternal(pChainSlotPointer);
308 }
309 
PerGroupRack(EffectsManager * pEffectsManager,EffectChainManager * pChainManager,const unsigned int iRackNumber,const QString & group)310 PerGroupRack::PerGroupRack(EffectsManager* pEffectsManager,
311                            EffectChainManager* pChainManager,
312                            const unsigned int iRackNumber,
313                            const QString& group)
314         : EffectRack(pEffectsManager, pChainManager, iRackNumber, group,
315                      SignalProcessingStage::Prefader) {
316 }
317 
setupForGroup(const QString & groupName)318 void PerGroupRack::setupForGroup(const QString& groupName) {
319     VERIFY_OR_DEBUG_ASSERT(!m_groupToChainSlot.contains(groupName)) {
320         return;
321     }
322 
323     int iChainSlotNumber = m_groupToChainSlot.size();
324     QString chainSlotGroup = formatEffectChainSlotGroupForGroup(
325         getRackNumber(), iChainSlotNumber, groupName);
326     EffectChainSlot* pChainSlot = new EffectChainSlot(this, chainSlotGroup,
327                                                       iChainSlotNumber);
328     EffectChainSlotPointer pChainSlotPointer(pChainSlot);
329     addEffectChainSlotInternal(pChainSlotPointer);
330     m_groupToChainSlot[groupName] = pChainSlotPointer;
331 
332     // TODO(rryan): Set up next/prev signals.
333 
334     EffectChainPointer pChain(new EffectChain(m_pEffectsManager, chainSlotGroup));
335     pChainSlot->loadEffectChainToSlot(pChain);
336     pChain->addToEngine(getEngineEffectRack(), iChainSlotNumber);
337     // Set the chain to be fully wet.
338     pChain->setMix(1.0);
339     pChain->updateEngineState();
340 
341     // TODO(rryan): remove.
342     const ChannelHandleAndGroup* handleAndGroup = nullptr;
343     for (const ChannelHandleAndGroup& handle_group :
344              m_pEffectChainManager->registeredInputChannels()) {
345         if (handle_group.name() == groupName) {
346             handleAndGroup = &handle_group;
347             break;
348         }
349     }
350     DEBUG_ASSERT(handleAndGroup != nullptr);
351 
352     // Register this channel alone with the chain slot.
353     pChainSlot->registerInputChannel(*handleAndGroup);
354     pChainSlot->updateRoutingSwitches();
355 
356     // Add a single effect slot
357     pChainSlot->addEffectSlot(formatEffectSlotGroupString(0, groupName));
358     // DlgPrefEq loads the Effect with loadEffectToGroup
359 
360     configureEffectChainSlotForGroup(pChainSlotPointer, groupName);
361 }
362 
loadEffectToGroup(const QString & groupName,EffectPointer pEffect)363 bool PerGroupRack::loadEffectToGroup(const QString& groupName, EffectPointer pEffect) {
364     EffectChainSlotPointer pChainSlot = getGroupEffectChainSlot(groupName);
365     VERIFY_OR_DEBUG_ASSERT(pChainSlot) {
366         return false;
367     }
368 
369     EffectChainPointer pChain = pChainSlot->getOrCreateEffectChain(m_pEffectsManager);
370     pChain->replaceEffect(0, pEffect);
371     pChainSlot->updateRoutingSwitches();
372 
373     if (pEffect != nullptr) {
374         pEffect->setEnabled(true);
375     }
376     return true;
377 }
378 
getGroupEffectChainSlot(const QString & group)379 EffectChainSlotPointer PerGroupRack::getGroupEffectChainSlot(const QString& group) {
380     return m_groupToChainSlot[group];
381 }
382 
QuickEffectRack(EffectsManager * pEffectsManager,EffectChainManager * pChainManager,const unsigned int iRackNumber)383 QuickEffectRack::QuickEffectRack(EffectsManager* pEffectsManager,
384                                  EffectChainManager* pChainManager,
385                                  const unsigned int iRackNumber)
386         : PerGroupRack(pEffectsManager, pChainManager, iRackNumber,
387                        QuickEffectRack::formatGroupString(iRackNumber)) {
388 }
389 
configureEffectChainSlotForGroup(EffectChainSlotPointer pSlot,const QString & groupName)390 void QuickEffectRack::configureEffectChainSlotForGroup(
391         EffectChainSlotPointer pSlot, const QString& groupName) {
392     Q_UNUSED(groupName);
393     // Set the parameter default value to 0.5 (neutral).
394     pSlot->setSuperParameter(0.5);
395     pSlot->setSuperParameterDefaultValue(0.5);
396 }
397 
loadEffectToGroup(const QString & groupName,EffectPointer pEffect)398 bool QuickEffectRack::loadEffectToGroup(const QString& groupName,
399                                         EffectPointer pEffect) {
400     PerGroupRack::loadEffectToGroup(groupName, pEffect);
401     EffectChainSlotPointer pChainSlot = getGroupEffectChainSlot(groupName);
402     // Force update metaknobs and parameters to match state of superknob
403     pChainSlot->setSuperParameter(pChainSlot->getSuperParameter(), true);
404     return true;
405 }
406 
EqualizerRack(EffectsManager * pEffectsManager,EffectChainManager * pChainManager,const unsigned int iRackNumber)407 EqualizerRack::EqualizerRack(EffectsManager* pEffectsManager,
408                              EffectChainManager* pChainManager,
409                              const unsigned int iRackNumber)
410         : PerGroupRack(pEffectsManager, pChainManager, iRackNumber,
411                        EqualizerRack::formatGroupString(iRackNumber)) {
412 }
413 
configureEffectChainSlotForGroup(EffectChainSlotPointer pSlot,const QString & groupName)414 void EqualizerRack::configureEffectChainSlotForGroup(EffectChainSlotPointer pSlot,
415                                                      const QString& groupName) {
416     // Create aliases for legacy EQ controls.
417     // NOTE(rryan): If we ever add a second EqualizerRack then we need to make
418     // these only apply to the first.
419     EffectSlotPointer pEffectSlot = pSlot->getEffectSlot(0);
420     if (pEffectSlot) {
421         const QString& effectSlotGroup = pEffectSlot->getGroup();
422         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterLow"),
423                                           ConfigKey(effectSlotGroup, "parameter1"));
424 
425         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterMid"),
426                                           ConfigKey(effectSlotGroup, "parameter2"));
427 
428         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterHigh"),
429                                           ConfigKey(effectSlotGroup, "parameter3"));
430 
431         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterLowKill"),
432                                           ConfigKey(effectSlotGroup, "button_parameter1"));
433 
434         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterMidKill"),
435                                           ConfigKey(effectSlotGroup, "button_parameter2"));
436 
437         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterHighKill"),
438                                           ConfigKey(effectSlotGroup, "button_parameter3"));
439 
440         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterLow_loaded"),
441                                           ConfigKey(effectSlotGroup, "parameter1_loaded"));
442 
443         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterMid_loaded"),
444                                           ConfigKey(effectSlotGroup, "parameter2_loaded"));
445 
446         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterHigh_loaded"),
447                                           ConfigKey(effectSlotGroup, "parameter3_loaded"));
448 
449         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterLowKill_loaded"),
450                                           ConfigKey(effectSlotGroup, "button_parameter1_loaded"));
451 
452         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterMidKill_loaded"),
453                                           ConfigKey(effectSlotGroup, "button_parameter2_loaded"));
454 
455         ControlDoublePrivate::insertAlias(ConfigKey(groupName, "filterHighKill_loaded"),
456                                           ConfigKey(effectSlotGroup, "button_parameter3_loaded"));
457     }
458 }
459