#pragma once #include #include "ChainSlots.hpp" #include "LatencyListener.hpp" #include "General/AudioSpinMutex.h" #include "CloneableDelayLine.hpp" typedef CloneableDelayLine CloneableDelayLineType; class PluginChain { public: std::vector> chain; bool isChainBypassed; bool isChainMuted; std::function getModulationValueCallback; std::unique_ptr latencyCompLine; WECore::AudioSpinMutex latencyCompLineMutex; PluginChainLatencyListener latencyListener; juce::String customName; PluginChain(std::function getModulationValueCallback) : isChainBypassed(false), isChainMuted(false), getModulationValueCallback(getModulationValueCallback), latencyListener(this) { latencyCompLine.reset(new CloneableDelayLineType(0)); latencyCompLine->setDelay(0); } virtual ~PluginChain() { // The plugins might outlive this chain if they're also referenced by another copy in the // history, so remove the listener for (auto& slot : chain) { if (std::shared_ptr plugin = std::dynamic_pointer_cast(slot)) { plugin->plugin->removeListener(&latencyListener); } } } PluginChain* clone() const { return new PluginChain( chain, isChainBypassed, isChainMuted, getModulationValueCallback, std::unique_ptr(latencyCompLine->clone()), customName ); } private: PluginChain( std::vector> newChain, bool newIsChainBypassed, bool newIsChainMuted, std::function newGetModulationValueCallback, std::unique_ptr newLatencyCompLine, const juce::String& newCustomName) : isChainBypassed(newIsChainBypassed), isChainMuted(newIsChainMuted), getModulationValueCallback(newGetModulationValueCallback), latencyCompLine(std::move(newLatencyCompLine)), latencyListener(this), customName(newCustomName) { for (auto& slot : newChain) { chain.push_back(std::shared_ptr(slot->clone())); if (auto plugin = std::dynamic_pointer_cast(slot)) { plugin->plugin->addListener(&latencyListener); } } latencyListener.onPluginChainUpdate(); } };