Loading...
Searching...
No Matches
Context.hpp
1#pragma once
2#if defined(__clang__) && defined(__has_warning)
3#pragma clang diagnostic push
4#if __has_warning("-Wdeprecated-declarations")
5#pragma clang diagnostic ignored "-Wdeprecated-declarations"
6#endif
7#endif
8
9#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
10#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
11#include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
12#include <lv2/lv2plug.in/ns/ext/data-access/data-access.h>
13#include <lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h>
14#include <lv2/lv2plug.in/ns/ext/event/event.h>
15#include <lv2/lv2plug.in/ns/ext/instance-access/instance-access.h>
16#include <lv2/lv2plug.in/ns/ext/log/log.h>
17#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
18#include <lv2/lv2plug.in/ns/ext/morph/morph.h>
19#include <lv2/lv2plug.in/ns/ext/options/options.h>
20#include <lv2/lv2plug.in/ns/ext/parameters/parameters.h>
21#include <lv2/lv2plug.in/ns/ext/patch/patch.h>
22#include <lv2/lv2plug.in/ns/ext/port-groups/port-groups.h>
23#include <lv2/lv2plug.in/ns/ext/port-props/port-props.h>
24#include <lv2/lv2plug.in/ns/ext/presets/presets.h>
25#include <lv2/lv2plug.in/ns/ext/resize-port/resize-port.h>
26#include <lv2/lv2plug.in/ns/ext/state/state.h>
27#include <lv2/lv2plug.in/ns/ext/time/time.h>
28#include <lv2/lv2plug.in/ns/ext/uri-map/uri-map.h>
29#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
30#include <lv2/lv2plug.in/ns/ext/worker/worker.h>
31#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
32
33#include <ossia/detail/hash_map.hpp>
34#include <ossia/detail/lockfree_queue.hpp>
35#include <ossia/detail/small_vector.hpp>
36
37#include <boost/bimap.hpp>
38
39#include <QString>
40
41#include <lilv/lilvmm.hpp>
42
43#include <readerwriterqueue.h>
44
45#include <atomic>
46#include <cstdarg>
47#include <cstdio>
48#include <functional>
49#include <memory>
50#include <vector>
51
52#include <score_plugin_lv2_export.h>
53#include <suil-0/suil/suil.h>
54
55namespace LV2
56{
57struct EffectContext;
58struct GlobalContext;
60{
61 Lilv::Node make_node(const char* desc)
62 {
63 Lilv::Node n{nullptr};
64 n.me = lilv_new_uri(world.me, desc);
65 return n;
66 }
67
68 LV2::GlobalContext* global{};
69 LV2::EffectContext* current{};
70 LV2_Feature const* const* features{};
71 Lilv::World& world;
72
73 LV2_Atom_Forge forge{};
74
75 Lilv::Node input_class{make_node(LILV_URI_INPUT_PORT)};
76 Lilv::Node output_class{make_node(LILV_URI_OUTPUT_PORT)};
77 Lilv::Node control_class{make_node(LILV_URI_CONTROL_PORT)};
78 Lilv::Node audio_class{make_node(LILV_URI_AUDIO_PORT)};
79 Lilv::Node atom_class{make_node(LV2_ATOM__AtomPort)};
80 Lilv::Node atom_object_class{make_node(LV2_ATOM__Object)};
81 Lilv::Node event_class{make_node(LILV_URI_EVENT_PORT)};
82 Lilv::Node midi_event_class{make_node(LILV_URI_MIDI_EVENT)};
83 Lilv::Node cv_class{make_node(LV2_CORE__CVPort)};
84 Lilv::Node work_interface{make_node(LV2_WORKER__interface)};
85 Lilv::Node work_schedule{make_node(LV2_WORKER__schedule)};
86
87 Lilv::Node time_time_class{make_node(LV2_TIME__Time)};
88 Lilv::Node time_Position_class{make_node(LV2_TIME__Position)};
89 Lilv::Node time_rate_class{make_node(LV2_TIME__Rate)};
90 //Lilv::Node time_position_class{make_node(LV2_TIME__position)};
91 Lilv::Node time_barBeat_class{make_node(LV2_TIME__barBeat)};
92 Lilv::Node time_bar_class{make_node(LV2_TIME__bar)};
93 Lilv::Node time_beat_class{make_node(LV2_TIME__beat)};
94 Lilv::Node time_beatUnit_class{make_node(LV2_TIME__beatUnit)};
95 Lilv::Node time_beatsPerBar_class{make_node(LV2_TIME__beatsPerBar)};
96 Lilv::Node time_beatsPerMinute_class{make_node(LV2_TIME__beatsPerMinute)};
97 Lilv::Node time_frame_class{make_node(LV2_TIME__frame)};
98 Lilv::Node time_framesPerSecond_class{make_node(LV2_TIME__framesPerSecond)};
99 Lilv::Node time_speed_class{make_node(LV2_TIME__speed)};
100
101 Lilv::Node optional_feature{make_node(LV2_CORE__optionalFeature)};
102 Lilv::Node fixed_size{make_node(LV2_UI__fixedSize)};
103 Lilv::Node no_user_resize{make_node(LV2_UI__noUserResize)};
104
105 Lilv::Node state_loadDefaultState_node{make_node(LV2_STATE__loadDefaultState)};
106
107 Lilv::Node integer_property{make_node("http://lv2plug.in/ns/lv2core#integer")};
108 Lilv::Node toggled_property{make_node("http://lv2plug.in/ns/lv2core#toggled")};
109 Lilv::Node enumeration_property{
110 make_node("http://lv2plug.in/ns/lv2core#enumeration")};
111 Lilv::Node logarithmic_property{make_node(LV2_PORT_PROPS__logarithmic)};
112 Lilv::Node notOnGUI_property{make_node(LV2_PORT_PROPS__notOnGUI)};
113
114 Lilv::Node host_ui_type{make_node("http://lv2plug.in/ns/extensions/ui#Qt6UI")};
115
116 int32_t midi_buffer_size = 2048;
117 LV2_URID midi_event_id{};
118 LV2_URID atom_chunk_id{};
119 LV2_URID atom_sequence_id{};
120 LV2_URID atom_object_id{};
121 LV2_URID null_id{};
122 LV2_URID atom_eventTransfer{};
123
124 // state:port-restore payload types; see Ardour set_port_value (lv2_plugin.cc:313)
125 LV2_URID atom_Float_id{};
126 LV2_URID atom_Double_id{};
127 LV2_URID atom_Int_id{};
128 LV2_URID atom_Long_id{};
129
130 LV2_URID time_Time_id{};
131 LV2_URID time_Position_id{};
132 LV2_URID time_rate_id{};
133 // LV2_URID time_position_id{};
134 LV2_URID time_barBeat_id{};
135 LV2_URID time_bar_id{};
136 LV2_URID time_beat_id{};
137 LV2_URID time_beatUnit_id{};
138 LV2_URID time_beatsPerBar_id{};
139 LV2_URID time_beatsPerMinute_id{};
140 LV2_URID time_frame_id{};
141 LV2_URID time_framesPerSecond_id{};
142 LV2_URID time_speed_id{};
143
144 std::vector<char> acquire_worker_data(const char* data, uint32_t s) noexcept
145 {
146 std::vector<char> cp;
147 worker_datas_pool.try_dequeue(cp);
148 cp.assign(data, data + s);
149 return cp;
150 }
151
152 void release_worker_data(std::vector<char>&& v) noexcept
153 {
154 worker_datas_pool.enqueue(std::move(v));
155 }
156
157 ossia::mpmc_queue<std::vector<char>> worker_datas_pool{};
158
159 // Set by the audio node per-voice so work_schedule routes to the right queue
160 ossia::mpmc_queue<std::vector<char>>* current_worker_datas{};
161};
162
163// shared_ptr<InstanceHandle>: refcounted LilvInstance. Last drop MUST be on the main thread.
165{
166 LilvInstance* instance{};
167 bool activated{false};
168
169 InstanceHandle() = default;
170 explicit InstanceHandle(LilvInstance* i) noexcept
171 : instance{i}
172 {
173 }
174 InstanceHandle(const InstanceHandle&) = delete;
175 InstanceHandle& operator=(const InstanceHandle&) = delete;
176 InstanceHandle(InstanceHandle&&) = delete;
177 InstanceHandle& operator=(InstanceHandle&&) = delete;
178 ~InstanceHandle() noexcept
179 {
180 if(!instance)
181 return;
182 if(activated)
183 lilv_instance_deactivate(instance);
184 lilv_instance_free(instance);
185 }
186};
187
188using SharedInstance = std::shared_ptr<InstanceHandle>;
189
191{
192 Lilv::Plugin plugin{nullptr};
193 // alias for instance_holder->instance
194 LilvInstance* instance{};
195 SharedInstance instance_holder{};
196 const LV2_Worker_Interface* worker{};
197 LV2_Extension_Data_Feature data{};
198 const LilvUI* ui{};
199 const LilvNode* ui_type{};
200 SuilInstance* ui_instance{};
201
202 ossia::mpmc_queue<std::vector<char>> worker_datas;
203};
204
205struct SCORE_PLUGIN_LV2_EXPORT GlobalContext
206{
207public:
208 GlobalContext(int buffer_size, LV2::HostContext& host);
209 void loadPlugins();
210 LV2_Feature const* const* features() const { return lv2_features.data(); }
211
212 using urid_map_t = boost::bimap<std::string, LV2_URID>;
213 LV2::HostContext& host;
214 int sampleRate = 44100;
215
216 std::vector<LV2_Options_Option> options;
217
218 LV2_URID urid_map_cur = 1;
219 ossia::hash_map<std::string, LV2_URID> urid_map_left;
220 ossia::hash_map<LV2_URID, std::string> urid_map_right;
221
222 LV2_URI_Map_Feature uri_map{};
223 LV2_URID uri_map_cur = 1;
224 ossia::hash_map<std::string, LV2_URID> uri_map_left;
225
226 LV2_URID_Map map{};
227 LV2_URID_Unmap unmap{};
228 LV2_Event_Feature event{};
229 LV2_Worker_Schedule worker{};
230 LV2_Worker_Schedule worker_state{};
231
232 LV2_Log_Log logger{};
233 LV2_Extension_Data_Feature ext_data{nullptr};
234
235 LV2_Resize_Port_Resize ext_port_resize{};
236 LV2_State_Make_Path state_make_path{};
237
238 LV2_Feature uri_map_feature{"http://lv2plug.in/ns/ext/uri-map", &uri_map};
239 LV2_Feature map_feature{LV2_URID__map, &map};
240 LV2_Feature unmap_feature{LV2_URID__unmap, &unmap};
241 LV2_Feature event_feature{LV2_EVENT_URI, &event};
242 LV2_Feature options_feature{LV2_OPTIONS__options, nullptr};
243 LV2_Feature worker_feature{LV2_WORKER__schedule, &worker};
244 LV2_Feature worker_state_feature{LV2_WORKER__schedule, &worker};
245 LV2_Feature logger_feature{LV2_LOG__log, &logger};
246 LV2_Feature ext_data_feature{LV2_DATA_ACCESS_URI, &ext_data};
247 LV2_Feature ext_port_resize_feature{LV2_RESIZE_PORT_URI, &ext_port_resize};
248 LV2_Feature state_make_path_feature{LV2_STATE__makePath, &state_make_path};
249
250 LV2_Feature state_load_default_feature{LV2_STATE__loadDefaultState, nullptr};
251 // LV2_Feature
252 // state_thread_safe_restore_feature{LV2_STATE__threadSafeRestore, nullptr};
253
254 LV2_Feature bounded{LV2_BUF_SIZE__boundedBlockLength, nullptr};
255 LV2_Feature pow2{LV2_BUF_SIZE__powerOf2BlockLength, nullptr};
256
257 std::vector<LV2_Feature*> lv2_features;
258
259 SuilHost* ui_host{};
260
261 const LV2_Feature data_feature{LV2_DATA_ACCESS_URI, &ext_data};
262};
263
264struct SCORE_PLUGIN_LV2_EXPORT LV2Data
265{
267
268 ~LV2Data() { }
269
270 LV2::HostContext& host;
271 LV2::EffectContext& effect;
272 ossia::small_vector<int, 4> audio_in_ports, audio_out_ports;
273 ossia::small_vector<int, 8> control_in_ports, control_out_ports, control_other_ports;
274 ossia::small_vector<int, 2> midi_in_ports, midi_out_ports, midi_other_ports, cv_ports;
275 ossia::small_vector<int, 2> atom_in_ports, atom_out_ports;
276
277 ossia::small_vector<int, 2> time_Position_ports{};
278
279 // ossia::small_vector<int, 2> atom_in_ports, atom_out_ports;
280};
281
283{
284 uint32_t index;
285 uint32_t protocol;
286 ossia::small_vector<uint8_t, 32> body;
287};
288
289SCORE_PLUGIN_LV2_EXPORT QString get_lv2_plugin_name(const Lilv::Plugin& node);
290}
291
292#if defined(__clang__) && defined(__has_warning)
293#pragma clang diagnostic pop
294#endif
Definition Context.hpp:191
Definition Context.hpp:206
Definition Context.hpp:60
Definition Context.hpp:165
Definition Context.hpp:265
Definition Context.hpp:283