controller.h (7448B)
1 #pragma once 2 3 #include "parameterdescriptions.h" 4 #include "parameter.h" 5 #include "parameterlocking.h" 6 #include "softknob.h" 7 8 #include "synthLib/midiTypes.h" 9 10 #include <string> 11 12 #include "parameterlinks.h" 13 14 namespace juce 15 { 16 class AudioProcessor; 17 class Value; 18 } 19 20 namespace pluginLib 21 { 22 class Processor; 23 using SysEx = std::vector<uint8_t>; 24 25 class Controller : juce::Timer 26 { 27 public: 28 static constexpr uint32_t InvalidParameterIndex = 0xffffffff; 29 30 baseLib::Event<uint8_t> onCurrentPartChanged; 31 32 explicit Controller(Processor& _processor, const std::string& _parameterDescJsonFilename); 33 ~Controller() override; 34 35 virtual void sendParameterChange(const Parameter& _parameter, ParamValue _value) = 0; 36 void sendLockedParameters(uint8_t _part); 37 38 juce::Value* getParamValueObject(uint32_t _index, uint8_t _part) const; 39 Parameter* getParameter(uint32_t _index) const; 40 Parameter* getParameter(uint32_t _index, uint8_t _part) const; 41 Parameter* getParameter(const std::string& _name, uint8_t _part) const; 42 43 uint32_t getParameterIndexByName(const std::string& _name) const; 44 45 bool setParameters(const std::map<std::string, ParamValue>& _values, uint8_t _part, Parameter::Origin _changedBy) const; 46 47 const MidiPacket* getMidiPacket(const std::string& _name) const; 48 49 bool createNamedParamValues(MidiPacket::NamedParamValues& _params, const std::string& _packetName, uint8_t _part) const; 50 bool createNamedParamValues(MidiPacket::NamedParamValues& _dest, const MidiPacket::AnyPartParamValues& _source) const; 51 bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, uint8_t _part) const; 52 bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, const MidiPacket::NamedParamValues& _values) const; 53 bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, const MidiPacket::AnyPartParamValues& _values) const; 54 55 bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const; 56 bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, MidiPacket::AnyPartParamValues& _parameterValues, const SysEx& _src) const; 57 bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, const std::function<void(MidiPacket::ParamIndex, ParamValue)>& _parameterValues, const SysEx& _src) const; 58 bool parseMidiPacket(const std::string& _name, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const; 59 bool parseMidiPacket(std::string& _name, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const; 60 61 const auto& getExposedParameters() const { return m_synthParams; } 62 63 uint8_t getCurrentPart() const { return m_currentPart; } 64 virtual bool setCurrentPart(uint8_t _part); 65 virtual uint8_t getPartCount() const { return 16; } 66 67 virtual bool parseSysexMessage(const SysEx&, synthLib::MidiEventSource) = 0; 68 virtual bool parseControllerMessage(const synthLib::SMidiEvent&) = 0; 69 70 virtual bool parseMidiMessage(const synthLib::SMidiEvent& _e); 71 72 virtual void onStateLoaded() = 0; 73 74 // this is called by the plug-in on audio thread! 75 void enqueueMidiMessages(const std::vector<synthLib::SMidiEvent>&); 76 77 void loadChunkData(baseLib::ChunkReader& _cr); 78 void saveChunkData(baseLib::BinaryStream& _s) const; 79 80 static Parameter::Origin midiEventSourceToParameterOrigin(synthLib::MidiEventSource _source); 81 82 std::vector<uint8_t> getPartsForMidiEvent(const synthLib::SMidiEvent& _e) 83 { 84 return getPartsForMidiChannel(_e.a & 0x0f); 85 } 86 87 virtual std::vector<uint8_t> getPartsForMidiChannel(uint8_t _channel) { return {}; } 88 89 private: 90 void getMidiMessages(std::vector<synthLib::SMidiEvent>&); 91 void processMidiMessages(); 92 std::string loadParameterDescriptions(const std::string& _filename) const; 93 94 public: 95 ParameterLocking& getParameterLocking() { return m_locking; } 96 ParameterLinks& getParameterLinks() { return m_parameterLinks; } 97 98 std::set<std::string> getRegionIdsForParameter(const Parameter* _param) const; 99 std::set<std::string> getRegionIdsForParameter(const std::string& _name) const; 100 101 const ParameterDescriptions& getParameterDescriptions() const { return m_descriptions; } 102 103 const SoftKnob* getSoftknob(const Parameter* _parameter) const 104 { 105 const auto it = m_softKnobs.find(_parameter); 106 return it->second.get(); 107 } 108 109 SoftKnob* getSoftknob(const Parameter* _parameter) 110 { 111 const auto it = m_softKnobs.find(_parameter); 112 return it->second.get(); 113 } 114 115 Processor& getProcessor() const { return m_processor; } 116 117 protected: 118 virtual Parameter* createParameter(Controller& _controller, const Description& _desc, uint8_t _part, int _uid, const Parameter::PartFormatter& _partFormatter); 119 void registerParams(juce::AudioProcessor& _processor, Parameter::PartFormatter _partFormatter = nullptr); 120 121 void sendSysEx(const pluginLib::SysEx &) const; 122 bool sendSysEx(const std::string& _packetName) const; 123 bool sendSysEx(const std::string& _packetName, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const; 124 void sendMidiEvent(const synthLib::SMidiEvent& _ev) const; 125 void sendMidiEvent(uint8_t _a, uint8_t _b, uint8_t _c, uint32_t _offset = 0, synthLib::MidiEventSource _source = synthLib::MidiEventSource::Editor) const; 126 127 bool combineParameterChange(uint8_t& _result, const std::string& _midiPacket, const Parameter& _parameter, ParamValue _value) const; 128 129 void applyPatchParameters(const MidiPacket::ParamValues& _params, uint8_t _part) const; 130 131 virtual bool isDerivedParameter(Parameter& _derived, Parameter& _base) const { return true; } 132 133 struct ParamIndex 134 { 135 uint8_t page; 136 uint8_t partNum; 137 uint8_t paramNum; 138 139 bool operator<(const ParamIndex& _p) const 140 { 141 if (page < _p.page) return true; 142 if (page > _p.page) return false; 143 if (partNum < _p.partNum) return true; 144 if (partNum > _p.partNum) return false; 145 if (paramNum < _p.paramNum) return true; 146 if (paramNum > _p.paramNum) return false; 147 return false; 148 } 149 150 bool operator==(const ParamIndex& _p) const 151 { 152 return page == _p.page && partNum == _p.partNum && paramNum && _p.paramNum; 153 } 154 }; 155 156 using ParameterList = std::vector<Parameter*>; 157 158 void timerCallback() override; 159 160 private: 161 Processor& m_processor; 162 const ParameterDescriptions m_descriptions; 163 164 uint8_t m_currentPart = 0; 165 166 std::mutex m_midiMessagesLock; 167 std::vector<synthLib::SMidiEvent> m_midiMessages; 168 169 std::map<const Parameter*, std::unique_ptr<SoftKnob>> m_softKnobs; 170 171 protected: 172 // tries to find synth param in both internal and host 173 const ParameterList& findSynthParam(uint8_t _part, uint8_t _page, uint8_t _paramIndex) const; 174 const ParameterList& findSynthParam(const ParamIndex& _paramIndex) const; 175 176 std::map<ParamIndex, ParameterList> m_synthInternalParams; 177 std::map<ParamIndex, ParameterList> m_synthParams; // exposed and managed by audio processor 178 std::array<ParameterList, 16> m_paramsByParamType; 179 std::vector<std::unique_ptr<Parameter>> m_synthInternalParamList; 180 ParameterLocking m_locking; 181 ParameterLinks m_parameterLinks; 182 }; 183 }