score-plugin-vst/Vst/EffectModel.hpp
1 #pragma once
2 #include <Process/Dataflow/PortFactory.hpp>
3 #include <Process/GenericProcessFactory.hpp>
4 #include <Process/Process.hpp>
5 
6 #include <Control/DefaultEffectItem.hpp>
7 #include <Effect/EffectFactory.hpp>
8 #include <Vst/Loader.hpp>
9 
10 #include <score/tools/std/Invoke.hpp>
11 
12 #include <ossia/detail/hash_map.hpp>
13 
14 #include <verdigris>
15 namespace vst
16 {
17 class Model;
18 class ControlInlet;
19 }
20 PROCESS_METADATA(
21  , vst::Model, "BE8E6BD3-75F2-4102-8895-8A4EB4EA545A", "VST", "VST",
22  Process::ProcessCategory::Other, "Plugins", "VST plug-in",
23  "VST is a trademark of Steinberg Media Technologies GmbH", {}, {}, {},
24  QUrl("https://ossia.io/score-docs/processes/audio-plugins.html#controlling-vst-parameters"),
25  Process::ProcessFlags::ExternalEffect)
26 UUID_METADATA(, Process::Port, vst::ControlInlet, "e523bc44-8599-4a04-94c1-04ce0d1a692a")
27 DESCRIPTION_METADATA(, vst::Model, "")
28 namespace vst
29 {
30 #define VST_FIRST_CONTROL_INDEX(synth) ((synth) ? 2 : 1)
31 struct AEffectWrapper
32 {
33  AEffect* fx{};
34  VstTimeInfo info;
35  bool ui_opened{};
36 
37  AEffectWrapper(AEffect* f) noexcept
38  : fx{f}
39  {
40  }
41 
42  auto getParameter(int32_t index) const noexcept { return fx->getParameter(fx, index); }
43  auto setParameter(int32_t index, float p) const noexcept
44  {
45  return fx->setParameter(fx, index, p);
46  }
47 
48  auto dispatch(
49  int32_t opcode, int32_t index = 0, intptr_t value = 0, void* ptr = nullptr,
50  float opt = 0.0f) const noexcept
51  {
52  return fx->dispatcher(fx, opcode, index, value, ptr, opt);
53  }
54 
55  ~AEffectWrapper();
56 };
57 
58 class CreateControl;
59 class ControlInlet;
60 class Model final : public Process::ProcessModel
61 {
62  W_OBJECT(Model)
63  SCORE_SERIALIZE_FRIENDS
64  friend class vst::CreateControl;
65 
66 public:
67  MODEL_METADATA_IMPL(Model)
68  Model(
69  TimeVal t, const QString& name, const Id<Process::ProcessModel>&, QObject* parent);
70 
71  ~Model() override;
72  template <typename Impl>
73  Model(Impl& vis, QObject* parent)
74  : ProcessModel{vis, parent}
75  , m_registration{*this}
76  {
77  init();
78  vis.writeTo(*this);
79  }
80 
81  QString prettyShortName() const noexcept override
82  {
84  }
85  QString category() const noexcept override
86  {
88  }
89  QStringList tags() const noexcept override { return Metadata<Tags_k, Model>::get(); }
90  Process::ProcessFlags flags() const noexcept override;
91  void setCreatingControls(bool ok) override;
92 
93  ControlInlet* getControl(const Id<Process::Port>& p) const;
94  QString effect() const noexcept override;
95  QString prettyName() const noexcept override;
96  bool hasExternalUI() const noexcept;
97 
98  std::shared_ptr<AEffectWrapper> fx{};
99 
100  ossia::hash_map<int, ControlInlet*> controls;
101 
102  void removeControl(const Id<Process::Port>&);
103  void removeControl(int fxnum);
104 
105  //void addControl(int idx, float v) W_SIGNAL(addControl, idx, v);
106  void on_addControl(int idx, float v);
107  W_SLOT(on_addControl);
108  void on_addControl_impl(ControlInlet* inl);
109  void on_controlChangedFromScore(int num, float newval);
110 
111  void reloadControls();
112  void reloadPrograms();
113 
114  auto dispatch(
115  int32_t opcode, int32_t index = 0, intptr_t value = 0, void* ptr = nullptr,
116  float opt = 0.0f)
117  {
118  return fx->dispatch(opcode, index, value, ptr, opt);
119  }
120  std::atomic_bool needIdle{};
121 
122 private:
123  void loadPreset(const Process::Preset& preset) override;
124  Process::Preset savePreset() const noexcept override;
125  std::vector<Process::Preset> builtinPresets() const noexcept override;
126 
127  QString getString(AEffectOpcodes op, int param);
128  void setControlName(int fxnum, ControlInlet* ctrl);
129  void init();
130  void create();
131  void load();
132  void closePlugin();
133  void initFx();
134 
135  std::string m_backup_chunk;
136  ossia::float_vector m_backup_float_data;
137  std::vector<std::pair<std::string, int>> m_programs;
138  int32_t m_effectId{};
139  bool m_createControls{};
140 
141  struct vst_context_handler
142  {
143  Model& self;
144  explicit vst_context_handler(Model& self);
145  ~vst_context_handler();
146  } m_registration;
147 };
148 
149 // VSTModule* getPlugin(QString path);
150 AEffect* getPluginInstance(int32_t id);
151 intptr_t vst_host_callback(
152  AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr,
153  float opt);
154 }
155 
156 namespace Process
157 {
158 template <>
159 QString EffectProcessFactory_T<vst::Model>::customConstructionData() const noexcept;
160 
161 template <>
162 Process::Descriptor
163 EffectProcessFactory_T<vst::Model>::descriptor(QString d) const noexcept;
164 }
165 
166 namespace vst
167 {
168 using VSTEffectFactory = Process::EffectProcessFactory_T<Model>;
169 }
Definition: QmlObjects.hpp:114
Definition: EffectFactory.hpp:14
Definition: Port.hpp:102
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
The id_base_t class.
Definition: Identifier.hpp:57
Definition: Vst/Control.hpp:15
Definition: plugins/score-plugin-vst/Vst/commands.hpp:41
Base classes and tools to implement processes and layers.
Definition: JSONVisitor.hpp:1324
ProcessFlags
Various settings for processes.
Definition: ProcessFlags.hpp:17
Static metadata implementation.
Definition: lib/score/tools/Metadata.hpp:36
Definition: Preset.hpp:32
Definition: TimeValue.hpp:21