3 * Copyright (C) 2011-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_LV2_UTILS_HPP_INCLUDED
19 #define CARLA_LV2_UTILS_HPP_INCLUDED
21 #include "CarlaMathUtils.hpp"
22 #include "CarlaStringList.hpp"
23 #include "CarlaMIDI.h"
30 // disable -Wdocumentation for LV2 headers
31 #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
32 # pragma clang diagnostic push
33 # pragma clang diagnostic ignored "-Wdocumentation"
38 #include "lv2/atom-forge.h"
39 #include "lv2/atom-helpers.h"
40 #include "lv2/atom-util.h"
41 #include "lv2/buf-size.h"
42 #include "lv2/data-access.h"
44 #include "lv2/event.h"
45 #include "lv2/event-helpers.h"
46 #include "lv2/inline-display.h"
47 #include "lv2/instance-access.h"
51 #include "lv2/midnam.h"
53 #include "lv2/options.h"
54 #include "lv2/parameters.h"
55 #include "lv2/patch.h"
56 #include "lv2/port-groups.h"
57 #include "lv2/port-props.h"
58 #include "lv2/presets.h"
59 #include "lv2/resize-port.h"
60 #include "lv2/state.h"
63 #include "lv2/units.h"
64 #include "lv2/uri-map.h"
66 #include "lv2/worker.h"
68 #include "lv2/lv2-miditype.h"
69 #include "lv2/lv2-midifunctions.h"
70 #include "lv2/lv2_external_ui.h"
71 #include "lv2/lv2_kxstudio_properties.h"
72 #include "lv2/lv2_programs.h"
73 #include "lv2/lv2_rtmempool.h"
75 #include "lv2/control-input-port-change-request.h"
77 #include "lilv/lilvmm.hpp"
78 #include "sratom/sratom.h"
79 #include "lilv/config/lilv_config.h"
81 // enable -Wdocumentation again
82 #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
83 # pragma clang diagnostic pop
86 #include "lv2_rdf.hpp"
88 #if defined(CARLA_UTILS_USE_QT)
89 # include <QtCore/QStringList>
91 # include "water/text/StringArray.h"
94 // used for scalepoint sorting
96 typedef std::map
<double,const LilvScalePoint
*> LilvScalePointMap
;
98 // --------------------------------------------------------------------------------------------------------------------
99 // Define namespaces and missing prefixes
101 #define NS_dct "http://purl.org/dc/terms/"
102 #define NS_doap "http://usefulinc.com/ns/doap#"
103 #define NS_rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
104 #define NS_rdfs "http://www.w3.org/2000/01/rdf-schema#"
105 #define NS_llmm "http://ll-plugins.nongnu.org/lv2/ext/midimap#"
106 #define NS_devp "http://lv2plug.in/ns/dev/extportinfo#"
107 #define NS_mod "http://moddevices.com/ns/modgui#"
109 #define LV2_MIDI_Map__CC "http://ll-plugins.nongnu.org/lv2/namespace#CC"
110 #define LV2_MIDI_Map__NRPN "http://ll-plugins.nongnu.org/lv2/namespace#NRPN"
112 #define LV2_MIDI_LL__MidiPort "http://ll-plugins.nongnu.org/lv2/ext/MidiPort"
114 #define LV2_UI__makeResident LV2_UI_PREFIX "makeResident"
115 #define LV2_UI__makeSONameResident LV2_UI_PREFIX "makeSONameResident"
117 // TODO: update LV2 headers once again
118 #define LV2_CORE__Parameter LV2_CORE_PREFIX "Parameter" ///< http://lv2plug.in/ns/lv2core#Parameter
119 #define LV2_CORE__enabled LV2_CORE_PREFIX "enabled" ///< http://lv2plug.in/ns/lv2core#enabled
120 #define LV2_CORE__isSideChain LV2_CORE_PREFIX "isSideChain" ///< http://lv2plug.in/ns/lv2core#isSideChain
122 // --------------------------------------------------------------------------------------------------------------------
125 struct LV2_Atom_MidiEvent
{
126 LV2_Atom atom
; /**< Atom header. */
127 uint8_t data
[4]; /**< MIDI data (body). */
131 uint32_t lv2_atom_total_size(const LV2_Atom_MidiEvent
& midiEv
)
133 return static_cast<uint32_t>(sizeof(LV2_Atom
)) + midiEv
.atom
.size
;
136 // ---------------------------------------------------------------------------------------------------------------------
137 // -Weffc++ compat ext widget
141 typedef struct _LV2_External_UI_Widget_Compat
{
142 void (*run
)(struct _LV2_External_UI_Widget_Compat
*);
143 void (*show
)(struct _LV2_External_UI_Widget_Compat
*);
144 void (*hide
)(struct _LV2_External_UI_Widget_Compat
*);
146 _LV2_External_UI_Widget_Compat() noexcept
147 : run(nullptr), show(nullptr), hide(nullptr) {}
149 } LV2_External_UI_Widget_Compat
;
153 // --------------------------------------------------------------------------------------------------------------------
154 // Our LV2 World class
156 class Lv2WorldClass
: public Lilv::World
162 Lilv::Node designation
;
163 Lilv::Node freeWheeling
;
164 Lilv::Node reportsLatency
;
167 Lilv::Node class_allpass
;
168 Lilv::Node class_amplifier
;
169 Lilv::Node class_analyzer
;
170 Lilv::Node class_bandpass
;
171 Lilv::Node class_chorus
;
172 Lilv::Node class_comb
;
173 Lilv::Node class_compressor
;
174 Lilv::Node class_constant
;
175 Lilv::Node class_converter
;
176 Lilv::Node class_delay
;
177 Lilv::Node class_distortion
;
178 Lilv::Node class_dynamics
;
180 Lilv::Node class_envelope
;
181 Lilv::Node class_expander
;
182 Lilv::Node class_filter
;
183 Lilv::Node class_flanger
;
184 Lilv::Node class_function
;
185 Lilv::Node class_gate
;
186 Lilv::Node class_generator
;
187 Lilv::Node class_highpass
;
188 Lilv::Node class_instrument
;
189 Lilv::Node class_limiter
;
190 Lilv::Node class_lowpass
;
191 Lilv::Node class_mixer
;
192 Lilv::Node class_modulator
;
193 Lilv::Node class_multiEQ
;
194 Lilv::Node class_oscillator
;
195 Lilv::Node class_paraEQ
;
196 Lilv::Node class_phaser
;
197 Lilv::Node class_pitch
;
198 Lilv::Node class_reverb
;
199 Lilv::Node class_simulator
;
200 Lilv::Node class_spatial
;
201 Lilv::Node class_spectral
;
202 Lilv::Node class_utility
;
203 Lilv::Node class_waveshaper
;
206 Lilv::Node port_input
;
207 Lilv::Node port_output
;
208 Lilv::Node port_control
;
209 Lilv::Node port_audio
;
211 Lilv::Node port_atom
;
212 Lilv::Node port_event
;
213 Lilv::Node port_midi
;
216 Lilv::Node pprop_optional
;
217 Lilv::Node pprop_enumeration
;
218 Lilv::Node pprop_integer
;
219 Lilv::Node pprop_isSideChain
;
220 Lilv::Node pprop_sampleRate
;
221 Lilv::Node pprop_toggled
;
222 Lilv::Node pprop_artifacts
;
223 Lilv::Node pprop_continuousCV
;
224 Lilv::Node pprop_discreteCV
;
225 Lilv::Node pprop_expensive
;
226 Lilv::Node pprop_strictBounds
;
227 Lilv::Node pprop_logarithmic
;
228 Lilv::Node pprop_notAutomatic
;
229 Lilv::Node pprop_notOnGUI
;
230 Lilv::Node pprop_trigger
;
231 Lilv::Node pprop_nonAutomatable
;
234 Lilv::Node unit_name
;
235 Lilv::Node unit_render
;
236 Lilv::Node unit_symbol
;
237 Lilv::Node unit_unit
;
246 Lilv::Node ui_windows
;
248 Lilv::Node ui_external
;
249 Lilv::Node ui_externalOld
;
252 Lilv::Node atom_bufferType
;
253 Lilv::Node atom_sequence
;
254 Lilv::Node atom_supports
;
257 Lilv::Node lv2_symbol
;
258 Lilv::Node patch_readable
;
259 Lilv::Node patch_writable
;
261 Lilv::Node pg_sideChainOf
;
262 Lilv::Node preset_preset
;
263 Lilv::Node state_state
;
265 Lilv::Node ui_portIndex
;
266 Lilv::Node ui_portNotif
;
267 Lilv::Node ui_protocol
;
269 Lilv::Node value_default
;
270 Lilv::Node value_minimum
;
271 Lilv::Node value_maximum
;
273 Lilv::Node rz_asLargeAs
;
274 Lilv::Node rz_minSize
;
277 Lilv::Node midi_binding
;
278 Lilv::Node midi_ctlrNumber
;
279 Lilv::Node midi_event
;
280 Lilv::Node patch_message
;
281 Lilv::Node time_position
;
284 Lilv::Node mm_defaultControl
;
285 Lilv::Node mm_controlType
;
286 Lilv::Node mm_controlNumber
;
289 Lilv::Node dct_replaces
;
290 Lilv::Node doap_license
;
292 Lilv::Node rdfs_comment
;
293 Lilv::Node rdfs_label
;
294 Lilv::Node rdfs_range
;
298 const LilvPlugins
* allPlugins
;
299 const LilvPlugin
** cachedPlugins
;
302 // ----------------------------------------------------------------------------------------------------------------
306 port (new_uri(LV2_CORE__port
)),
307 symbol (new_uri(LV2_CORE__symbol
)),
308 designation (new_uri(LV2_CORE__designation
)),
309 freeWheeling (new_uri(LV2_CORE__freeWheeling
)),
310 reportsLatency (new_uri(LV2_CORE__reportsLatency
)),
312 class_allpass (new_uri(LV2_CORE__AllpassPlugin
)),
313 class_amplifier (new_uri(LV2_CORE__AmplifierPlugin
)),
314 class_analyzer (new_uri(LV2_CORE__AnalyserPlugin
)),
315 class_bandpass (new_uri(LV2_CORE__BandpassPlugin
)),
316 class_chorus (new_uri(LV2_CORE__ChorusPlugin
)),
317 class_comb (new_uri(LV2_CORE__CombPlugin
)),
318 class_compressor (new_uri(LV2_CORE__CompressorPlugin
)),
319 class_constant (new_uri(LV2_CORE__ConstantPlugin
)),
320 class_converter (new_uri(LV2_CORE__ConverterPlugin
)),
321 class_delay (new_uri(LV2_CORE__DelayPlugin
)),
322 class_distortion (new_uri(LV2_CORE__DistortionPlugin
)),
323 class_dynamics (new_uri(LV2_CORE__DynamicsPlugin
)),
324 class_eq (new_uri(LV2_CORE__EQPlugin
)),
325 class_envelope (new_uri(LV2_CORE__EnvelopePlugin
)),
326 class_expander (new_uri(LV2_CORE__ExpanderPlugin
)),
327 class_filter (new_uri(LV2_CORE__FilterPlugin
)),
328 class_flanger (new_uri(LV2_CORE__FlangerPlugin
)),
329 class_function (new_uri(LV2_CORE__FunctionPlugin
)),
330 class_gate (new_uri(LV2_CORE__GatePlugin
)),
331 class_generator (new_uri(LV2_CORE__GeneratorPlugin
)),
332 class_highpass (new_uri(LV2_CORE__HighpassPlugin
)),
333 class_instrument (new_uri(LV2_CORE__InstrumentPlugin
)),
334 class_limiter (new_uri(LV2_CORE__LimiterPlugin
)),
335 class_lowpass (new_uri(LV2_CORE__LowpassPlugin
)),
336 class_mixer (new_uri(LV2_CORE__MixerPlugin
)),
337 class_modulator (new_uri(LV2_CORE__ModulatorPlugin
)),
338 class_multiEQ (new_uri(LV2_CORE__MultiEQPlugin
)),
339 class_oscillator (new_uri(LV2_CORE__OscillatorPlugin
)),
340 class_paraEQ (new_uri(LV2_CORE__ParaEQPlugin
)),
341 class_phaser (new_uri(LV2_CORE__PhaserPlugin
)),
342 class_pitch (new_uri(LV2_CORE__PitchPlugin
)),
343 class_reverb (new_uri(LV2_CORE__ReverbPlugin
)),
344 class_simulator (new_uri(LV2_CORE__SimulatorPlugin
)),
345 class_spatial (new_uri(LV2_CORE__SpatialPlugin
)),
346 class_spectral (new_uri(LV2_CORE__SpectralPlugin
)),
347 class_utility (new_uri(LV2_CORE__UtilityPlugin
)),
348 class_waveshaper (new_uri(LV2_CORE__WaveshaperPlugin
)),
350 port_input (new_uri(LV2_CORE__InputPort
)),
351 port_output (new_uri(LV2_CORE__OutputPort
)),
352 port_control (new_uri(LV2_CORE__ControlPort
)),
353 port_audio (new_uri(LV2_CORE__AudioPort
)),
354 port_cv (new_uri(LV2_CORE__CVPort
)),
355 port_atom (new_uri(LV2_ATOM__AtomPort
)),
356 port_event (new_uri(LV2_EVENT__EventPort
)),
357 port_midi (new_uri(LV2_MIDI_LL__MidiPort
)),
359 pprop_optional (new_uri(LV2_CORE__connectionOptional
)),
360 pprop_enumeration (new_uri(LV2_CORE__enumeration
)),
361 pprop_integer (new_uri(LV2_CORE__integer
)),
362 pprop_isSideChain (new_uri(LV2_CORE__isSideChain
)),
363 pprop_sampleRate (new_uri(LV2_CORE__sampleRate
)),
364 pprop_toggled (new_uri(LV2_CORE__toggled
)),
365 pprop_artifacts (new_uri(LV2_PORT_PROPS__causesArtifacts
)),
366 pprop_continuousCV (new_uri(LV2_PORT_PROPS__continuousCV
)),
367 pprop_discreteCV (new_uri(LV2_PORT_PROPS__discreteCV
)),
368 pprop_expensive (new_uri(LV2_PORT_PROPS__expensive
)),
369 pprop_strictBounds (new_uri(LV2_PORT_PROPS__hasStrictBounds
)),
370 pprop_logarithmic (new_uri(LV2_PORT_PROPS__logarithmic
)),
371 pprop_notAutomatic (new_uri(LV2_PORT_PROPS__notAutomatic
)),
372 pprop_notOnGUI (new_uri(LV2_PORT_PROPS__notOnGUI
)),
373 pprop_trigger (new_uri(LV2_PORT_PROPS__trigger
)),
374 pprop_nonAutomatable (new_uri(LV2_KXSTUDIO_PROPERTIES__NonAutomatable
)),
376 unit_name (new_uri(LV2_UNITS__name
)),
377 unit_render (new_uri(LV2_UNITS__render
)),
378 unit_symbol (new_uri(LV2_UNITS__symbol
)),
379 unit_unit (new_uri(LV2_UNITS__unit
)),
381 ui (new_uri(LV2_UI__UI
)),
382 ui_gtk2 (new_uri(LV2_UI__GtkUI
)),
383 ui_gtk3 (new_uri(LV2_UI__Gtk3UI
)),
384 ui_qt4 (new_uri(LV2_UI__Qt4UI
)),
385 ui_qt5 (new_uri(LV2_UI__Qt5UI
)),
386 ui_cocoa (new_uri(LV2_UI__CocoaUI
)),
387 ui_windows (new_uri(LV2_UI__WindowsUI
)),
388 ui_x11 (new_uri(LV2_UI__X11UI
)),
389 ui_external (new_uri(LV2_EXTERNAL_UI__Widget
)),
390 ui_externalOld (new_uri(LV2_EXTERNAL_UI_DEPRECATED_URI
)),
392 atom_bufferType (new_uri(LV2_ATOM__bufferType
)),
393 atom_sequence (new_uri(LV2_ATOM__Sequence
)),
394 atom_supports (new_uri(LV2_ATOM__supports
)),
396 lv2_name (new_uri(LV2_CORE__name
)),
397 lv2_symbol (new_uri(LV2_CORE__symbol
)),
398 patch_readable (new_uri(LV2_PATCH__readable
)),
399 patch_writable (new_uri(LV2_PATCH__writable
)),
400 pg_group (new_uri(LV2_PORT_GROUPS__group
)),
401 pg_sideChainOf (new_uri(LV2_PORT_GROUPS__sideChainOf
)),
402 preset_preset (new_uri(LV2_PRESETS__Preset
)),
403 state_state (new_uri(LV2_STATE__state
)),
405 ui_portIndex (new_uri(LV2_UI__portIndex
)),
406 ui_portNotif (new_uri(LV2_UI__portNotification
)),
407 ui_protocol (new_uri(LV2_UI__protocol
)),
409 value_default (new_uri(LV2_CORE__default
)),
410 value_minimum (new_uri(LV2_CORE__minimum
)),
411 value_maximum (new_uri(LV2_CORE__maximum
)),
413 rz_asLargeAs (new_uri(LV2_RESIZE_PORT__asLargeAs
)),
414 rz_minSize (new_uri(LV2_RESIZE_PORT__minimumSize
)),
416 midi_binding (new_uri(LV2_MIDI__binding
)),
417 midi_ctlrNumber (new_uri(LV2_MIDI__controllerNumber
)),
418 midi_event (new_uri(LV2_MIDI__MidiEvent
)),
419 patch_message (new_uri(LV2_PATCH__Message
)),
420 time_position (new_uri(LV2_TIME__Position
)),
422 mm_defaultControl (new_uri(NS_llmm
"defaultMidiController")),
423 mm_controlType (new_uri(NS_llmm
"controllerType")),
424 mm_controlNumber (new_uri(NS_llmm
"controllerNumber")),
426 dct_replaces (new_uri(NS_dct
"replaces")),
427 doap_license (new_uri(NS_doap
"license")),
428 rdf_type (new_uri(NS_rdf
"type")),
429 rdfs_comment (new_uri(NS_rdfs
"comment")),
430 rdfs_label (new_uri(NS_rdfs
"label")),
431 rdfs_range (new_uri(NS_rdfs
"range")),
435 cachedPlugins(nullptr),
438 ~Lv2WorldClass() override
441 allPlugins
= nullptr;
443 if (cachedPlugins
!= nullptr)
445 delete[] cachedPlugins
;
446 cachedPlugins
= nullptr;
450 // FIXME - remove this
451 static Lv2WorldClass
& getInstance()
453 static Lv2WorldClass lv2World
;
457 void initIfNeeded(const char* LV2_PATH
)
459 if (LV2_PATH
== nullptr || LV2_PATH
[0] == '\0')
461 static const char* const DEFAULT_LV2_PATH
= LILV_DEFAULT_LV2_PATH
;
462 LV2_PATH
= DEFAULT_LV2_PATH
;
470 Lilv::World::load_all(LV2_PATH
);
472 allPlugins
= lilv_world_get_all_plugins(this->me
);
473 CARLA_SAFE_ASSERT_RETURN(allPlugins
!= nullptr,);
475 if ((pluginCount
= lilv_plugins_size(allPlugins
)))
477 cachedPlugins
= new const LilvPlugin
*[pluginCount
+1];
478 carla_zeroPointers(cachedPlugins
, pluginCount
+1);
481 for (LilvIter
* it
= lilv_plugins_begin(allPlugins
); ! lilv_plugins_is_end(allPlugins
, it
); it
= lilv_plugins_next(allPlugins
, it
))
482 cachedPlugins
[i
++] = lilv_plugins_get(allPlugins
, it
);
486 void load_bundle(const char* const bundle
)
488 CARLA_SAFE_ASSERT_RETURN(bundle
!= nullptr && bundle
[0] != '\0',);
489 CARLA_SAFE_ASSERT_RETURN(needsInit
,);
492 Lilv::World::load_bundle(Lilv::Node(new_uri(bundle
)));
494 allPlugins
= lilv_world_get_all_plugins(this->me
);
495 CARLA_SAFE_ASSERT_RETURN(allPlugins
!= nullptr,);
497 if ((pluginCount
= lilv_plugins_size(allPlugins
)))
499 cachedPlugins
= new const LilvPlugin
*[pluginCount
+1];
500 carla_zeroPointers(cachedPlugins
, pluginCount
+1);
503 for (LilvIter
* it
= lilv_plugins_begin(allPlugins
); ! lilv_plugins_is_end(allPlugins
, it
); it
= lilv_plugins_next(allPlugins
, it
))
504 cachedPlugins
[i
++] = lilv_plugins_get(allPlugins
, it
);
508 uint
getPluginCount() const
510 CARLA_SAFE_ASSERT_RETURN(! needsInit
, 0);
515 const LilvPlugin
* getPluginFromIndex(const uint index
) const
517 CARLA_SAFE_ASSERT_RETURN(! needsInit
, nullptr);
518 CARLA_SAFE_ASSERT_RETURN(cachedPlugins
!= nullptr, nullptr);
519 CARLA_SAFE_ASSERT_RETURN(index
< pluginCount
, nullptr);
521 return cachedPlugins
[index
];
524 const LilvPlugin
* getPluginFromURI(const LV2_URI uri
) const
526 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', nullptr);
527 CARLA_SAFE_ASSERT_RETURN(! needsInit
, nullptr);
528 CARLA_SAFE_ASSERT_RETURN(allPlugins
!= nullptr, nullptr);
530 LilvNode
* const uriNode(lilv_new_uri(this->me
, uri
));
531 CARLA_SAFE_ASSERT_RETURN(uriNode
!= nullptr, nullptr);
533 const LilvPlugin
* const cPlugin(lilv_plugins_get_by_uri(allPlugins
, uriNode
));
534 lilv_node_free(uriNode
);
539 LilvState
* getStateFromURI(const LV2_URI uri
, const LV2_URID_Map
* const uridMap
) const
541 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', nullptr);
542 CARLA_SAFE_ASSERT_RETURN(uridMap
!= nullptr, nullptr);
543 CARLA_SAFE_ASSERT_RETURN(! needsInit
, nullptr);
545 LilvNode
* const uriNode(lilv_new_uri(this->me
, uri
));
546 CARLA_SAFE_ASSERT_RETURN(uriNode
!= nullptr, nullptr);
548 CARLA_SAFE_ASSERT(lilv_world_load_resource(this->me
, uriNode
) >= 0);
550 LilvState
* const cState(lilv_state_new_from_world(this->me
, uridMap
, uriNode
));
551 lilv_node_free(uriNode
);
556 CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
557 CARLA_DECLARE_NON_COPYABLE(Lv2WorldClass
)
560 // --------------------------------------------------------------------------------------------------------------------
561 // Our LV2 Plugin base class
563 #if defined(__clang__)
564 # pragma clang diagnostic push
565 # pragma clang diagnostic ignored "-Weffc++"
566 # pragma clang diagnostic ignored "-Wnon-virtual-dtor"
567 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
568 # pragma GCC diagnostic push
569 # pragma GCC diagnostic ignored "-Weffc++"
570 # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
572 template<class TimeInfoStruct
>
573 class Lv2PluginBaseClass
: public LV2_External_UI_Widget_Compat
575 #if defined(__clang__)
576 # pragma clang diagnostic pop
577 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
578 # pragma GCC diagnostic pop
581 Lv2PluginBaseClass(const double sampleRate
, const LV2_Feature
* const* const features
)
584 fUsingNominal(false),
586 fSampleRate(sampleRate
),
591 fInlineDisplay(nullptr),
602 if (fSampleRate
< 1.0)
604 carla_stderr("Host doesn't provide a valid sample rate");
608 const LV2_State_Free_Path
* freePath
= nullptr;
609 const LV2_Options_Option
* options
= nullptr;
610 const LV2_URID_Map
* uridMap
= nullptr;
611 const LV2_URID_Unmap
* uridUnmap
= nullptr;
612 const LV2_Worker_Schedule
* worker
= nullptr;
613 const LV2_Inline_Display
* idisp
= nullptr;
615 for (int i
=0; features
[i
] != nullptr; ++i
)
617 /**/ if (std::strcmp(features
[i
]->URI
, LV2_STATE__freePath
) == 0)
618 freePath
= (const LV2_State_Free_Path
*)features
[i
]->data
;
619 else if (std::strcmp(features
[i
]->URI
, LV2_OPTIONS__options
) == 0)
620 options
= (const LV2_Options_Option
*)features
[i
]->data
;
621 else if (std::strcmp(features
[i
]->URI
, LV2_URID__map
) == 0)
622 uridMap
= (const LV2_URID_Map
*)features
[i
]->data
;
623 else if (std::strcmp(features
[i
]->URI
, LV2_URID__unmap
) == 0)
624 uridUnmap
= (const LV2_URID_Unmap
*)features
[i
]->data
;
625 else if (std::strcmp(features
[i
]->URI
, LV2_WORKER__schedule
) == 0)
626 worker
= (const LV2_Worker_Schedule
*)features
[i
]->data
;
627 else if (std::strcmp(features
[i
]->URI
, LV2_INLINEDISPLAY__queue_draw
) == 0)
628 idisp
= (const LV2_Inline_Display
*)features
[i
]->data
;
631 if (options
== nullptr || uridMap
== nullptr)
633 carla_stderr("Host doesn't provide option and urid-map features");
637 for (int i
=0; options
[i
].key
!= 0; ++i
)
639 if (uridUnmap
!= nullptr) {
640 carla_debug("Host option %i:\"%s\"", i
, uridUnmap
->unmap(uridUnmap
->handle
, options
[i
].key
));
643 if (options
[i
].key
== uridMap
->map(uridMap
->handle
, LV2_BUF_SIZE__nominalBlockLength
))
645 if (options
[i
].type
== uridMap
->map(uridMap
->handle
, LV2_ATOM__Int
))
647 const int32_t value(*(const int32_t*)options
[i
].value
);
648 CARLA_SAFE_ASSERT_CONTINUE(value
> 0);
650 fBufferSize
= static_cast<uint32_t>(value
);
651 fUsingNominal
= true;
655 carla_stderr("Host provides nominalBlockLength but has wrong value type");
660 if (options
[i
].key
== uridMap
->map(uridMap
->handle
, LV2_BUF_SIZE__maxBlockLength
))
662 if (options
[i
].type
== uridMap
->map(uridMap
->handle
, LV2_ATOM__Int
))
664 const int32_t value(*(const int32_t*)options
[i
].value
);
665 CARLA_SAFE_ASSERT_CONTINUE(value
> 0);
667 fBufferSize
= static_cast<uint32_t>(value
);
671 carla_stderr("Host provides maxBlockLength but has wrong value type");
673 // no break, continue in case host supports nominalBlockLength
677 if (fBufferSize
== 0)
679 carla_stderr("Host doesn't provide buffer-size feature");
681 // as testing, continue for now
688 fFreePath
= freePath
;
689 fUridUnmap
= uridUnmap
;
691 fInlineDisplay
= idisp
;
696 virtual ~Lv2PluginBaseClass() {}
698 bool loadedInProperHost() const noexcept
700 return fUridMap
!= nullptr && fBufferSize
!= 0;
703 // ----------------------------------------------------------------------------------------------------------------
705 void lv2_connect_port(const uint32_t port
, void* const dataLocation
) noexcept
707 fPorts
.connectPort(port
, dataLocation
);
710 bool lv2_pre_run(const uint32_t frames
)
712 CARLA_SAFE_ASSERT_RETURN(fIsActive
, false);
714 fIsOffline
= (fPorts
.freewheel
!= nullptr && *fPorts
.freewheel
>= 0.5f
);
716 // cache midi events and time information first
719 LV2_ATOM_SEQUENCE_FOREACH(fPorts
.eventsIn
[0], event
)
721 if (event
== nullptr)
723 if (event
->body
.type
!= fURIs
.atomBlank
&& event
->body
.type
!= fURIs
.atomObject
)
726 const LV2_Atom_Object
* const obj((const LV2_Atom_Object
*)&event
->body
);
728 if (obj
->body
.otype
!= fURIs
.timePos
)
731 LV2_Atom
* bar
= nullptr;
732 LV2_Atom
* barBeat
= nullptr;
733 LV2_Atom
* beatUnit
= nullptr;
734 LV2_Atom
* beatsPerBar
= nullptr;
735 LV2_Atom
* beatsPerMinute
= nullptr;
736 LV2_Atom
* frame
= nullptr;
737 LV2_Atom
* speed
= nullptr;
738 LV2_Atom
* ticksPerBeat
= nullptr;
740 lv2_atom_object_get(obj
,
742 fURIs
.timeBarBeat
, &barBeat
,
743 fURIs
.timeBeatUnit
, &beatUnit
,
744 fURIs
.timeBeatsPerBar
, &beatsPerBar
,
745 fURIs
.timeBeatsPerMinute
, &beatsPerMinute
,
746 fURIs
.timeFrame
, &frame
,
747 fURIs
.timeSpeed
, &speed
,
748 fURIs
.timeTicksPerBeat
, &ticksPerBeat
,
751 // need to handle this first as other values depend on it
752 if (ticksPerBeat
!= nullptr)
754 double ticksPerBeatValue
= -1.0;
756 /**/ if (ticksPerBeat
->type
== fURIs
.atomDouble
)
757 ticksPerBeatValue
= ((LV2_Atom_Double
*)ticksPerBeat
)->body
;
758 else if (ticksPerBeat
->type
== fURIs
.atomFloat
)
759 ticksPerBeatValue
= ((LV2_Atom_Float
*)ticksPerBeat
)->body
;
760 else if (ticksPerBeat
->type
== fURIs
.atomInt
)
761 ticksPerBeatValue
= static_cast<double>(((LV2_Atom_Int
*)ticksPerBeat
)->body
);
762 else if (ticksPerBeat
->type
== fURIs
.atomLong
)
763 ticksPerBeatValue
= static_cast<double>(((LV2_Atom_Long
*)ticksPerBeat
)->body
);
765 carla_stderr("Unknown lv2 ticksPerBeat value type");
767 if (ticksPerBeatValue
> 0.0)
768 fTimeInfo
.bbt
.ticksPerBeat
= fLastPositionData
.ticksPerBeat
= ticksPerBeatValue
;
770 carla_stderr("Invalid lv2 ticksPerBeat value");
774 if (speed
!= nullptr)
776 /**/ if (speed
->type
== fURIs
.atomDouble
)
777 fLastPositionData
.speed
= ((LV2_Atom_Double
*)speed
)->body
;
778 else if (speed
->type
== fURIs
.atomFloat
)
779 fLastPositionData
.speed
= ((LV2_Atom_Float
*)speed
)->body
;
780 else if (speed
->type
== fURIs
.atomInt
)
781 fLastPositionData
.speed
= static_cast<double>(((LV2_Atom_Int
*)speed
)->body
);
782 else if (speed
->type
== fURIs
.atomLong
)
783 fLastPositionData
.speed
= static_cast<double>(((LV2_Atom_Long
*)speed
)->body
);
785 carla_stderr("Unknown lv2 speed value type");
787 fTimeInfo
.playing
= carla_isNotZero(fLastPositionData
.speed
);
789 if (fTimeInfo
.playing
&& fLastPositionData
.beatsPerMinute
> 0.0)
791 fTimeInfo
.bbt
.beatsPerMinute
= fLastPositionData
.beatsPerMinute
*
792 std::abs(fLastPositionData
.speed
);
798 int64_t barValue
= -1;
800 /**/ if (bar
->type
== fURIs
.atomDouble
)
801 barValue
= static_cast<int64_t>(((LV2_Atom_Double
*)bar
)->body
);
802 else if (bar
->type
== fURIs
.atomFloat
)
803 barValue
= static_cast<int64_t>(((LV2_Atom_Float
*)bar
)->body
);
804 else if (bar
->type
== fURIs
.atomInt
)
805 barValue
= ((LV2_Atom_Int
*)bar
)->body
;
806 else if (bar
->type
== fURIs
.atomLong
)
807 barValue
= ((LV2_Atom_Long
*)bar
)->body
;
809 carla_stderr("Unknown lv2 bar value type");
811 if (barValue
>= 0 && barValue
< INT32_MAX
)
813 fLastPositionData
.bar
= static_cast<int32_t>(barValue
);
814 fLastPositionData
.bar_f
= static_cast<float>(barValue
);
815 fTimeInfo
.bbt
.bar
= fLastPositionData
.bar
+ 1;
819 carla_stderr("Invalid lv2 bar value");
823 if (barBeat
!= nullptr)
825 double barBeatValue
= -1.0;
827 /**/ if (barBeat
->type
== fURIs
.atomDouble
)
828 barBeatValue
= ((LV2_Atom_Double
*)barBeat
)->body
;
829 else if (barBeat
->type
== fURIs
.atomFloat
)
830 barBeatValue
= ((LV2_Atom_Float
*)barBeat
)->body
;
831 else if (barBeat
->type
== fURIs
.atomInt
)
832 barBeatValue
= static_cast<float>(((LV2_Atom_Int
*)barBeat
)->body
);
833 else if (barBeat
->type
== fURIs
.atomLong
)
834 barBeatValue
= static_cast<float>(((LV2_Atom_Long
*)barBeat
)->body
);
836 carla_stderr("Unknown lv2 barBeat value type");
838 if (barBeatValue
>= 0.0)
840 fLastPositionData
.barBeat
= static_cast<float>(barBeatValue
);
842 const double rest
= std::fmod(barBeatValue
, 1.0);
843 fTimeInfo
.bbt
.beat
= static_cast<int32_t>(barBeatValue
-rest
+1.0);
844 fTimeInfo
.bbt
.tick
= static_cast<int32_t>(rest
*fTimeInfo
.bbt
.ticksPerBeat
+0.5);
848 carla_stderr("Invalid lv2 barBeat value");
852 if (beatUnit
!= nullptr)
854 int64_t beatUnitValue
= -1;
856 /**/ if (beatUnit
->type
== fURIs
.atomDouble
)
857 beatUnitValue
= static_cast<int64_t>(((LV2_Atom_Double
*)beatUnit
)->body
);
858 else if (beatUnit
->type
== fURIs
.atomFloat
)
859 beatUnitValue
= static_cast<int64_t>(((LV2_Atom_Float
*)beatUnit
)->body
);
860 else if (beatUnit
->type
== fURIs
.atomInt
)
861 beatUnitValue
= ((LV2_Atom_Int
*)beatUnit
)->body
;
862 else if (beatUnit
->type
== fURIs
.atomLong
)
863 beatUnitValue
= ((LV2_Atom_Long
*)beatUnit
)->body
;
865 carla_stderr("Unknown lv2 beatUnit value type");
867 if (beatUnitValue
> 0 && beatUnitValue
< UINT32_MAX
)
869 fLastPositionData
.beatUnit
= static_cast<uint32_t>(beatUnitValue
);
870 fTimeInfo
.bbt
.beatType
= static_cast<float>(beatUnitValue
);
874 carla_stderr("Invalid lv2 beatUnit value");
878 if (beatsPerBar
!= nullptr)
880 float beatsPerBarValue
= -1.0f
;
882 /**/ if (beatsPerBar
->type
== fURIs
.atomDouble
)
883 beatsPerBarValue
= static_cast<float>(((LV2_Atom_Double
*)beatsPerBar
)->body
);
884 else if (beatsPerBar
->type
== fURIs
.atomFloat
)
885 beatsPerBarValue
= ((LV2_Atom_Float
*)beatsPerBar
)->body
;
886 else if (beatsPerBar
->type
== fURIs
.atomInt
)
887 beatsPerBarValue
= static_cast<float>(((LV2_Atom_Int
*)beatsPerBar
)->body
);
888 else if (beatsPerBar
->type
== fURIs
.atomLong
)
889 beatsPerBarValue
= static_cast<float>(((LV2_Atom_Long
*)beatsPerBar
)->body
);
891 carla_stderr("Unknown lv2 beatsPerBar value type");
893 if (beatsPerBarValue
> 0.0f
)
894 fTimeInfo
.bbt
.beatsPerBar
= fLastPositionData
.beatsPerBar
= beatsPerBarValue
;
896 carla_stderr("Invalid lv2 beatsPerBar value");
899 if (beatsPerMinute
!= nullptr)
901 double beatsPerMinuteValue
= -1.0;
903 /**/ if (beatsPerMinute
->type
== fURIs
.atomDouble
)
904 beatsPerMinuteValue
= ((LV2_Atom_Double
*)beatsPerMinute
)->body
;
905 else if (beatsPerMinute
->type
== fURIs
.atomFloat
)
906 beatsPerMinuteValue
= ((LV2_Atom_Float
*)beatsPerMinute
)->body
;
907 else if (beatsPerMinute
->type
== fURIs
.atomInt
)
908 beatsPerMinuteValue
= static_cast<double>(((LV2_Atom_Int
*)beatsPerMinute
)->body
);
909 else if (beatsPerMinute
->type
== fURIs
.atomLong
)
910 beatsPerMinuteValue
= static_cast<double>(((LV2_Atom_Long
*)beatsPerMinute
)->body
);
912 carla_stderr("Unknown lv2 beatsPerMinute value type");
914 if (beatsPerMinuteValue
>= 12.0 && beatsPerMinuteValue
<= 999.0)
916 fTimeInfo
.bbt
.beatsPerMinute
= fLastPositionData
.beatsPerMinute
= beatsPerMinuteValue
;
918 if (carla_isNotZero(fLastPositionData
.speed
))
919 fTimeInfo
.bbt
.beatsPerMinute
*= std::abs(fLastPositionData
.speed
);
923 carla_stderr("Invalid lv2 beatsPerMinute value");
927 if (frame
!= nullptr)
929 int64_t frameValue
= -1;
931 /**/ if (frame
->type
== fURIs
.atomDouble
)
932 frameValue
= static_cast<int64_t>(((LV2_Atom_Double
*)frame
)->body
);
933 else if (frame
->type
== fURIs
.atomFloat
)
934 frameValue
= static_cast<int64_t>(((LV2_Atom_Float
*)frame
)->body
);
935 else if (frame
->type
== fURIs
.atomInt
)
936 frameValue
= ((LV2_Atom_Int
*)frame
)->body
;
937 else if (frame
->type
== fURIs
.atomLong
)
938 frameValue
= ((LV2_Atom_Long
*)frame
)->body
;
940 carla_stderr("Unknown lv2 frame value type");
943 fTimeInfo
.frame
= fLastPositionData
.frame
= static_cast<uint64_t>(frameValue
);
945 carla_stderr("Invalid lv2 frame value");
948 fTimeInfo
.bbt
.barStartTick
= static_cast<double>(fTimeInfo
.bbt
.ticksPerBeat
) *
949 static_cast<double>(fTimeInfo
.bbt
.beatsPerBar
) *
950 (fTimeInfo
.bbt
.bar
-1);
952 fTimeInfo
.bbt
.valid
= (fLastPositionData
.beatsPerMinute
> 0.0 &&
953 fLastPositionData
.beatUnit
> 0 &&
954 fLastPositionData
.beatsPerBar
> 0.0f
);
958 // Check for updated parameters
961 for (uint32_t i
=0; i
< fPorts
.numParams
; ++i
)
963 if (fPorts
.paramsOut
[i
])
966 CARLA_SAFE_ASSERT_CONTINUE(fPorts
.paramsPtr
[i
] != nullptr)
968 curValue
= *fPorts
.paramsPtr
[i
];
970 if (carla_isEqual(fPorts
.paramsLast
[i
], curValue
))
973 fPorts
.paramsLast
[i
] = curValue
;
974 handleParameterValueChanged(i
, curValue
);
977 // init event out data
978 if (fPorts
.numMidiOuts
> 0 || fPorts
.hasUI
)
980 const uint32_t count
= fPorts
.numMidiOuts
> 0 ? fPorts
.numMidiOuts
: 1;
982 for (uint32_t i
=0; i
< count
; ++i
)
984 LV2_Atom_Sequence
* const seq(fPorts
.eventsOut
[i
]);
985 CARLA_SAFE_ASSERT_CONTINUE(seq
!= nullptr);
987 fPorts
.eventsOutData
[i
].capacity
= seq
->atom
.size
;
988 fPorts
.eventsOutData
[i
].offset
= 0;
990 seq
->atom
.size
= sizeof(LV2_Atom_Sequence_Body
);
991 seq
->atom
.type
= fURIs
.atomSequence
;
1003 void lv2_post_run(const uint32_t frames
)
1005 // update timePos for next callback
1007 if (carla_isZero(fLastPositionData
.speed
))
1010 if (fLastPositionData
.speed
> 0.0)
1013 fLastPositionData
.frame
+= frames
;
1017 // playing backwards
1018 if (frames
>= fLastPositionData
.frame
)
1019 fLastPositionData
.frame
= 0;
1021 fLastPositionData
.frame
-= frames
;
1024 fTimeInfo
.frame
= fLastPositionData
.frame
;
1026 if (fTimeInfo
.bbt
.valid
)
1028 const double beatsPerMinute
= fLastPositionData
.beatsPerMinute
* fLastPositionData
.speed
;
1029 const double framesPerBeat
= 60.0 * fSampleRate
/ beatsPerMinute
;
1030 const double addedBarBeats
= double(frames
) / framesPerBeat
;
1032 if (fLastPositionData
.barBeat
>= 0.0f
)
1034 fLastPositionData
.barBeat
= std::fmod(fLastPositionData
.barBeat
+static_cast<float>(addedBarBeats
),
1035 fLastPositionData
.beatsPerBar
);
1037 const double rest
= std::fmod(fLastPositionData
.barBeat
, 1.0f
);
1038 fTimeInfo
.bbt
.beat
= static_cast<int32_t>(static_cast<double>(fLastPositionData
.barBeat
)-rest
+1.0);
1039 fTimeInfo
.bbt
.tick
= rest
* fTimeInfo
.bbt
.ticksPerBeat
;
1041 if (fLastPositionData
.bar_f
>= 0.0f
)
1043 fLastPositionData
.bar_f
+= std::floor((fLastPositionData
.barBeat
+static_cast<float>(addedBarBeats
))/
1044 fLastPositionData
.beatsPerBar
);
1046 if (fLastPositionData
.bar_f
<= 0.0f
)
1048 fLastPositionData
.bar
= 0;
1049 fLastPositionData
.bar_f
= 0.0f
;
1053 fLastPositionData
.bar
= static_cast<int32_t>(fLastPositionData
.bar_f
+0.5f
);
1056 fTimeInfo
.bbt
.bar
= fLastPositionData
.bar
+ 1;
1058 fTimeInfo
.bbt
.barStartTick
= static_cast<double>(fTimeInfo
.bbt
.ticksPerBeat
) *
1059 static_cast<double>(fTimeInfo
.bbt
.beatsPerBar
) *
1060 (fTimeInfo
.bbt
.bar
-1);
1066 // ----------------------------------------------------------------------------------------------------------------
1068 uint32_t lv2_get_options(LV2_Options_Option
* const /*options*/) const
1071 return LV2_OPTIONS_SUCCESS
;
1074 uint32_t lv2_set_options(const LV2_Options_Option
* const options
)
1076 for (int i
=0; options
[i
].key
!= 0; ++i
)
1078 if (options
[i
].key
== fUridMap
->map(fUridMap
->handle
, LV2_BUF_SIZE__nominalBlockLength
))
1080 if (options
[i
].type
== fURIs
.atomInt
)
1082 const int32_t value(*(const int32_t*)options
[i
].value
);
1083 CARLA_SAFE_ASSERT_CONTINUE(value
> 0);
1085 const uint32_t newBufferSize
= static_cast<uint32_t>(value
);
1087 if (fBufferSize
!= newBufferSize
)
1089 fBufferSize
= newBufferSize
;
1090 handleBufferSizeChanged(newBufferSize
);
1095 carla_stderr("Host changed nominalBlockLength but with wrong value type");
1098 else if (options
[i
].key
== fUridMap
->map(fUridMap
->handle
, LV2_BUF_SIZE__maxBlockLength
) && ! fUsingNominal
)
1100 if (options
[i
].type
== fURIs
.atomInt
)
1102 const int32_t value(*(const int32_t*)options
[i
].value
);
1103 CARLA_SAFE_ASSERT_CONTINUE(value
> 0);
1105 const uint32_t newBufferSize
= static_cast<uint32_t>(value
);
1107 if (fBufferSize
!= newBufferSize
)
1109 fBufferSize
= newBufferSize
;
1110 handleBufferSizeChanged(newBufferSize
);
1115 carla_stderr("Host changed maxBlockLength but with wrong value type");
1118 else if (options
[i
].key
== fUridMap
->map(fUridMap
->handle
, LV2_PARAMETERS__sampleRate
))
1120 if (options
[i
].type
== fURIs
.atomFloat
)
1122 const double value(*(const float*)options
[i
].value
);
1123 CARLA_SAFE_ASSERT_CONTINUE(value
> 0.0);
1125 if (carla_isNotEqual(fSampleRate
, value
))
1127 fSampleRate
= value
;
1128 handleSampleRateChanged(value
);
1133 carla_stderr("Host changed sampleRate but with wrong value type");
1138 return LV2_OPTIONS_SUCCESS
;
1141 // ----------------------------------------------------------------------------------------------------------------
1143 int lv2ui_idle() const
1145 if (! fUI
.isVisible
)
1164 void lv2ui_cleanup()
1170 fUI
.touch
= nullptr;
1171 fUI
.writeFunction
= nullptr;
1172 fUI
.controller
= nullptr;
1175 // ----------------------------------------------------------------------------------------------------------------
1178 virtual void handleUiRun() const = 0;
1179 virtual void handleUiShow() = 0;
1180 virtual void handleUiHide() = 0;
1182 virtual void handleParameterValueChanged(const uint32_t index
, const float value
) = 0;
1183 virtual void handleBufferSizeChanged(const uint32_t bufferSize
) = 0;
1184 virtual void handleSampleRateChanged(const double sampleRate
) = 0;
1186 void resetTimeInfo() noexcept
1190 // hosts may not send all values, resulting on some invalid data
1191 fTimeInfo
.bbt
.bar
= 1;
1192 fTimeInfo
.bbt
.beat
= 1;
1193 fTimeInfo
.bbt
.beatsPerBar
= 4;
1194 fTimeInfo
.bbt
.beatType
= 4;
1195 fTimeInfo
.bbt
.ticksPerBeat
= fLastPositionData
.ticksPerBeat
= 960.0;
1196 fTimeInfo
.bbt
.beatsPerMinute
= fLastPositionData
.beatsPerMinute
= 120.0;
1201 bool fIsOffline
: 1;
1202 bool fUsingNominal
: 1;
1203 uint32_t fBufferSize
;
1206 // LV2 host features
1207 const LV2_State_Free_Path
* fFreePath
;
1208 const LV2_URID_Map
* fUridMap
;
1209 const LV2_URID_Unmap
* fUridUnmap
;
1210 const LV2_Worker_Schedule
* fWorker
;
1211 const LV2_Inline_Display
* fInlineDisplay
;
1214 TimeInfoStruct fTimeInfo
;
1216 struct Lv2PositionData
{
1222 double beatsPerMinute
;
1225 double ticksPerBeat
;
1233 beatsPerMinute(-1.0),
1236 ticksPerBeat(-1.0) {}
1245 beatsPerMinute
= -1.0;
1248 ticksPerBeat
= -1.0;
1251 } fLastPositionData
;
1255 // need to save current state
1256 struct EventsOutData
{
1266 uint32_t indexOffset
;
1267 uint32_t numAudioIns
;
1268 uint32_t numAudioOuts
;
1271 uint32_t numMidiIns
;
1272 uint32_t numMidiOuts
;
1278 const LV2_Atom_Sequence
** eventsIn
;
1279 /* */ LV2_Atom_Sequence
** eventsOut
;
1280 /* */ EventsOutData
* eventsOutData
;
1281 /* */ float** audioCVIns
;
1282 /* */ float** audioCVOuts
;
1283 /* */ float* freewheel
;
1285 // cached parameter values
1303 eventsOutData(nullptr),
1304 audioCVIns(nullptr),
1305 audioCVOuts(nullptr),
1307 paramsLast(nullptr),
1309 paramsOut(nullptr) {}
1313 if (eventsIn
!= nullptr)
1319 if (eventsOut
!= nullptr)
1322 eventsOut
= nullptr;
1325 if (eventsOutData
!= nullptr)
1327 delete[] eventsOutData
;
1328 eventsOutData
= nullptr;
1331 if (audioCVIns
!= nullptr)
1333 delete[] audioCVIns
;
1334 audioCVIns
= nullptr;
1337 if (audioCVOuts
!= nullptr)
1339 delete[] audioCVOuts
;
1340 audioCVOuts
= nullptr;
1343 if (paramsLast
!= nullptr)
1345 delete[] paramsLast
;
1346 paramsLast
= nullptr;
1349 if (paramsPtr
!= nullptr)
1352 paramsPtr
= nullptr;
1355 if (paramsOut
!= nullptr)
1358 paramsOut
= nullptr;
1362 // NOTE: assumes num* has been filled by parent class
1367 eventsIn
= new const LV2_Atom_Sequence
*[numMidiIns
];
1369 for (uint32_t i
=0; i
< numMidiIns
; ++i
)
1370 eventsIn
[i
] = nullptr;
1372 else if (usesTime
|| hasUI
)
1374 eventsIn
= new const LV2_Atom_Sequence
*[1];
1375 eventsIn
[0] = nullptr;
1378 if (numMidiOuts
> 0)
1380 eventsOut
= new LV2_Atom_Sequence
*[numMidiOuts
];
1381 eventsOutData
= new EventsOutData
[numMidiOuts
];
1383 for (uint32_t i
=0; i
< numMidiOuts
; ++i
)
1384 eventsOut
[i
] = nullptr;
1388 eventsOut
= new LV2_Atom_Sequence
*[1];
1389 eventsOut
[0] = nullptr;
1390 eventsOutData
= new EventsOutData
[1];
1393 if (const uint32_t numAudioCVIns
= numAudioIns
+numCVIns
)
1395 audioCVIns
= new float*[numAudioCVIns
];
1396 carla_zeroPointers(audioCVIns
, numAudioCVIns
);
1399 if (const uint32_t numAudioCVOuts
= numAudioOuts
+numCVOuts
)
1401 audioCVOuts
= new float*[numAudioCVOuts
];
1402 carla_zeroPointers(audioCVOuts
, numAudioCVOuts
);
1407 paramsLast
= new float[numParams
];
1408 paramsPtr
= new float*[numParams
];
1409 paramsOut
= new bool[numParams
];
1411 carla_zeroFloats(paramsLast
, numParams
);
1412 carla_zeroPointers(paramsPtr
, numParams
);
1413 carla_zeroStructs(paramsOut
, numParams
);
1415 // NOTE: need to be filled in by the parent class
1418 indexOffset
= numAudioIns
+ numAudioOuts
+ numCVIns
+ numCVOuts
;
1419 // 1 event port for time or ui if no midi input is used
1420 indexOffset
+= numMidiIns
> 0 ? numMidiIns
: ((usesTime
|| hasUI
) ? 1 : 0);
1421 // 1 event port for ui if no midi output is used
1422 indexOffset
+= numMidiOuts
> 0 ? numMidiOuts
: (hasUI
? 1 : 0);
1423 // 1 extra for freewheel port
1427 void connectPort(const uint32_t port
, void* const dataLocation
)
1431 if (numMidiIns
> 0 || usesTime
|| hasUI
)
1433 if (port
== index
++)
1435 eventsIn
[0] = (LV2_Atom_Sequence
*)dataLocation
;
1440 for (uint32_t i
=1; i
< numMidiIns
; ++i
)
1442 if (port
== index
++)
1444 eventsIn
[i
] = (LV2_Atom_Sequence
*)dataLocation
;
1449 if (numMidiOuts
> 0 || hasUI
)
1451 if (port
== index
++)
1453 eventsOut
[0] = (LV2_Atom_Sequence
*)dataLocation
;
1458 for (uint32_t i
=1; i
< numMidiOuts
; ++i
)
1460 if (port
== index
++)
1462 eventsOut
[i
] = (LV2_Atom_Sequence
*)dataLocation
;
1467 if (port
== index
++)
1469 freewheel
= (float*)dataLocation
;
1473 for (uint32_t i
=0; i
< numAudioIns
; ++i
)
1475 if (port
== index
++)
1477 audioCVIns
[i
] = (float*)dataLocation
;
1482 for (uint32_t i
=0; i
< numAudioOuts
; ++i
)
1484 if (port
== index
++)
1486 audioCVOuts
[i
] = (float*)dataLocation
;
1491 for (uint32_t i
=0; i
< numCVIns
; ++i
)
1493 if (port
== index
++)
1495 audioCVIns
[numAudioIns
+i
] = (float*)dataLocation
;
1500 for (uint32_t i
=0; i
< numCVOuts
; ++i
)
1502 if (port
== index
++)
1504 audioCVOuts
[numAudioOuts
+i
] = (float*)dataLocation
;
1509 for (uint32_t i
=0; i
< numParams
; ++i
)
1511 if (port
== index
++)
1513 paramsPtr
[i
] = (float*)dataLocation
;
1519 CARLA_DECLARE_NON_COPYABLE(Ports
);
1522 // Rest of host<->plugin support
1526 LV2_URID atomObject
;
1527 LV2_URID atomDouble
;
1532 LV2_URID atomSequence
;
1533 LV2_URID atomString
;
1536 LV2_URID carlaFileAudio
;
1537 LV2_URID carlaFileMIDI
;
1538 LV2_URID carlaPreview
;
1540 LV2_URID patchProperty
;
1543 LV2_URID patchValue
;
1546 LV2_URID timeBarBeat
;
1547 LV2_URID timeBeatsPerBar
;
1548 LV2_URID timeBeatsPerMinute
;
1549 LV2_URID timeBeatUnit
;
1552 LV2_URID timeTicksPerBeat
;
1553 LV2_URID carlaRequestIdle
;
1554 LV2_URID carlaUiEvents
;
1581 timeBeatsPerMinute(0),
1585 timeTicksPerBeat(0),
1586 carlaRequestIdle(0),
1589 void map(const LV2_URID_Map
* const uridMap
)
1591 atomBlank
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Blank
);
1592 atomBool
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Bool
);
1593 atomObject
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Object
);
1594 atomDouble
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Double
);
1595 atomFloat
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Float
);
1596 atomInt
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Int
);
1597 atomLong
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Long
);
1598 atomPath
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Path
);
1599 atomSequence
= uridMap
->map(uridMap
->handle
, LV2_ATOM__Sequence
);
1600 atomString
= uridMap
->map(uridMap
->handle
, LV2_ATOM__String
);
1601 atomURID
= uridMap
->map(uridMap
->handle
, LV2_ATOM__URID
);
1602 carlaFile
= uridMap
->map(uridMap
->handle
, "http://kxstudio.sf.net/carla/file");
1603 carlaFileAudio
= uridMap
->map(uridMap
->handle
, "http://kxstudio.sf.net/carla/file/audio");
1604 carlaFileMIDI
= uridMap
->map(uridMap
->handle
, "http://kxstudio.sf.net/carla/file/midi");
1605 carlaPreview
= uridMap
->map(uridMap
->handle
, "http://kxstudio.sf.net/carla/preview");
1606 midiEvent
= uridMap
->map(uridMap
->handle
, LV2_MIDI__MidiEvent
);
1607 patchProperty
= uridMap
->map(uridMap
->handle
, LV2_PATCH__property
);
1608 patchGet
= uridMap
->map(uridMap
->handle
, LV2_PATCH__Get
);
1609 patchSet
= uridMap
->map(uridMap
->handle
, LV2_PATCH__Set
);
1610 patchValue
= uridMap
->map(uridMap
->handle
, LV2_PATCH__value
);
1611 timePos
= uridMap
->map(uridMap
->handle
, LV2_TIME__Position
);
1612 timeBar
= uridMap
->map(uridMap
->handle
, LV2_TIME__bar
);
1613 timeBarBeat
= uridMap
->map(uridMap
->handle
, LV2_TIME__barBeat
);
1614 timeBeatUnit
= uridMap
->map(uridMap
->handle
, LV2_TIME__beatUnit
);
1615 timeFrame
= uridMap
->map(uridMap
->handle
, LV2_TIME__frame
);
1616 timeSpeed
= uridMap
->map(uridMap
->handle
, LV2_TIME__speed
);
1617 timeBeatsPerBar
= uridMap
->map(uridMap
->handle
, LV2_TIME__beatsPerBar
);
1618 timeBeatsPerMinute
= uridMap
->map(uridMap
->handle
, LV2_TIME__beatsPerMinute
);
1619 timeTicksPerBeat
= uridMap
->map(uridMap
->handle
, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat
);
1620 carlaRequestIdle
= uridMap
->map(uridMap
->handle
, "urn:carla:idle");
1621 carlaUiEvents
= uridMap
->map(uridMap
->handle
, "urn:carla:uiEvents");
1626 const LV2_External_UI_Host
* host
;
1627 const LV2UI_Touch
* touch
;
1628 LV2UI_Write_Function writeFunction
;
1629 LV2UI_Controller controller
;
1635 writeFunction(nullptr),
1636 controller(nullptr),
1641 // ----------------------------------------------------------------------------------------------------------------
1643 #define handlePtr ((Lv2PluginBaseClass*)handle)
1645 static void extui_run(LV2_External_UI_Widget_Compat
* handle
)
1647 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr,);
1649 handlePtr
->handleUiRun();
1652 static void extui_show(LV2_External_UI_Widget_Compat
* handle
)
1654 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr,);
1655 carla_debug("extui_show(%p)", handle
);
1657 handlePtr
->handleUiShow();
1660 static void extui_hide(LV2_External_UI_Widget_Compat
* handle
)
1662 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr,);
1663 carla_debug("extui_hide(%p)", handle
);
1665 handlePtr
->handleUiHide();
1670 // ----------------------------------------------------------------------------------------------------------------
1672 void clearTimeData() noexcept
;
1674 // ----------------------------------------------------------------------------------------------------------------
1676 CARLA_DECLARE_NON_COPYABLE(Lv2PluginBaseClass
)
1679 // --------------------------------------------------------------------------------------------------------------------
1680 // Create new RDF object (using lilv)
1683 const LV2_RDF_Descriptor
* lv2_rdf_new(const LV2_URI uri
, const bool loadPresets
)
1685 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', nullptr);
1687 Lv2WorldClass
& lv2World(Lv2WorldClass::getInstance());
1689 const LilvPlugin
* const cPlugin(lv2World
.getPluginFromURI(uri
));
1690 CARLA_SAFE_ASSERT_RETURN(cPlugin
!= nullptr, nullptr);
1692 Lilv::Plugin
lilvPlugin(cPlugin
);
1693 LV2_RDF_Descriptor
* const rdfDescriptor(new LV2_RDF_Descriptor());
1695 CarlaStringList
portGroupURIs(false); // does not allocate own elements
1696 LinkedList
<LilvNode
*> portGroupNodes
;
1698 // ----------------------------------------------------------------------------------------------------------------
1701 Lilv::Nodes
typeNodes(lilvPlugin
.get_value(lv2World
.rdf_type
));
1703 if (typeNodes
.size() > 0)
1705 if (typeNodes
.contains(lv2World
.class_allpass
))
1706 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_ALLPASS
;
1707 if (typeNodes
.contains(lv2World
.class_amplifier
))
1708 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_AMPLIFIER
;
1709 if (typeNodes
.contains(lv2World
.class_analyzer
))
1710 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_ANALYSER
;
1711 if (typeNodes
.contains(lv2World
.class_bandpass
))
1712 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_BANDPASS
;
1713 if (typeNodes
.contains(lv2World
.class_chorus
))
1714 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_CHORUS
;
1715 if (typeNodes
.contains(lv2World
.class_comb
))
1716 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_COMB
;
1717 if (typeNodes
.contains(lv2World
.class_compressor
))
1718 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_COMPRESSOR
;
1719 if (typeNodes
.contains(lv2World
.class_constant
))
1720 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_CONSTANT
;
1721 if (typeNodes
.contains(lv2World
.class_converter
))
1722 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_CONVERTER
;
1723 if (typeNodes
.contains(lv2World
.class_delay
))
1724 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_DELAY
;
1725 if (typeNodes
.contains(lv2World
.class_distortion
))
1726 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_DISTORTION
;
1727 if (typeNodes
.contains(lv2World
.class_dynamics
))
1728 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_DYNAMICS
;
1729 if (typeNodes
.contains(lv2World
.class_eq
))
1730 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_EQ
;
1731 if (typeNodes
.contains(lv2World
.class_envelope
))
1732 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_ENVELOPE
;
1733 if (typeNodes
.contains(lv2World
.class_expander
))
1734 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_EXPANDER
;
1735 if (typeNodes
.contains(lv2World
.class_filter
))
1736 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_FILTER
;
1737 if (typeNodes
.contains(lv2World
.class_flanger
))
1738 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_FLANGER
;
1739 if (typeNodes
.contains(lv2World
.class_function
))
1740 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_FUNCTION
;
1741 if (typeNodes
.contains(lv2World
.class_gate
))
1742 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_GATE
;
1743 if (typeNodes
.contains(lv2World
.class_generator
))
1744 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_GENERATOR
;
1745 if (typeNodes
.contains(lv2World
.class_highpass
))
1746 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_HIGHPASS
;
1747 if (typeNodes
.contains(lv2World
.class_instrument
))
1748 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_INSTRUMENT
;
1749 if (typeNodes
.contains(lv2World
.class_limiter
))
1750 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_LIMITER
;
1751 if (typeNodes
.contains(lv2World
.class_lowpass
))
1752 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_LOWPASS
;
1753 if (typeNodes
.contains(lv2World
.class_mixer
))
1754 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_MIXER
;
1755 if (typeNodes
.contains(lv2World
.class_modulator
))
1756 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_MODULATOR
;
1757 if (typeNodes
.contains(lv2World
.class_multiEQ
))
1758 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_MULTI_EQ
;
1759 if (typeNodes
.contains(lv2World
.class_oscillator
))
1760 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_OSCILLATOR
;
1761 if (typeNodes
.contains(lv2World
.class_paraEQ
))
1762 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_PARA_EQ
;
1763 if (typeNodes
.contains(lv2World
.class_phaser
))
1764 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_PHASER
;
1765 if (typeNodes
.contains(lv2World
.class_pitch
))
1766 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_PITCH
;
1767 if (typeNodes
.contains(lv2World
.class_reverb
))
1768 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_REVERB
;
1769 if (typeNodes
.contains(lv2World
.class_simulator
))
1770 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_SIMULATOR
;
1771 if (typeNodes
.contains(lv2World
.class_spatial
))
1772 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_SPATIAL
;
1773 if (typeNodes
.contains(lv2World
.class_spectral
))
1774 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_SPECTRAL
;
1775 if (typeNodes
.contains(lv2World
.class_utility
))
1776 rdfDescriptor
->Type
[1] |= LV2_PLUGIN_UTILITY
;
1777 if (typeNodes
.contains(lv2World
.class_waveshaper
))
1778 rdfDescriptor
->Type
[0] |= LV2_PLUGIN_WAVESHAPER
;
1781 lilv_nodes_free(const_cast<LilvNodes
*>(typeNodes
.me
));
1784 // ----------------------------------------------------------------------------------------------------------------
1785 // Set Plugin Information
1787 rdfDescriptor
->URI
= carla_strdup(uri
);
1789 if (LilvNode
* const nameNode
= lilv_plugin_get_name(lilvPlugin
.me
))
1791 if (const char* const name
= lilv_node_as_string(nameNode
))
1792 rdfDescriptor
->Name
= carla_strdup(name
);
1793 lilv_node_free(nameNode
);
1796 if (const char* const author
= lilvPlugin
.get_author_name().as_string())
1797 rdfDescriptor
->Author
= carla_strdup(author
);
1799 if (const char* const binary
= lilvPlugin
.get_library_uri().as_string())
1800 rdfDescriptor
->Binary
= carla_strdup_free(lilv_file_uri_parse(binary
, nullptr));
1802 if (const char* const bundle
= lilvPlugin
.get_bundle_uri().as_string())
1803 rdfDescriptor
->Bundle
= carla_strdup_free(lilv_file_uri_parse(bundle
, nullptr));
1805 Lilv::Nodes
licenseNodes(lilvPlugin
.get_value(lv2World
.doap_license
));
1807 if (licenseNodes
.size() > 0)
1809 if (const char* const license
= licenseNodes
.get_first().as_string())
1810 rdfDescriptor
->License
= carla_strdup(license
);
1813 lilv_nodes_free(const_cast<LilvNodes
*>(licenseNodes
.me
));
1816 // ----------------------------------------------------------------------------------------------------------------
1817 // Set Plugin UniqueID
1819 Lilv::Nodes
replaceNodes(lilvPlugin
.get_value(lv2World
.dct_replaces
));
1821 if (replaceNodes
.size() > 0)
1823 Lilv::Node
replaceNode(replaceNodes
.get_first());
1825 if (replaceNode
.is_uri())
1827 #if defined(CARLA_UTILS_USE_QT)
1828 const QString
replaceURI(replaceNode
.as_uri());
1830 if (replaceURI
.startsWith("urn:"))
1832 const QString
replaceId(replaceURI
.split(":").last());
1835 const ulong
uniqueId(replaceId
.toULong(&ok
));
1837 if (ok
&& uniqueId
!= 0)
1838 rdfDescriptor
->UniqueID
= uniqueId
;
1841 const water::String
replaceURI(replaceNode
.as_uri());
1843 if (replaceURI
.startsWith("urn:"))
1845 const int uniqueId(replaceURI
.getTrailingIntValue());
1848 rdfDescriptor
->UniqueID
= static_cast<ulong
>(uniqueId
);
1854 lilv_nodes_free(const_cast<LilvNodes
*>(replaceNodes
.me
));
1857 // ----------------------------------------------------------------------------------------------------------------
1860 if (const uint numPorts
= lilvPlugin
.get_num_ports())
1862 rdfDescriptor
->PortCount
= numPorts
;
1863 rdfDescriptor
->Ports
= new LV2_RDF_Port
[numPorts
];
1865 for (uint i
= 0; i
< numPorts
; ++i
)
1867 Lilv::Port
lilvPort(lilvPlugin
.get_port_by_index(i
));
1868 CARLA_SAFE_ASSERT_CONTINUE(lilvPort
.me
!= nullptr);
1870 LV2_RDF_Port
* const rdfPort(&rdfDescriptor
->Ports
[i
]);
1872 // --------------------------------------------------------------------------------------------------------
1873 // Set Port Information
1875 if (LilvNode
* const nameNode
= lilv_port_get_name(lilvPlugin
.me
, lilvPort
.me
))
1877 if (const char* const name
= lilv_node_as_string(nameNode
))
1878 rdfPort
->Name
= carla_strdup(name
);
1879 lilv_node_free(nameNode
);
1882 if (const char* const symbol
= lilv_node_as_string(lilvPort
.get_symbol()))
1883 rdfPort
->Symbol
= carla_strdup(symbol
);
1885 if (LilvNode
* const commentNode
= lilvPort
.get(lv2World
.rdfs_comment
.me
))
1887 rdfPort
->Comment
= carla_strdup(lilv_node_as_string(commentNode
));
1888 lilv_node_free(commentNode
);
1891 if (LilvNode
* const groupNode
= lilvPort
.get(lv2World
.pg_group
.me
))
1893 rdfPort
->GroupURI
= carla_strdup(lilv_node_as_uri(groupNode
));
1895 if (portGroupURIs
.appendUnique(rdfPort
->GroupURI
))
1896 portGroupNodes
.append(groupNode
);
1898 lilv_node_free(groupNode
);
1902 // --------------------------------------------------------------------------------------------------------
1903 // Set Port Mode and Type
1906 /**/ if (lilvPort
.is_a(lv2World
.port_input
))
1907 rdfPort
->Types
|= LV2_PORT_INPUT
;
1908 else if (lilvPort
.is_a(lv2World
.port_output
))
1909 rdfPort
->Types
|= LV2_PORT_OUTPUT
;
1911 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is not input or output", uri
, rdfPort
->Name
);
1914 /**/ if (lilvPort
.is_a(lv2World
.port_control
))
1916 rdfPort
->Types
|= LV2_PORT_CONTROL
;
1918 else if (lilvPort
.is_a(lv2World
.port_audio
))
1920 rdfPort
->Types
|= LV2_PORT_AUDIO
;
1922 else if (lilvPort
.is_a(lv2World
.port_cv
))
1924 rdfPort
->Types
|= LV2_PORT_CV
;
1926 else if (lilvPort
.is_a(lv2World
.port_atom
))
1928 rdfPort
->Types
|= LV2_PORT_ATOM
;
1930 Lilv::Nodes
bufferTypeNodes(lilvPort
.get_value(lv2World
.atom_bufferType
));
1932 for (LilvIter
* it
= lilv_nodes_begin(bufferTypeNodes
.me
); ! lilv_nodes_is_end(bufferTypeNodes
.me
, it
); it
= lilv_nodes_next(bufferTypeNodes
.me
, it
))
1934 const Lilv::Node
node(lilv_nodes_get(bufferTypeNodes
.me
, it
));
1935 CARLA_SAFE_ASSERT_CONTINUE(node
.is_uri());
1937 if (node
.equals(lv2World
.atom_sequence
))
1938 rdfPort
->Types
|= LV2_PORT_ATOM_SEQUENCE
;
1940 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses an unknown atom buffer type '%s'", uri
, rdfPort
->Name
, node
.as_uri());
1943 Lilv::Nodes
supportNodes(lilvPort
.get_value(lv2World
.atom_supports
));
1945 for (LilvIter
* it
= lilv_nodes_begin(supportNodes
.me
); ! lilv_nodes_is_end(supportNodes
.me
, it
); it
= lilv_nodes_next(supportNodes
.me
, it
))
1947 const Lilv::Node
node(lilv_nodes_get(supportNodes
.me
, it
));
1948 CARLA_SAFE_ASSERT_CONTINUE(node
.is_uri());
1950 /**/ if (node
.equals(lv2World
.midi_event
))
1951 rdfPort
->Types
|= LV2_PORT_DATA_MIDI_EVENT
;
1953 else if (node
.equals(lv2World
.patch_message
))
1954 rdfPort
->Types
|= LV2_PORT_DATA_PATCH_MESSAGE
;
1956 else if (node
.equals(lv2World
.time_position
))
1957 rdfPort
->Types
|= LV2_PORT_DATA_TIME_POSITION
;
1960 // something new we don't support yet?
1961 else if (std::strstr(node
.as_uri(), "lv2plug.in/") != nullptr)
1962 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of atom type but has unsupported data '%s'", uri
, rdfPort
->Name
, node
.as_uri());
1966 lilv_nodes_free(const_cast<LilvNodes
*>(bufferTypeNodes
.me
));
1967 lilv_nodes_free(const_cast<LilvNodes
*>(supportNodes
.me
));
1969 else if (lilvPort
.is_a(lv2World
.port_event
))
1971 rdfPort
->Types
|= LV2_PORT_EVENT
;
1972 bool supported
= false;
1974 if (lilvPort
.supports_event(lv2World
.midi_event
))
1976 rdfPort
->Types
|= LV2_PORT_DATA_MIDI_EVENT
;
1979 if (lilvPort
.supports_event(lv2World
.patch_message
))
1981 rdfPort
->Types
|= LV2_PORT_DATA_PATCH_MESSAGE
;
1984 if (lilvPort
.supports_event(lv2World
.time_position
))
1986 rdfPort
->Types
|= LV2_PORT_DATA_TIME_POSITION
;
1991 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of event type but has unsupported data", uri
, rdfPort
->Name
);
1993 else if (lilvPort
.is_a(lv2World
.port_midi
))
1995 rdfPort
->Types
|= LV2_PORT_MIDI_LL
;
1996 rdfPort
->Types
|= LV2_PORT_DATA_MIDI_EVENT
;
1999 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of unknown data type", uri
, rdfPort
->Name
);
2002 // --------------------------------------------------------------------------------------------------------
2003 // Set Port Properties
2005 if (lilvPort
.has_property(lv2World
.pprop_optional
))
2006 rdfPort
->Properties
|= LV2_PORT_OPTIONAL
;
2007 if (lilvPort
.has_property(lv2World
.pprop_enumeration
))
2008 rdfPort
->Properties
|= LV2_PORT_ENUMERATION
;
2009 if (lilvPort
.has_property(lv2World
.pprop_integer
))
2010 rdfPort
->Properties
|= LV2_PORT_INTEGER
;
2011 if (lilvPort
.has_property(lv2World
.pprop_isSideChain
))
2012 rdfPort
->Properties
|= LV2_PORT_SIDECHAIN
;
2013 if (lilvPort
.has_property(lv2World
.pprop_sampleRate
))
2014 rdfPort
->Properties
|= LV2_PORT_SAMPLE_RATE
;
2015 if (lilvPort
.has_property(lv2World
.pprop_toggled
))
2016 rdfPort
->Properties
|= LV2_PORT_TOGGLED
;
2018 if (lilvPort
.has_property(lv2World
.pprop_artifacts
))
2019 rdfPort
->Properties
|= LV2_PORT_CAUSES_ARTIFACTS
;
2020 if (lilvPort
.has_property(lv2World
.pprop_continuousCV
))
2021 rdfPort
->Properties
|= LV2_PORT_CONTINUOUS_CV
;
2022 if (lilvPort
.has_property(lv2World
.pprop_discreteCV
))
2023 rdfPort
->Properties
|= LV2_PORT_DISCRETE_CV
;
2024 if (lilvPort
.has_property(lv2World
.pprop_expensive
))
2025 rdfPort
->Properties
|= LV2_PORT_EXPENSIVE
;
2026 if (lilvPort
.has_property(lv2World
.pprop_strictBounds
))
2027 rdfPort
->Properties
|= LV2_PORT_STRICT_BOUNDS
;
2028 if (lilvPort
.has_property(lv2World
.pprop_logarithmic
))
2029 rdfPort
->Properties
|= LV2_PORT_LOGARITHMIC
;
2030 if (lilvPort
.has_property(lv2World
.pprop_notAutomatic
))
2031 rdfPort
->Properties
|= LV2_PORT_NOT_AUTOMATIC
;
2032 if (lilvPort
.has_property(lv2World
.pprop_notOnGUI
))
2033 rdfPort
->Properties
|= LV2_PORT_NOT_ON_GUI
;
2034 if (lilvPort
.has_property(lv2World
.pprop_trigger
))
2035 rdfPort
->Properties
|= LV2_PORT_TRIGGER
;
2036 if (lilvPort
.has_property(lv2World
.pprop_nonAutomatable
))
2037 rdfPort
->Properties
|= LV2_PORT_NON_AUTOMATABLE
;
2039 if (lilvPort
.has_property(lv2World
.reportsLatency
))
2040 rdfPort
->Designation
= LV2_PORT_DESIGNATION_LATENCY
;
2042 // check if sidechain (some plugins use sidechain groups instead of isSidechain)
2043 if (LilvNode
* const portGroupNode
= lilvPort
.get(lv2World
.pg_group
.me
))
2045 if (LilvNode
* const portSideChainOfNode
= lilv_world_get(lv2World
.me
, portGroupNode
,
2046 lv2World
.pg_sideChainOf
.me
, nullptr))
2048 rdfPort
->Properties
|= LV2_PORT_SIDECHAIN
;
2049 lilv_node_free(portSideChainOfNode
);
2051 lilv_node_free(portGroupNode
);
2054 // no port properties set, check if using old/invalid ones
2055 if (rdfPort
->Properties
== 0x0)
2057 const Lilv::Node
oldPropArtifacts(lv2World
.new_uri(NS_devp
"causesArtifacts"));
2058 const Lilv::Node
oldPropContinuousCV(lv2World
.new_uri(NS_devp
"continuousCV"));
2059 const Lilv::Node
oldPropDiscreteCV(lv2World
.new_uri(NS_devp
"discreteCV"));
2060 const Lilv::Node
oldPropExpensive(lv2World
.new_uri(NS_devp
"expensive"));
2061 const Lilv::Node
oldPropStrictBounds(lv2World
.new_uri(NS_devp
"hasStrictBounds"));
2062 const Lilv::Node
oldPropLogarithmic(lv2World
.new_uri(NS_devp
"logarithmic"));
2063 const Lilv::Node
oldPropNotAutomatic(lv2World
.new_uri(NS_devp
"notAutomatic"));
2064 const Lilv::Node
oldPropNotOnGUI(lv2World
.new_uri(NS_devp
"notOnGUI"));
2065 const Lilv::Node
oldPropTrigger(lv2World
.new_uri(NS_devp
"trigger"));
2067 if (lilvPort
.has_property(oldPropArtifacts
))
2069 rdfPort
->Properties
|= LV2_PORT_CAUSES_ARTIFACTS
;
2070 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'causesArtifacts'", uri
, rdfPort
->Name
);
2072 if (lilvPort
.has_property(oldPropContinuousCV
))
2074 rdfPort
->Properties
|= LV2_PORT_CONTINUOUS_CV
;
2075 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'continuousCV'", uri
, rdfPort
->Name
);
2077 if (lilvPort
.has_property(oldPropDiscreteCV
))
2079 rdfPort
->Properties
|= LV2_PORT_DISCRETE_CV
;
2080 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'discreteCV'", uri
, rdfPort
->Name
);
2082 if (lilvPort
.has_property(oldPropExpensive
))
2084 rdfPort
->Properties
|= LV2_PORT_EXPENSIVE
;
2085 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'expensive'", uri
, rdfPort
->Name
);
2087 if (lilvPort
.has_property(oldPropStrictBounds
))
2089 rdfPort
->Properties
|= LV2_PORT_STRICT_BOUNDS
;
2090 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'hasStrictBounds'", uri
, rdfPort
->Name
);
2092 if (lilvPort
.has_property(oldPropLogarithmic
))
2094 rdfPort
->Properties
|= LV2_PORT_LOGARITHMIC
;
2095 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'logarithmic'", uri
, rdfPort
->Name
);
2097 if (lilvPort
.has_property(oldPropNotAutomatic
))
2099 rdfPort
->Properties
|= LV2_PORT_NOT_AUTOMATIC
;
2100 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notAutomatic'", uri
, rdfPort
->Name
);
2102 if (lilvPort
.has_property(oldPropNotOnGUI
))
2104 rdfPort
->Properties
|= LV2_PORT_NOT_ON_GUI
;
2105 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notOnGUI'", uri
, rdfPort
->Name
);
2107 if (lilvPort
.has_property(oldPropTrigger
))
2109 rdfPort
->Properties
|= LV2_PORT_TRIGGER
;
2110 carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'trigger'", uri
, rdfPort
->Name
);
2115 // --------------------------------------------------------------------------------------------------------
2116 // Set Port Designation
2118 if (LilvNode
* const designationNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.designation
.me
))
2120 if (const char* const designation
= lilv_node_as_string(designationNode
))
2122 /**/ if (std::strcmp(designation
, LV2_CORE__control
) == 0)
2123 rdfPort
->Designation
= LV2_PORT_DESIGNATION_CONTROL
;
2124 else if (std::strcmp(designation
, LV2_CORE__enabled
) == 0)
2125 rdfPort
->Designation
= LV2_PORT_DESIGNATION_ENABLED
;
2126 else if (std::strcmp(designation
, LV2_CORE__freeWheeling
) == 0)
2127 rdfPort
->Designation
= LV2_PORT_DESIGNATION_FREEWHEELING
;
2128 else if (std::strcmp(designation
, LV2_CORE__latency
) == 0)
2129 rdfPort
->Designation
= LV2_PORT_DESIGNATION_LATENCY
;
2130 else if (std::strcmp(designation
, LV2_PARAMETERS__sampleRate
) == 0)
2131 rdfPort
->Designation
= LV2_PORT_DESIGNATION_SAMPLE_RATE
;
2132 else if (std::strcmp(designation
, LV2_TIME__bar
) == 0)
2133 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BAR
;
2134 else if (std::strcmp(designation
, LV2_TIME__barBeat
) == 0)
2135 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BAR_BEAT
;
2136 else if (std::strcmp(designation
, LV2_TIME__beat
) == 0)
2137 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BEAT
;
2138 else if (std::strcmp(designation
, LV2_TIME__beatUnit
) == 0)
2139 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BEAT_UNIT
;
2140 else if (std::strcmp(designation
, LV2_TIME__beatsPerBar
) == 0)
2141 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR
;
2142 else if (std::strcmp(designation
, LV2_TIME__beatsPerMinute
) == 0)
2143 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE
;
2144 else if (std::strcmp(designation
, LV2_TIME__frame
) == 0)
2145 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_FRAME
;
2146 else if (std::strcmp(designation
, LV2_TIME__framesPerSecond
) == 0)
2147 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND
;
2148 else if (std::strcmp(designation
, LV2_TIME__speed
) == 0)
2149 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_SPEED
;
2150 else if (std::strcmp(designation
, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat
) == 0)
2151 rdfPort
->Designation
= LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT
;
2152 else if (std::strncmp(designation
, LV2_PARAMETERS_PREFIX
, std::strlen(LV2_PARAMETERS_PREFIX
)) == 0)
2154 else if (std::strncmp(designation
, LV2_PORT_GROUPS_PREFIX
, std::strlen(LV2_PORT_GROUPS_PREFIX
)) == 0)
2157 carla_stderr("lv2_rdf_new(\"%s\") - got unknown port designation '%s'", uri
, designation
);
2159 lilv_node_free(designationNode
);
2163 // --------------------------------------------------------------------------------------------------------
2164 // Set Port MIDI Map
2166 if (LilvNode
* const bindingNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.midi_binding
.me
))
2168 if (lilv_node_is_string(bindingNode
))
2170 if (const char* const bindingAsString
= lilv_node_as_string(bindingNode
))
2172 if (std::strncmp(bindingAsString
, "B0", 2) == 0 && std::strlen(bindingAsString
) == 6)
2174 const char binding
[3] = { bindingAsString
[2], bindingAsString
[3], '\0' };
2175 const long number
= std::strtol(binding
, nullptr, 16);
2177 if (number
>= 0 && number
<= 0xff)
2179 rdfPort
->MidiMap
.Type
= LV2_PORT_MIDI_MAP_CC
;
2180 rdfPort
->MidiMap
.Number
= static_cast<uint32_t>(number
);
2187 if (lilv_node_is_blank(bindingNode
))
2189 Lilv::Nodes
ctrlNumNodes(lv2World
.find_nodes(bindingNode
, lv2World
.midi_ctlrNumber
, nullptr));
2191 if (ctrlNumNodes
.size() == 1)
2193 const int midiCC
= ctrlNumNodes
.get_first().as_int();
2195 if (midiCC
>= 0 && midiCC
<= 0xff)
2197 rdfPort
->MidiMap
.Type
= LV2_PORT_MIDI_MAP_CC
;
2198 rdfPort
->MidiMap
.Number
= static_cast<uint32_t>(midiCC
);
2202 lilv_nodes_free(const_cast<LilvNodes
*>(ctrlNumNodes
.me
));
2206 lilv_node_free(bindingNode
);
2208 else if (LilvNode
* const midiMapNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.mm_defaultControl
.me
))
2210 if (lilv_node_is_blank(midiMapNode
))
2212 Lilv::Nodes
midiMapTypeNodes(lv2World
.find_nodes(midiMapNode
, lv2World
.mm_controlType
, nullptr));
2213 Lilv::Nodes
midiMapNumberNodes(lv2World
.find_nodes(midiMapNode
, lv2World
.mm_controlNumber
, nullptr));
2215 if (midiMapTypeNodes
.size() == 1 && midiMapNumberNodes
.size() == 1)
2217 if (const char* const midiMapType
= midiMapTypeNodes
.get_first().as_string())
2219 /**/ if (std::strcmp(midiMapType
, LV2_MIDI_Map__CC
) == 0)
2220 rdfPort
->MidiMap
.Type
= LV2_PORT_MIDI_MAP_CC
;
2221 else if (std::strcmp(midiMapType
, LV2_MIDI_Map__NRPN
) == 0)
2222 rdfPort
->MidiMap
.Type
= LV2_PORT_MIDI_MAP_NRPN
;
2224 carla_stderr("lv2_rdf_new(\"%s\") - got unknown port Midi-Map type '%s'", uri
, midiMapType
);
2226 rdfPort
->MidiMap
.Number
= static_cast<uint32_t>(midiMapNumberNodes
.get_first().as_int());
2230 lilv_nodes_free(const_cast<LilvNodes
*>(midiMapTypeNodes
.me
));
2231 lilv_nodes_free(const_cast<LilvNodes
*>(midiMapNumberNodes
.me
));
2234 lilv_node_free(midiMapNode
);
2237 // --------------------------------------------------------------------------------------------------------
2240 if (LilvNode
* const defNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.value_default
.me
))
2242 rdfPort
->Points
.Hints
|= LV2_PORT_POINT_DEFAULT
;
2243 rdfPort
->Points
.Default
= lilv_node_as_float(defNode
);
2244 lilv_node_free(defNode
);
2247 if (LilvNode
* const minNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.value_minimum
.me
))
2249 rdfPort
->Points
.Hints
|= LV2_PORT_POINT_MINIMUM
;
2250 rdfPort
->Points
.Minimum
= lilv_node_as_float(minNode
);
2251 lilv_node_free(minNode
);
2254 if (LilvNode
* const maxNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.value_maximum
.me
))
2256 rdfPort
->Points
.Hints
|= LV2_PORT_POINT_MAXIMUM
;
2257 rdfPort
->Points
.Maximum
= lilv_node_as_float(maxNode
);
2258 lilv_node_free(maxNode
);
2262 // --------------------------------------------------------------------------------------------------------
2265 if (LilvNode
* const unitUnitNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.unit_unit
.me
))
2267 if (lilv_node_is_uri(unitUnitNode
))
2269 if (const char* const unitUnit
= lilv_node_as_uri(unitUnitNode
))
2271 rdfPort
->Unit
.Hints
|= LV2_PORT_UNIT_UNIT
;
2273 /**/ if (std::strcmp(unitUnit
, LV2_UNITS__bar
) == 0)
2274 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_BAR
;
2275 else if (std::strcmp(unitUnit
, LV2_UNITS__beat
) == 0)
2276 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_BEAT
;
2277 else if (std::strcmp(unitUnit
, LV2_UNITS__bpm
) == 0)
2278 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_BPM
;
2279 else if (std::strcmp(unitUnit
, LV2_UNITS__cent
) == 0)
2280 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_CENT
;
2281 else if (std::strcmp(unitUnit
, LV2_UNITS__cm
) == 0)
2282 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_CM
;
2283 else if (std::strcmp(unitUnit
, LV2_UNITS__coef
) == 0)
2284 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_COEF
;
2285 else if (std::strcmp(unitUnit
, LV2_UNITS__db
) == 0)
2286 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_DB
;
2287 else if (std::strcmp(unitUnit
, LV2_UNITS__degree
) == 0)
2288 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_DEGREE
;
2289 else if (std::strcmp(unitUnit
, LV2_UNITS__frame
) == 0)
2290 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_FRAME
;
2291 else if (std::strcmp(unitUnit
, LV2_UNITS__hz
) == 0)
2292 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_HZ
;
2293 else if (std::strcmp(unitUnit
, LV2_UNITS__inch
) == 0)
2294 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_INCH
;
2295 else if (std::strcmp(unitUnit
, LV2_UNITS__khz
) == 0)
2296 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_KHZ
;
2297 else if (std::strcmp(unitUnit
, LV2_UNITS__km
) == 0)
2298 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_KM
;
2299 else if (std::strcmp(unitUnit
, LV2_UNITS__m
) == 0)
2300 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_M
;
2301 else if (std::strcmp(unitUnit
, LV2_UNITS__mhz
) == 0)
2302 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MHZ
;
2303 else if (std::strcmp(unitUnit
, LV2_UNITS__midiNote
) == 0)
2304 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MIDINOTE
;
2305 else if (std::strcmp(unitUnit
, LV2_UNITS__mile
) == 0)
2306 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MILE
;
2307 else if (std::strcmp(unitUnit
, LV2_UNITS__min
) == 0)
2308 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MIN
;
2309 else if (std::strcmp(unitUnit
, LV2_UNITS__mm
) == 0)
2310 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MM
;
2311 else if (std::strcmp(unitUnit
, LV2_UNITS__ms
) == 0)
2312 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_MS
;
2313 else if (std::strcmp(unitUnit
, LV2_UNITS__oct
) == 0)
2314 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_OCT
;
2315 else if (std::strcmp(unitUnit
, LV2_UNITS__pc
) == 0)
2316 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_PC
;
2317 else if (std::strcmp(unitUnit
, LV2_UNITS__s
) == 0)
2318 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_S
;
2319 else if (std::strcmp(unitUnit
, LV2_UNITS__semitone12TET
) == 0)
2320 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_SEMITONE
;
2321 else if (std::strcmp(unitUnit
, "http://moddevices.com/ns/mod#volts") == 0)
2322 rdfPort
->Unit
.Unit
= LV2_PORT_UNIT_VOLTS
;
2324 carla_stderr("lv2_rdf_new(\"%s\") - got unknown unit '%s'", uri
, unitUnit
);
2328 if (LilvNode
* const unitNameNode
= lilv_world_get(lv2World
.me
, unitUnitNode
, lv2World
.unit_name
.me
, nullptr))
2330 if (const char* const unitName
= lilv_node_as_string(unitNameNode
))
2332 rdfPort
->Unit
.Hints
|= LV2_PORT_UNIT_NAME
;
2333 rdfPort
->Unit
.Name
= carla_strdup(unitName
);
2335 lilv_node_free(unitNameNode
);
2338 if (LilvNode
* const unitRenderNode
= lilv_world_get(lv2World
.me
, unitUnitNode
, lv2World
.unit_render
.me
, nullptr))
2340 if (const char* const unitRender
= lilv_node_as_string(unitRenderNode
))
2342 rdfPort
->Unit
.Hints
|= LV2_PORT_UNIT_RENDER
;
2343 rdfPort
->Unit
.Render
= carla_strdup(unitRender
);
2345 lilv_node_free(unitRenderNode
);
2348 if (LilvNode
* const unitSymbolNode
= lilv_world_get(lv2World
.me
, unitUnitNode
, lv2World
.unit_symbol
.me
, nullptr))
2350 if (const char* const unitSymbol
= lilv_node_as_string(unitSymbolNode
))
2352 rdfPort
->Unit
.Hints
|= LV2_PORT_UNIT_SYMBOL
;
2353 rdfPort
->Unit
.Symbol
= carla_strdup(unitSymbol
);
2355 lilv_node_free(unitSymbolNode
);
2358 lilv_node_free(unitUnitNode
);
2362 // --------------------------------------------------------------------------------------------------------
2363 // Set Port Minimum Size
2365 if (LilvNode
* const minimumSizeNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.rz_minSize
.me
))
2367 const int minimumSize(lilv_node_as_int(minimumSizeNode
));
2369 if (minimumSize
> 0)
2370 rdfPort
->MinimumSize
= static_cast<uint32_t>(minimumSize
);
2372 carla_safe_assert_int("minimumSize > 0", __FILE__
, __LINE__
, minimumSize
);
2374 lilv_node_free(minimumSizeNode
);
2378 // --------------------------------------------------------------------------------------------------------
2379 // Set Port Scale Points
2381 Lilv::ScalePoints
lilvScalePoints(lilvPort
.get_scale_points());
2383 if (const uint numScalePoints
= lilvScalePoints
.size())
2385 rdfPort
->ScalePoints
= new LV2_RDF_PortScalePoint
[numScalePoints
];
2387 // get all scalepoints and sort them by value
2388 LilvScalePointMap sortedpoints
;
2390 LILV_FOREACH(scale_points
, it
, lilvScalePoints
)
2392 Lilv::ScalePoint
lilvScalePoint(lilvScalePoints
.get(it
));
2394 CARLA_SAFE_ASSERT_CONTINUE(lilvScalePoint
.get_label() != nullptr);
2396 if (const LilvNode
* const valuenode
= lilvScalePoint
.get_value())
2398 const double valueid
= lilv_node_as_float(valuenode
);
2399 sortedpoints
[valueid
] = lilvScalePoint
.me
;
2403 // now safe to store, sorted by using std::map
2405 for (LilvScalePointMap::iterator it
=sortedpoints
.begin(), end
=sortedpoints
.end(); it
!= end
; ++it
)
2407 CARLA_SAFE_ASSERT_BREAK(numUsed
< numScalePoints
);
2408 LV2_RDF_PortScalePoint
* const rdfScalePoint(&rdfPort
->ScalePoints
[numUsed
++]);
2410 const LilvScalePoint
* const scalepoint
= it
->second
;
2412 const LilvNode
* const xlabel
= lilv_scale_point_get_label(scalepoint
);
2413 const LilvNode
* const xvalue
= lilv_scale_point_get_value(scalepoint
);
2415 rdfScalePoint
->Label
= carla_strdup(lilv_node_as_string(xlabel
));
2416 rdfScalePoint
->Value
= lilv_node_as_float(xvalue
);
2419 rdfPort
->ScalePointCount
= numUsed
;
2422 lilv_nodes_free(const_cast<LilvNodes
*>(lilvScalePoints
.me
));
2427 // ----------------------------------------------------------------------------------------------------------------
2428 // Set Plugin Parameters
2430 std::map
<std::string
, LV2_RDF_Parameter
> parameters
;
2431 Lilv::Nodes
patchReadableNodes(lilvPlugin
.get_value(lv2World
.patch_readable
));
2432 Lilv::Nodes
patchWritableNodes(lilvPlugin
.get_value(lv2World
.patch_writable
));
2434 if (const uint numParameters
= patchWritableNodes
.size())
2437 LILV_FOREACH(nodes
, it
, patchWritableNodes
)
2439 CARLA_SAFE_ASSERT_BREAK(numUsed
< numParameters
);
2441 Lilv::Node
patchWritableNode(patchWritableNodes
.get(it
));
2443 if (LilvNode
* const typeNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2444 lv2World
.rdf_type
.me
, nullptr))
2446 const char* const type
= lilv_node_as_uri(typeNode
);
2448 if (std::strcmp(type
, LV2_CORE__Parameter
) != 0)
2450 lilv_node_free(typeNode
);
2454 lilv_node_free(typeNode
);
2461 CARLA_SAFE_ASSERT_CONTINUE(patchWritableNode
.is_uri());
2464 LV2_RDF_Parameter rdfParam
;
2465 rdfParam
.URI
= carla_strdup(patchWritableNode
.as_uri());
2466 rdfParam
.Flags
= LV2_PARAMETER_FLAG_INPUT
;
2468 if (patchReadableNodes
.contains(patchWritableNode
))
2469 rdfParam
.Flags
|= LV2_PARAMETER_FLAG_OUTPUT
;
2471 // ----------------------------------------------------------------------------------------------------
2474 if (LilvNode
* const rangeNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2475 lv2World
.rdfs_range
.me
, nullptr))
2477 const char* const rangeURI
= lilv_node_as_string(rangeNode
);
2479 /**/ if (std::strcmp(rangeURI
, LV2_ATOM__Bool
) == 0)
2480 rdfParam
.Type
= LV2_PARAMETER_TYPE_BOOL
;
2481 else if (std::strcmp(rangeURI
, LV2_ATOM__Int
) == 0)
2482 rdfParam
.Type
= LV2_PARAMETER_TYPE_INT
;
2483 else if (std::strcmp(rangeURI
, LV2_ATOM__Long
) == 0)
2484 rdfParam
.Type
= LV2_PARAMETER_TYPE_LONG
;
2485 else if (std::strcmp(rangeURI
, LV2_ATOM__Float
) == 0)
2486 rdfParam
.Type
= LV2_PARAMETER_TYPE_FLOAT
;
2487 else if (std::strcmp(rangeURI
, LV2_ATOM__Double
) == 0)
2488 rdfParam
.Type
= LV2_PARAMETER_TYPE_DOUBLE
;
2489 else if (std::strcmp(rangeURI
, LV2_ATOM__Path
) == 0)
2490 rdfParam
.Type
= LV2_PARAMETER_TYPE_PATH
;
2491 else if (std::strcmp(rangeURI
, LV2_ATOM__String
) == 0)
2492 rdfParam
.Type
= LV2_PARAMETER_TYPE_STRING
;
2494 carla_stderr("lv2_rdf_new(\"%s\") - got unknown parameter type '%s'", uri
, rangeURI
);
2496 lilv_node_free(rangeNode
);
2499 if (LilvNode
* const labelNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2500 lv2World
.rdfs_label
.me
, nullptr))
2502 rdfParam
.Label
= carla_strdup(lilv_node_as_string(labelNode
));
2503 lilv_node_free(labelNode
);
2506 if (LilvNode
* const commentNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2507 lv2World
.rdfs_comment
.me
, nullptr))
2509 rdfParam
.Comment
= carla_strdup_safe(lilv_node_as_string(commentNode
));
2510 lilv_node_free(commentNode
);
2513 if (LilvNode
* const groupNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2514 lv2World
.pg_group
.me
, nullptr))
2516 rdfParam
.GroupURI
= carla_strdup_safe(lilv_node_as_uri(groupNode
));
2518 if (portGroupURIs
.appendUnique(rdfParam
.GroupURI
))
2519 portGroupNodes
.append(groupNode
);
2521 lilv_node_free(groupNode
);
2524 // ----------------------------------------------------------------------------------------------------
2525 // Set Port MIDI Map
2527 if (LilvNode
* const bindingNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2528 lv2World
.midi_binding
.me
, nullptr))
2530 if (const char* const bindingAsString
= lilv_node_as_string(bindingNode
))
2532 if (std::strncmp(bindingAsString
, "B0", 2) == 0 && std::strlen(bindingAsString
) == 6)
2534 const char binding
[3] = { bindingAsString
[2], bindingAsString
[3], '\0' };
2535 const long number
= std::strtol(binding
, nullptr, 16);
2537 if (number
>= 0 && number
<= 0xff)
2539 rdfParam
.MidiMap
.Type
= LV2_PORT_MIDI_MAP_CC
;
2540 rdfParam
.MidiMap
.Number
= static_cast<uint32_t>(number
);
2545 lilv_node_free(bindingNode
);
2548 // ----------------------------------------------------------------------------------------------------
2551 if (LilvNode
* const defNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2552 lv2World
.value_default
.me
, nullptr))
2554 rdfParam
.Points
.Hints
|= LV2_PORT_POINT_DEFAULT
;
2555 rdfParam
.Points
.Default
= lilv_node_as_float(defNode
);
2556 lilv_node_free(defNode
);
2559 if (LilvNode
* const minNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2560 lv2World
.value_minimum
.me
, nullptr))
2562 rdfParam
.Points
.Hints
|= LV2_PORT_POINT_MINIMUM
;
2563 rdfParam
.Points
.Minimum
= lilv_node_as_float(minNode
);
2564 lilv_node_free(minNode
);
2567 if (LilvNode
* const maxNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2568 lv2World
.value_maximum
.me
, nullptr))
2570 rdfParam
.Points
.Hints
|= LV2_PORT_POINT_MAXIMUM
;
2571 rdfParam
.Points
.Maximum
= lilv_node_as_float(maxNode
);
2572 lilv_node_free(maxNode
);
2575 // ----------------------------------------------------------------------------------------------------
2578 if (LilvNode
* const unitUnitNode
= lilv_world_get(lv2World
.me
, patchWritableNode
,
2579 lv2World
.unit_unit
.me
, nullptr))
2581 if (lilv_node_is_uri(unitUnitNode
))
2583 if (const char* const unitUnit
= lilv_node_as_uri(unitUnitNode
))
2585 rdfParam
.Unit
.Hints
|= LV2_PORT_UNIT_UNIT
;
2587 /**/ if (std::strcmp(unitUnit
, LV2_UNITS__bar
) == 0)
2588 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_BAR
;
2589 else if (std::strcmp(unitUnit
, LV2_UNITS__beat
) == 0)
2590 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_BEAT
;
2591 else if (std::strcmp(unitUnit
, LV2_UNITS__bpm
) == 0)
2592 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_BPM
;
2593 else if (std::strcmp(unitUnit
, LV2_UNITS__cent
) == 0)
2594 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_CENT
;
2595 else if (std::strcmp(unitUnit
, LV2_UNITS__cm
) == 0)
2596 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_CM
;
2597 else if (std::strcmp(unitUnit
, LV2_UNITS__coef
) == 0)
2598 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_COEF
;
2599 else if (std::strcmp(unitUnit
, LV2_UNITS__db
) == 0)
2600 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_DB
;
2601 else if (std::strcmp(unitUnit
, LV2_UNITS__degree
) == 0)
2602 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_DEGREE
;
2603 else if (std::strcmp(unitUnit
, LV2_UNITS__frame
) == 0)
2604 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_FRAME
;
2605 else if (std::strcmp(unitUnit
, LV2_UNITS__hz
) == 0)
2606 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_HZ
;
2607 else if (std::strcmp(unitUnit
, LV2_UNITS__inch
) == 0)
2608 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_INCH
;
2609 else if (std::strcmp(unitUnit
, LV2_UNITS__khz
) == 0)
2610 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_KHZ
;
2611 else if (std::strcmp(unitUnit
, LV2_UNITS__km
) == 0)
2612 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_KM
;
2613 else if (std::strcmp(unitUnit
, LV2_UNITS__m
) == 0)
2614 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_M
;
2615 else if (std::strcmp(unitUnit
, LV2_UNITS__mhz
) == 0)
2616 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MHZ
;
2617 else if (std::strcmp(unitUnit
, LV2_UNITS__midiNote
) == 0)
2618 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MIDINOTE
;
2619 else if (std::strcmp(unitUnit
, LV2_UNITS__mile
) == 0)
2620 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MILE
;
2621 else if (std::strcmp(unitUnit
, LV2_UNITS__min
) == 0)
2622 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MIN
;
2623 else if (std::strcmp(unitUnit
, LV2_UNITS__mm
) == 0)
2624 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MM
;
2625 else if (std::strcmp(unitUnit
, LV2_UNITS__ms
) == 0)
2626 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_MS
;
2627 else if (std::strcmp(unitUnit
, LV2_UNITS__oct
) == 0)
2628 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_OCT
;
2629 else if (std::strcmp(unitUnit
, LV2_UNITS__pc
) == 0)
2630 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_PC
;
2631 else if (std::strcmp(unitUnit
, LV2_UNITS__s
) == 0)
2632 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_S
;
2633 else if (std::strcmp(unitUnit
, LV2_UNITS__semitone12TET
) == 0)
2634 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_SEMITONE
;
2635 else if (std::strcmp(unitUnit
, "http://moddevices.com/ns/mod#volts") == 0)
2636 rdfParam
.Unit
.Unit
= LV2_PORT_UNIT_VOLTS
;
2638 carla_stderr("lv2_rdf_new(\"%s\") - got unknown unit '%s'", uri
, unitUnit
);
2642 if (LilvNode
* const unitNameNode
= lilv_world_get(lv2World
.me
, unitUnitNode
,
2643 lv2World
.unit_name
.me
, nullptr))
2645 if (const char* const unitName
= lilv_node_as_string(unitNameNode
))
2647 rdfParam
.Unit
.Hints
|= LV2_PORT_UNIT_NAME
;
2648 rdfParam
.Unit
.Name
= carla_strdup(unitName
);
2650 lilv_node_free(unitNameNode
);
2653 if (LilvNode
* const unitRenderNode
= lilv_world_get(lv2World
.me
, unitUnitNode
,
2654 lv2World
.unit_render
.me
, nullptr))
2656 if (const char* const unitRender
= lilv_node_as_string(unitRenderNode
))
2658 rdfParam
.Unit
.Hints
|= LV2_PORT_UNIT_RENDER
;
2659 rdfParam
.Unit
.Render
= carla_strdup(unitRender
);
2661 lilv_node_free(unitRenderNode
);
2664 if (LilvNode
* const unitSymbolNode
= lilv_world_get(lv2World
.me
, unitUnitNode
,
2665 lv2World
.unit_symbol
.me
, nullptr))
2667 if (const char* const unitSymbol
= lilv_node_as_string(unitSymbolNode
))
2669 rdfParam
.Unit
.Hints
|= LV2_PORT_UNIT_SYMBOL
;
2670 rdfParam
.Unit
.Symbol
= carla_strdup(unitSymbol
);
2672 lilv_node_free(unitSymbolNode
);
2675 lilv_node_free(unitUnitNode
);
2678 parameters
[rdfParam
.URI
].copyAndReplace(rdfParam
);
2681 CARLA_SAFE_ASSERT_UINT2(parameters
.size() == numUsed
, parameters
.size(), numUsed
);
2682 rdfDescriptor
->Parameters
= new LV2_RDF_Parameter
[numUsed
];
2683 rdfDescriptor
->ParameterCount
= numUsed
;
2686 for (std::map
<std::string
, LV2_RDF_Parameter
>::iterator it
= parameters
.begin(), end
= parameters
.end();
2689 rdfDescriptor
->Parameters
[numUsed
++].copyAndReplace(it
->second
);
2693 lilv_nodes_free(const_cast<LilvNodes
*>(patchReadableNodes
.me
));
2694 lilv_nodes_free(const_cast<LilvNodes
*>(patchWritableNodes
.me
));
2697 // ----------------------------------------------------------------------------------------------------------------
2698 // Set Plugin Port Groups
2700 if (const size_t portGroupCount
= portGroupURIs
.count())
2702 rdfDescriptor
->PortGroups
= new LV2_RDF_PortGroup
[portGroupCount
];
2705 CarlaStringList::Itenerator itu
= portGroupURIs
.begin2();
2706 LinkedList
<LilvNode
*>::Itenerator itn
= portGroupNodes
.begin2();
2707 for (; itu
.valid() && itn
.valid(); itu
.next(), itn
.next())
2709 const char* const portGroupURI
= itu
.getValue(nullptr);
2710 CARLA_SAFE_ASSERT_CONTINUE(portGroupURI
!= nullptr);
2712 LilvNode
* const portGroupNode
= itn
.getValue(nullptr);
2713 CARLA_SAFE_ASSERT_CONTINUE(portGroupNode
!= nullptr);
2715 LV2_RDF_PortGroup
& portGroup(rdfDescriptor
->PortGroups
[count
]);
2716 portGroup
.URI
= portGroupURI
;
2718 if (LilvNode
* const portGroupNameNode
= lilv_world_get(lv2World
.me
, portGroupNode
,
2719 lv2World
.lv2_name
.me
, nullptr))
2721 portGroup
.Name
= carla_strdup_safe(lilv_node_as_string(portGroupNameNode
));
2722 lilv_node_free(portGroupNameNode
);
2724 // some plugins use rdfs:label, spec was not clear which one to use
2725 else if (LilvNode
* const portGroupLabelNode
= lilv_world_get(lv2World
.me
, portGroupNode
,
2726 lv2World
.rdfs_label
.me
, nullptr))
2728 portGroup
.Name
= carla_strdup_safe(lilv_node_as_string(portGroupLabelNode
));
2729 lilv_node_free(portGroupLabelNode
);
2732 if (LilvNode
* const portGroupSymbolNode
= lilv_world_get(lv2World
.me
, portGroupNode
,
2733 lv2World
.lv2_symbol
.me
, nullptr))
2735 portGroup
.Symbol
= carla_strdup_safe(lilv_node_as_string(portGroupSymbolNode
));
2736 lilv_node_free(portGroupSymbolNode
);
2740 lilv_node_free(portGroupNode
);
2743 rdfDescriptor
->PortGroupCount
= count
;
2744 portGroupNodes
.clear();
2747 // ----------------------------------------------------------------------------------------------------------------
2748 // Set Plugin Presets
2752 Lilv::Nodes
presetNodes(lilvPlugin
.get_related(lv2World
.preset_preset
));
2754 if (presetNodes
.size() > 0)
2756 // create a list of preset URIs (for sorting and unique-ness)
2757 #if defined(CARLA_UTILS_USE_QT)
2758 QStringList presetListURIs
;
2760 LILV_FOREACH(nodes
, it
, presetNodes
)
2762 Lilv::Node
presetNode(presetNodes
.get(it
));
2764 QString
presetURI(presetNode
.as_uri());
2766 if (! (presetURI
.trimmed().isEmpty() || presetListURIs
.contains(presetURI
)))
2767 presetListURIs
.append(presetURI
);
2770 presetListURIs
.sort();
2772 rdfDescriptor
->PresetCount
= static_cast<uint32_t>(presetListURIs
.count());
2774 water::StringArray presetListURIs
;
2776 LILV_FOREACH(nodes
, it
, presetNodes
)
2778 Lilv::Node
presetNode(presetNodes
.get(it
));
2780 water::String
presetURI(presetNode
.as_uri());
2782 if (presetURI
.trim().isNotEmpty())
2783 presetListURIs
.addIfNotAlreadyThere(presetURI
);
2786 presetListURIs
.sortNatural();
2788 rdfDescriptor
->PresetCount
= static_cast<uint32_t>(presetListURIs
.size());
2791 // create presets with unique URIs
2792 rdfDescriptor
->Presets
= new LV2_RDF_Preset
[rdfDescriptor
->PresetCount
];
2795 LILV_FOREACH(nodes
, it
, presetNodes
)
2797 Lilv::Node
presetNode(presetNodes
.get(it
));
2799 const char* const presetURI(presetNode
.as_uri());
2800 CARLA_SAFE_ASSERT_CONTINUE(presetURI
!= nullptr && presetURI
[0] != '\0');
2802 // try to find label without loading the preset resource first
2803 Lilv::Nodes
presetLabelNodes(lv2World
.find_nodes(presetNode
, lv2World
.rdfs_label
, nullptr));
2805 // failed, try loading resource
2806 if (presetLabelNodes
.size() == 0)
2808 // if loading resource fails, skip this preset
2809 if (lv2World
.load_resource(presetNode
) == -1)
2812 // ok, let's try again
2813 presetLabelNodes
= lv2World
.find_nodes(presetNode
, lv2World
.rdfs_label
, nullptr);
2816 if (presetLabelNodes
.size() > 0)
2818 #if defined(CARLA_UTILS_USE_QT)
2819 const int index
= presetListURIs
.indexOf(QString(presetURI
));
2821 const int index
= presetListURIs
.indexOf(water::String(presetURI
));
2823 CARLA_SAFE_ASSERT_CONTINUE(index
>= 0 && index
< static_cast<int>(rdfDescriptor
->PresetCount
));
2825 LV2_RDF_Preset
* const rdfPreset(&rdfDescriptor
->Presets
[index
]);
2827 // ---------------------------------------------------
2828 // Set Preset Information
2830 rdfPreset
->URI
= carla_strdup(presetURI
);
2832 if (const char* const label
= presetLabelNodes
.get_first().as_string())
2833 rdfPreset
->Label
= carla_strdup(label
);
2835 lilv_nodes_free(const_cast<LilvNodes
*>(presetLabelNodes
.me
));
2840 lilv_nodes_free(const_cast<LilvNodes
*>(presetNodes
.me
));
2843 // ----------------------------------------------------------------------------------------------------------------
2844 // Set Plugin Features
2846 Lilv::Nodes
lilvFeatureNodes(lilvPlugin
.get_supported_features());
2848 if (const uint numFeatures
= lilvFeatureNodes
.size())
2850 Lilv::Nodes
lilvFeatureNodesR(lilvPlugin
.get_required_features());
2852 rdfDescriptor
->Features
= new LV2_RDF_Feature
[numFeatures
];
2855 LILV_FOREACH(nodes
, it
, lilvFeatureNodes
)
2857 CARLA_SAFE_ASSERT_BREAK(numUsed
< numFeatures
);
2859 Lilv::Node
lilvFeatureNode(lilvFeatureNodes
.get(it
));
2860 LV2_RDF_Feature
* const rdfFeature(&rdfDescriptor
->Features
[numUsed
++]);
2862 rdfFeature
->Required
= lilvFeatureNodesR
.contains(lilvFeatureNode
);
2864 if (const char* const featureURI
= lilvFeatureNode
.as_uri())
2865 rdfFeature
->URI
= carla_strdup(featureURI
);
2867 rdfFeature
->URI
= nullptr;
2870 rdfDescriptor
->FeatureCount
= numUsed
;
2871 lilv_nodes_free(const_cast<LilvNodes
*>(lilvFeatureNodesR
.me
));
2874 lilv_nodes_free(const_cast<LilvNodes
*>(lilvFeatureNodes
.me
));
2877 // ----------------------------------------------------------------------------------------------------------------
2878 // Set Plugin Extensions
2880 Lilv::Nodes
lilvExtensionDataNodes(lilvPlugin
.get_extension_data());
2882 if (const uint numExtensions
= lilvExtensionDataNodes
.size())
2884 rdfDescriptor
->Extensions
= new LV2_URI
[numExtensions
];
2887 LILV_FOREACH(nodes
, it
, lilvExtensionDataNodes
)
2889 CARLA_SAFE_ASSERT_BREAK(numUsed
< numExtensions
);
2891 Lilv::Node
lilvExtensionDataNode(lilvExtensionDataNodes
.get(it
));
2892 LV2_URI
* const rdfExtension(&rdfDescriptor
->Extensions
[numUsed
++]);
2894 if (lilvExtensionDataNode
.is_uri())
2896 if (const char* const extURI
= lilvExtensionDataNode
.as_uri())
2898 *rdfExtension
= carla_strdup(extURI
);
2902 *rdfExtension
= nullptr;
2905 for (uint32_t x
=numUsed
; x
< rdfDescriptor
->ExtensionCount
; ++x
)
2906 rdfDescriptor
->Extensions
[x
] = nullptr;
2908 rdfDescriptor
->ExtensionCount
= numUsed
;
2911 lilv_nodes_free(const_cast<LilvNodes
*>(lilvExtensionDataNodes
.me
));
2914 // ----------------------------------------------------------------------------------------------------------------
2917 #ifdef CARLA_OS_LINUX
2918 const bool hasMODGui
= lilvPlugin
.get_modgui_resources_directory().as_uri() != nullptr;
2920 const bool hasMODGui
= false;
2923 Lilv::UIs
lilvUIs(lilvPlugin
.get_uis());
2925 const uint numUIs
= lilvUIs
.size() + (hasMODGui
? 1 : 0);
2929 rdfDescriptor
->UIs
= new LV2_RDF_UI
[numUIs
];
2932 LILV_FOREACH(uis
, it
, lilvUIs
)
2934 CARLA_SAFE_ASSERT_BREAK(numUsed
< numUIs
);
2936 Lilv::UI
lilvUI(lilvUIs
.get(it
));
2937 LV2_RDF_UI
* const rdfUI(&rdfDescriptor
->UIs
[numUsed
++]);
2939 lv2World
.load_resource(lilvUI
.get_uri());
2941 // ----------------------------------------------------------------------------------------------------
2944 /**/ if (lilvUI
.is_a(lv2World
.ui_gtk2
))
2945 rdfUI
->Type
= LV2_UI_GTK2
;
2946 else if (lilvUI
.is_a(lv2World
.ui_gtk3
))
2947 rdfUI
->Type
= LV2_UI_GTK3
;
2948 else if (lilvUI
.is_a(lv2World
.ui_qt4
))
2949 rdfUI
->Type
= LV2_UI_QT4
;
2950 else if (lilvUI
.is_a(lv2World
.ui_qt5
))
2951 rdfUI
->Type
= LV2_UI_QT5
;
2952 else if (lilvUI
.is_a(lv2World
.ui_cocoa
))
2953 rdfUI
->Type
= LV2_UI_COCOA
;
2954 else if (lilvUI
.is_a(lv2World
.ui_windows
))
2955 rdfUI
->Type
= LV2_UI_WINDOWS
;
2956 else if (lilvUI
.is_a(lv2World
.ui_x11
))
2957 rdfUI
->Type
= LV2_UI_X11
;
2958 else if (lilvUI
.is_a(lv2World
.ui_external
))
2959 rdfUI
->Type
= LV2_UI_EXTERNAL
;
2960 else if (lilvUI
.is_a(lv2World
.ui_externalOld
))
2961 rdfUI
->Type
= LV2_UI_OLD_EXTERNAL
;
2962 else if (lilvUI
.is_a(lv2World
.ui
))
2963 rdfUI
->Type
= LV2_UI_NONE
;
2965 carla_stderr("lv2_rdf_new(\"%s\") - UI '%s' is of unknown type", uri
, lilvUI
.get_uri().as_uri());
2967 // ----------------------------------------------------------------------------------------------------
2968 // Set UI Information
2970 if (const char* const uiURI
= lilvUI
.get_uri().as_uri())
2971 rdfUI
->URI
= carla_strdup(uiURI
);
2973 if (const char* const uiBinary
= lilvUI
.get_binary_uri().as_string())
2974 rdfUI
->Binary
= carla_strdup_free(lilv_file_uri_parse(uiBinary
, nullptr));
2976 if (const char* const uiBundle
= lilvUI
.get_bundle_uri().as_string())
2977 rdfUI
->Bundle
= carla_strdup_free(lilv_file_uri_parse(uiBundle
, nullptr));
2980 // ----------------------------------------------------------------------------------------------------
2983 Lilv::Nodes
lilvFeatureNodes(lilvUI
.get_supported_features());
2985 if (const uint numFeatures
= lilvFeatureNodes
.size())
2987 Lilv::Nodes
lilvFeatureNodesR(lilvUI
.get_required_features());
2989 rdfUI
->Features
= new LV2_RDF_Feature
[numFeatures
];
2992 LILV_FOREACH(nodes
, it2
, lilvFeatureNodes
)
2994 CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2
< numFeatures
, numUsed2
, numFeatures
);
2996 Lilv::Node
lilvFeatureNode(lilvFeatureNodes
.get(it2
));
2997 LV2_RDF_Feature
* const rdfFeature(&rdfUI
->Features
[numUsed2
++]);
2999 rdfFeature
->Required
= lilvFeatureNodesR
.contains(lilvFeatureNode
);
3001 if (const char* const featureURI
= lilvFeatureNode
.as_uri())
3002 rdfFeature
->URI
= carla_strdup(featureURI
);
3004 rdfFeature
->URI
= nullptr;
3007 rdfUI
->FeatureCount
= numUsed2
;
3008 lilv_nodes_free(const_cast<LilvNodes
*>(lilvFeatureNodesR
.me
));
3011 lilv_nodes_free(const_cast<LilvNodes
*>(lilvFeatureNodes
.me
));
3014 // ----------------------------------------------------------------------------------------------------
3015 // Set UI Extensions
3017 Lilv::Nodes
lilvExtensionDataNodes(lilvUI
.get_extension_data());
3019 if (const uint numExtensions
= lilvExtensionDataNodes
.size())
3021 rdfUI
->Extensions
= new LV2_URI
[numExtensions
];
3024 LILV_FOREACH(nodes
, it2
, lilvExtensionDataNodes
)
3026 CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2
< numExtensions
, numUsed2
, numExtensions
);
3028 Lilv::Node
lilvExtensionDataNode(lilvExtensionDataNodes
.get(it2
));
3029 LV2_URI
* const rdfExtension(&rdfUI
->Extensions
[numUsed2
++]);
3031 if (lilvExtensionDataNode
.is_uri())
3033 if (const char* const extURI
= lilvExtensionDataNode
.as_uri())
3035 *rdfExtension
= carla_strdup(extURI
);
3039 *rdfExtension
= nullptr;
3042 for (uint x2
=numUsed2
; x2
< rdfUI
->ExtensionCount
; ++x2
)
3043 rdfUI
->Extensions
[x2
] = nullptr;
3045 rdfUI
->ExtensionCount
= numUsed2
;
3048 lilv_nodes_free(const_cast<LilvNodes
*>(lilvExtensionDataNodes
.me
));
3051 // ----------------------------------------------------------------------------------------------------
3052 // Set UI Port Notifications
3054 Lilv::Nodes
portNotifNodes(lv2World
.find_nodes(lilvUI
.get_uri(), lv2World
.ui_portNotif
.me
, nullptr));
3056 if (const uint portNotifCount
= portNotifNodes
.size())
3058 rdfUI
->PortNotificationCount
= portNotifCount
;
3059 rdfUI
->PortNotifications
= new LV2_RDF_UI_PortNotification
[portNotifCount
];
3062 LILV_FOREACH(nodes
, it2
, portNotifNodes
)
3064 CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2
< portNotifCount
, numUsed2
, portNotifCount
);
3066 Lilv::Node
portNotifNode(portNotifNodes
.get(it2
));
3067 LV2_RDF_UI_PortNotification
* const rdfPortNotif(&rdfUI
->PortNotifications
[numUsed2
++]);
3069 LilvNode
* const protocolNode
= lilv_world_get(lv2World
.me
, portNotifNode
,
3070 lv2World
.ui_protocol
.me
, nullptr);
3072 if (protocolNode
!= nullptr)
3074 CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_uri(protocolNode
));
3076 const char* const protocol
= lilv_node_as_uri(protocolNode
);
3077 CARLA_SAFE_ASSERT_CONTINUE(protocol
!= nullptr && protocol
[0] != '\0');
3079 /**/ if (std::strcmp(protocol
, LV2_UI__floatProtocol
) == 0)
3080 rdfPortNotif
->Protocol
= LV2_UI_PORT_PROTOCOL_FLOAT
;
3081 else if (std::strcmp(protocol
, LV2_UI__peakProtocol
) == 0)
3082 rdfPortNotif
->Protocol
= LV2_UI_PORT_PROTOCOL_PEAK
;
3086 rdfPortNotif
->Protocol
= LV2_UI_PORT_PROTOCOL_FLOAT
;
3089 /**/ if (LilvNode
* const symbolNode
= lilv_world_get(lv2World
.me
, portNotifNode
,
3090 lv2World
.symbol
.me
, nullptr))
3092 CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_string(symbolNode
));
3094 const char* const symbol
= lilv_node_as_string(symbolNode
);
3095 CARLA_SAFE_ASSERT_CONTINUE(symbol
!= nullptr && symbol
[0] != '\0');
3097 rdfPortNotif
->Symbol
= carla_strdup(symbol
);
3099 lilv_node_free(symbolNode
);
3101 else if (LilvNode
* const indexNode
= lilv_world_get(lv2World
.me
, portNotifNode
,
3102 lv2World
.ui_portIndex
.me
, nullptr))
3104 CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_int(indexNode
));
3106 const int index
= lilv_node_as_int(indexNode
);
3107 CARLA_SAFE_ASSERT_CONTINUE(index
>= 0);
3109 rdfPortNotif
->Index
= static_cast<uint32_t>(index
);
3111 lilv_node_free(indexNode
);
3114 lilv_node_free(protocolNode
);
3118 lilv_nodes_free(const_cast<LilvNodes
*>(portNotifNodes
.me
));
3124 CARLA_SAFE_ASSERT_BREAK(numUsed
== numUIs
-1);
3126 LV2_RDF_UI
* const rdfUI(&rdfDescriptor
->UIs
[numUsed
++]);
3128 // -------------------------------------------------------
3131 rdfUI
->Type
= LV2_UI_MOD
;
3133 // -------------------------------------------------------
3134 // Set UI Information
3136 if (const char* const resDir
= lilvPlugin
.get_modgui_resources_directory().as_uri())
3137 rdfUI
->URI
= carla_strdup_free(lilv_file_uri_parse(resDir
, nullptr));
3139 if (rdfDescriptor
->Bundle
!= nullptr)
3140 rdfUI
->Bundle
= carla_strdup(rdfDescriptor
->Bundle
);
3145 rdfDescriptor
->UICount
= numUsed
;
3148 lilv_nodes_free(const_cast<LilvNodes
*>(lilvUIs
.me
));
3151 return rdfDescriptor
;
3154 // --------------------------------------------------------------------------------------------------------------------
3155 // Check if we support a plugin port
3158 bool is_lv2_port_supported(const LV2_Property types
) noexcept
3160 if (LV2_IS_PORT_CONTROL(types
))
3162 if (LV2_IS_PORT_AUDIO(types
))
3164 if (LV2_IS_PORT_CV(types
))
3166 if (LV2_IS_PORT_ATOM_SEQUENCE(types
))
3168 if (LV2_IS_PORT_EVENT(types
))
3170 if (LV2_IS_PORT_MIDI_LL(types
))
3175 // --------------------------------------------------------------------------------------------------------------------
3176 // Check if we support a plugin feature
3179 bool is_lv2_feature_supported(const LV2_URI uri
) noexcept
3181 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', false);
3183 if (std::strcmp(uri
, LV2_BUF_SIZE__boundedBlockLength
) == 0)
3185 if (std::strcmp(uri
, LV2_BUF_SIZE__fixedBlockLength
) == 0)
3187 if (std::strcmp(uri
, LV2_BUF_SIZE__powerOf2BlockLength
) == 0)
3189 if (std::strcmp(uri
, LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI
) == 0)
3191 if (std::strcmp(uri
, LV2_CORE__hardRTCapable
) == 0)
3193 if (std::strcmp(uri
, LV2_CORE__inPlaceBroken
) == 0)
3195 if (std::strcmp(uri
, LV2_CORE__isLive
) == 0)
3197 if (std::strcmp(uri
, LV2_EVENT_URI
) == 0)
3199 if (std::strcmp(uri
, LV2_INLINEDISPLAY__queue_draw
) == 0)
3201 if (std::strcmp(uri
, LV2_LOG__log
) == 0)
3203 if (std::strcmp(uri
, LV2_OPTIONS__options
) == 0)
3205 if (std::strcmp(uri
, LV2_PROGRAMS__Host
) == 0)
3207 if (std::strcmp(uri
, LV2_RESIZE_PORT__resize
) == 0)
3209 if (std::strcmp(uri
, LV2_RTSAFE_MEMORY_POOL__Pool
) == 0)
3211 if (std::strcmp(uri
, LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI
) == 0)
3213 if (std::strcmp(uri
, LV2_STATE__freePath
) == 0)
3215 if (std::strcmp(uri
, LV2_STATE__loadDefaultState
) == 0)
3217 if (std::strcmp(uri
, LV2_STATE__makePath
) == 0)
3219 if (std::strcmp(uri
, LV2_STATE__mapPath
) == 0)
3221 if (std::strcmp(uri
, LV2_STATE__threadSafeRestore
) == 0)
3223 if (std::strcmp(uri
, LV2_PORT_PROPS__supportsStrictBounds
) == 0)
3225 if (std::strcmp(uri
, LV2_URI_MAP_URI
) == 0)
3227 if (std::strcmp(uri
, LV2_URID__map
) == 0)
3229 if (std::strcmp(uri
, LV2_URID__unmap
) == 0)
3231 if (std::strcmp(uri
, LV2_WORKER__schedule
) == 0)
3236 // --------------------------------------------------------------------------------------------------------------------
3237 // Check if we support a plugin or UI feature
3240 bool is_lv2_ui_feature_supported(const LV2_URI uri
) noexcept
3242 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', false);
3244 if (is_lv2_feature_supported(uri
))
3246 #ifndef BUILD_BRIDGE_UI
3247 if (std::strcmp(uri
, LV2_DATA_ACCESS_URI
) == 0)
3249 if (std::strcmp(uri
, LV2_INSTANCE_ACCESS_URI
) == 0)
3252 if (std::strcmp(uri
, LV2_UI__fixedSize
) == 0)
3254 if (std::strcmp(uri
, LV2_UI__idleInterface
) == 0)
3256 if (std::strcmp(uri
, LV2_UI__makeResident
) == 0)
3258 if (std::strcmp(uri
, LV2_UI__makeSONameResident
) == 0)
3260 if (std::strcmp(uri
, LV2_UI__noUserResize
) == 0)
3262 if (std::strcmp(uri
, LV2_UI__parent
) == 0)
3264 if (std::strcmp(uri
, LV2_UI__portMap
) == 0)
3266 if (std::strcmp(uri
, LV2_UI__portSubscribe
) == 0)
3268 if (std::strcmp(uri
, LV2_UI__requestValue
) == 0)
3270 if (std::strcmp(uri
, LV2_UI__resize
) == 0)
3272 if (std::strcmp(uri
, LV2_UI__touch
) == 0)
3274 if (std::strcmp(uri
, LV2_EXTERNAL_UI__Widget
) == 0)
3276 if (std::strcmp(uri
, LV2_EXTERNAL_UI_DEPRECATED_URI
) == 0)
3281 // --------------------------------------------------------------------------------------------------------------------
3283 #endif // CARLA_LV2_UTILS_HPP_INCLUDED