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