Loading...
Searching...
No Matches
score-plugin-clap/Clap/EffectModel.hpp
1#pragma once
2#include <Process/GenericProcessFactory.hpp>
3#include <Process/Process.hpp>
4#include <Process/ProcessMetadata.hpp>
5
6#include <Control/DefaultEffectItem.hpp>
7#include <Effect/EffectFactory.hpp>
8
10#include <score/serialization/JSONVisitor.hpp>
11
12#include <ossia/detail/hash_map.hpp>
13
14#include <QSocketNotifier>
15
16#include <clap/all.h>
17
18#include <memory>
19#include <verdigris>
20
21namespace Clap
22{
23class Model;
24}
25
26PROCESS_METADATA(
27 , Clap::Model, "10e8d26d-1d82-4bfc-a9fb-d85ffdf04e5f", "CLAP", "CLAP",
28 Process::ProcessCategory::Other, "Plugins", "CLever Audio Plug-in", "ossia score",
29 {}, {}, {},
30 QUrl(
31 "https://ossia.io/score-docs/processes/"
32 "audio-plugins.html#common-formats-vst-vst3-lv2-jsfx"),
33 Process::ProcessFlags::ExternalEffect)
34DESCRIPTION_METADATA(, Clap::Model, "Clap")
35
36namespace Clap
37{
38class Window;
39class Model;
40struct PluginHandle
41{
42 PluginHandle();
43 PluginHandle(const PluginHandle&) = delete;
44 PluginHandle(PluginHandle&&) = delete;
45 PluginHandle& operator=(const PluginHandle&) = delete;
46 PluginHandle& operator=(PluginHandle&&) = delete;
47 ~PluginHandle();
48
49 void load(Model& context, QByteArray path, QByteArray id);
50 void* library{};
51 const clap_plugin_entry_t* entry{};
52 const clap_plugin_factory_t* factory{};
53 const clap_plugin_t* plugin{};
54 const clap_plugin_descriptor_t* desc{};
55
56 clap_host_t host;
57
58 // Common plugin extensions
59 const clap_plugin_params_t* ext_params{};
60 const clap_plugin_timer_support_t* ext_timer_support{};
61
62 // Metadata we parsed
63 std::vector<clap_param_info_t> m_parameters_ins;
64 std::vector<clap_param_info_t> m_parameters_outs;
65 std::vector<clap_audio_port_info_t> m_audio_ins;
66 std::vector<clap_audio_port_info_t> m_audio_outs;
67 std::vector<clap_note_port_info_t> m_midi_ins;
68 std::vector<clap_note_port_info_t> m_midi_outs;
69
70 QPointer<Model> model;
71
72 bool activated{};
73};
74
75class Model final : public Process::ProcessModel
76{
77 W_OBJECT(Model)
78 SCORE_SERIALIZE_FRIENDS
79
80public:
81 MODEL_METADATA_IMPL(Model)
82
83 Model(
84 const TimeVal& duration, const QString& pluginPath,
85 const Id<Process::ProcessModel>& id, QObject* parent);
86
87 Model(DataStream::Deserializer& vis, QObject* parent);
88 Model(JSONObject::Deserializer& vis, QObject* parent);
89 Model(DataStream::Deserializer&& vis, QObject* parent);
90 Model(JSONObject::Deserializer&& vis, QObject* parent);
91
92 ~Model() override;
93
94 QString prettyShortName() const noexcept override
95 {
97 }
98 QString category() const noexcept override
99 {
101 }
102 QStringList tags() const noexcept override { return Metadata<Tags_k, Model>::get(); }
103 Process::ProcessFlags flags() const noexcept override;
104 bool hasExternalUI() const noexcept;
105 const std::shared_ptr<PluginHandle>& handle() const noexcept { return m_plugin; }
106
107 void closeUI() const;
108
109 const QString& pluginId() const noexcept { return m_pluginId; }
110 bool supports64() const noexcept { return m_supports64; }
111
112 const std::vector<clap_param_info_t>& parameterInputs() const noexcept
113 {
114 return m_plugin->m_parameters_ins;
115 }
116 const std::vector<clap_param_info_t>& parameterOutputs() const noexcept
117 {
118 return m_plugin->m_parameters_outs;
119 }
120 const std::vector<clap_note_port_info_t>& midiInputs() const noexcept
121 {
122 return m_plugin->m_midi_ins;
123 }
124 const std::vector<clap_note_port_info_t>& midiOutputs() const noexcept
125 {
126 return m_plugin->m_midi_outs;
127 }
128 const std::vector<clap_audio_port_info_t>& audioInputs() const noexcept
129 {
130 return m_plugin->m_audio_ins;
131 }
132 const std::vector<clap_audio_port_info_t>& audioOutputs() const noexcept
133 {
134 return m_plugin->m_audio_outs;
135 }
136
137 // Preset functionality
138 void loadPreset(const Process::Preset& preset) override;
139 Process::Preset savePreset() const noexcept override;
140 std::vector<Process::Preset> builtinPresets() const noexcept override;
141
142 void restartPlugin() W_SIGNAL(restartPlugin);
143 Clap::Window* window{};
144 std::vector<std::pair<clap_id, QTimer*>> timers;
145
146 struct FdNotifiers
147 {
148 std::unique_ptr<QSocketNotifier> read;
149 std::unique_ptr<QSocketNotifier> write;
150 std::unique_ptr<QSocketNotifier> error;
151 };
152 ossia::hash_map<int, std::unique_ptr<FdNotifiers>> fd_notifiers;
153
154 void requestFlush() W_SIGNAL(requestFlush);
155
156 void flushFromPluginToHost();
157
158 bool currentlyReadingValues{};
159
160private:
161 void loadPlugin();
162 void createControls(bool loading);
163 void setupControlInlet(
164 const clap_plugin_params_t&, const clap_param_info_t& info, int index,
166 void setupControlOutlet(
167 const clap_plugin_params_t&, const clap_param_info_t& info, int index,
169
170 QString m_pluginPath;
171 QString m_pluginId;
172
173 std::shared_ptr<PluginHandle> m_plugin;
174 QByteArray m_loadedState;
175
176 bool m_supports64{};
177};
178}
179
180namespace Process
181{
182template <>
183QString EffectProcessFactory_T<Clap::Model>::customConstructionData() const noexcept;
184
185template <>
186Process::Descriptor
187EffectProcessFactory_T<Clap::Model>::descriptor(QString d) const noexcept;
188}
189
190namespace Clap
191{
192class Window;
194using EffectLayerFactory = Process::EffectLayerFactory_T<
195 Clap::Model,
197 Window>;
198}
Definition DataStreamVisitor.hpp:202
Definition JSONVisitor.hpp:423
Definition Port.hpp:204
Definition Port.hpp:426
Definition DefaultEffectItem.hpp:26
Definition EffectFactory.hpp:67
Definition EffectFactory.hpp:14
The Process class.
Definition score-lib-process/Process/Process.hpp:61
The id_base_t class.
Definition Identifier.hpp:59
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1115
ProcessFlags
Various settings for processes.
Definition ProcessFlags.hpp:17
STL namespace.
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Definition Preset.hpp:32
Definition TimeValue.hpp:21