Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CarlaLv2Utils.hpp 68KB

11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
12 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613
  1. /*
  2. * Carla LV2 utils
  3. * Copyright (C) 2011-2016 Filipe Coelho <falktx@falktx.com>
  4. *
  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.
  9. *
  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.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_LV2_UTILS_HPP_INCLUDED
  18. #define CARLA_LV2_UTILS_HPP_INCLUDED
  19. #include "CarlaUtils.hpp"
  20. #ifndef nullptr
  21. # undef NULL
  22. # define NULL nullptr
  23. #endif
  24. // disable -Wdocumentation for LV2 headers
  25. #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
  26. # pragma clang diagnostic push
  27. # pragma clang diagnostic ignored "-Wdocumentation"
  28. #endif
  29. #include "lv2/lv2.h"
  30. #include "lv2/atom.h"
  31. #include "lv2/atom-forge.h"
  32. #include "lv2/atom-helpers.h"
  33. #include "lv2/atom-util.h"
  34. #include "lv2/buf-size.h"
  35. #include "lv2/data-access.h"
  36. // dynmanifest
  37. #include "lv2/event.h"
  38. #include "lv2/event-helpers.h"
  39. #include "lv2/instance-access.h"
  40. #include "lv2/log.h"
  41. // logger
  42. #include "lv2/midi.h"
  43. // morph
  44. #include "lv2/options.h"
  45. #include "lv2/parameters.h"
  46. #include "lv2/patch.h"
  47. #include "lv2/port-groups.h"
  48. #include "lv2/port-props.h"
  49. #include "lv2/presets.h"
  50. #include "lv2/resize-port.h"
  51. #include "lv2/state.h"
  52. #include "lv2/time.h"
  53. #include "lv2/ui.h"
  54. #include "lv2/units.h"
  55. #include "lv2/uri-map.h"
  56. #include "lv2/urid.h"
  57. #include "lv2/worker.h"
  58. #include "lv2/lv2-miditype.h"
  59. #include "lv2/lv2-midifunctions.h"
  60. #include "lv2/lv2_external_ui.h"
  61. #include "lv2/lv2_kxstudio_properties.h"
  62. #include "lv2/lv2_programs.h"
  63. #include "lv2/lv2_rtmempool.h"
  64. #include "lilv/lilvmm.hpp"
  65. #include "sratom/sratom.h"
  66. // enable -Wdocumentation again
  67. #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
  68. # pragma clang diagnostic pop
  69. #endif
  70. #include "lv2_rdf.hpp"
  71. #ifdef USE_QT
  72. # include <QtCore/QStringList>
  73. #else
  74. # include "juce_core/juce_core.h"
  75. #endif
  76. // used for scalepoint sorting
  77. #include <map>
  78. typedef std::map<double,const LilvScalePoint*> LilvScalePointMap;
  79. // -----------------------------------------------------------------------
  80. // Define namespaces and missing prefixes
  81. #define NS_dct "http://purl.org/dc/terms/"
  82. #define NS_doap "http://usefulinc.com/ns/doap#"
  83. #define NS_rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  84. #define NS_rdfs "http://www.w3.org/2000/01/rdf-schema#"
  85. #define NS_llmm "http://ll-plugins.nongnu.org/lv2/ext/midimap#"
  86. #define NS_mod "http://moddevices.com/ns/modgui#"
  87. #define LV2_MIDI_Map__CC "http://ll-plugins.nongnu.org/lv2/namespace#CC"
  88. #define LV2_MIDI_Map__NRPN "http://ll-plugins.nongnu.org/lv2/namespace#NRPN"
  89. #define LV2_MIDI_LL__MidiPort "http://ll-plugins.nongnu.org/lv2/ext/MidiPort"
  90. #define LV2_UI__makeResident LV2_UI_PREFIX "makeResident"
  91. #define LV2_UI__makeSONameResident LV2_UI_PREFIX "makeSONameResident"
  92. // -----------------------------------------------------------------------
  93. // Custom Atom types
  94. struct LV2_Atom_MidiEvent {
  95. LV2_Atom atom; /**< Atom header. */
  96. uint8_t data[4]; /**< MIDI data (body). */
  97. };
  98. static inline
  99. uint32_t lv2_atom_total_size(const LV2_Atom_MidiEvent& midiEv)
  100. {
  101. return static_cast<uint32_t>(sizeof(LV2_Atom)) + midiEv.atom.size;
  102. }
  103. // -----------------------------------------------------------------------
  104. // Our LV2 World class
  105. class Lv2WorldClass : public Lilv::World
  106. {
  107. public:
  108. // Base Types
  109. Lilv::Node port;
  110. Lilv::Node symbol;
  111. Lilv::Node designation;
  112. Lilv::Node freeWheeling;
  113. Lilv::Node reportsLatency;
  114. // Plugin Types
  115. Lilv::Node class_allpass;
  116. Lilv::Node class_amplifier;
  117. Lilv::Node class_analyzer;
  118. Lilv::Node class_bandpass;
  119. Lilv::Node class_chorus;
  120. Lilv::Node class_comb;
  121. Lilv::Node class_compressor;
  122. Lilv::Node class_constant;
  123. Lilv::Node class_converter;
  124. Lilv::Node class_delay;
  125. Lilv::Node class_distortion;
  126. Lilv::Node class_dynamics;
  127. Lilv::Node class_eq;
  128. Lilv::Node class_envelope;
  129. Lilv::Node class_expander;
  130. Lilv::Node class_filter;
  131. Lilv::Node class_flanger;
  132. Lilv::Node class_function;
  133. Lilv::Node class_gate;
  134. Lilv::Node class_generator;
  135. Lilv::Node class_highpass;
  136. Lilv::Node class_instrument;
  137. Lilv::Node class_limiter;
  138. Lilv::Node class_lowpass;
  139. Lilv::Node class_mixer;
  140. Lilv::Node class_modulator;
  141. Lilv::Node class_multiEQ;
  142. Lilv::Node class_oscillator;
  143. Lilv::Node class_paraEQ;
  144. Lilv::Node class_phaser;
  145. Lilv::Node class_pitch;
  146. Lilv::Node class_reverb;
  147. Lilv::Node class_simulator;
  148. Lilv::Node class_spatial;
  149. Lilv::Node class_spectral;
  150. Lilv::Node class_utility;
  151. Lilv::Node class_waveshaper;
  152. // Port Types
  153. Lilv::Node port_input;
  154. Lilv::Node port_output;
  155. Lilv::Node port_control;
  156. Lilv::Node port_audio;
  157. Lilv::Node port_cv;
  158. Lilv::Node port_atom;
  159. Lilv::Node port_event;
  160. Lilv::Node port_midi;
  161. // Port Properties
  162. Lilv::Node pprop_optional;
  163. Lilv::Node pprop_enumeration;
  164. Lilv::Node pprop_integer;
  165. Lilv::Node pprop_sampleRate;
  166. Lilv::Node pprop_toggled;
  167. Lilv::Node pprop_artifacts;
  168. Lilv::Node pprop_continuousCV;
  169. Lilv::Node pprop_discreteCV;
  170. Lilv::Node pprop_expensive;
  171. Lilv::Node pprop_strictBounds;
  172. Lilv::Node pprop_logarithmic;
  173. Lilv::Node pprop_notAutomatic;
  174. Lilv::Node pprop_notOnGUI;
  175. Lilv::Node pprop_trigger;
  176. Lilv::Node pprop_nonAutomable;
  177. // Unit Hints
  178. Lilv::Node unit_name;
  179. Lilv::Node unit_render;
  180. Lilv::Node unit_symbol;
  181. Lilv::Node unit_unit;
  182. // UI Types
  183. Lilv::Node ui_gtk2;
  184. Lilv::Node ui_gtk3;
  185. Lilv::Node ui_qt4;
  186. Lilv::Node ui_qt5;
  187. Lilv::Node ui_cocoa;
  188. Lilv::Node ui_windows;
  189. Lilv::Node ui_x11;
  190. Lilv::Node ui_external;
  191. Lilv::Node ui_externalOld;
  192. Lilv::Node ui_externalOld2;
  193. // Misc
  194. Lilv::Node atom_bufferType;
  195. Lilv::Node atom_sequence;
  196. Lilv::Node atom_supports;
  197. Lilv::Node preset_preset;
  198. Lilv::Node state_state;
  199. Lilv::Node value_default;
  200. Lilv::Node value_minimum;
  201. Lilv::Node value_maximum;
  202. Lilv::Node rz_asLargeAs;
  203. Lilv::Node rz_minSize;
  204. // Port Data Types
  205. Lilv::Node midi_event;
  206. Lilv::Node patch_message;
  207. Lilv::Node time_position;
  208. // MIDI CC
  209. Lilv::Node mm_defaultControl;
  210. Lilv::Node mm_controlType;
  211. Lilv::Node mm_controlNumber;
  212. // Other
  213. Lilv::Node dct_replaces;
  214. Lilv::Node doap_license;
  215. Lilv::Node rdf_type;
  216. Lilv::Node rdfs_label;
  217. bool needsInit;
  218. const LilvPlugins* allPlugins;
  219. const LilvPlugin** cachedPlugins;
  220. uint pluginCount;
  221. // -------------------------------------------------------------------
  222. Lv2WorldClass()
  223. : Lilv::World(),
  224. port (new_uri(LV2_CORE__port)),
  225. symbol (new_uri(LV2_CORE__symbol)),
  226. designation (new_uri(LV2_CORE__designation)),
  227. freeWheeling (new_uri(LV2_CORE__freeWheeling)),
  228. reportsLatency (new_uri(LV2_CORE__reportsLatency)),
  229. class_allpass (new_uri(LV2_CORE__AllpassPlugin)),
  230. class_amplifier (new_uri(LV2_CORE__AmplifierPlugin)),
  231. class_analyzer (new_uri(LV2_CORE__AnalyserPlugin)),
  232. class_bandpass (new_uri(LV2_CORE__BandpassPlugin)),
  233. class_chorus (new_uri(LV2_CORE__ChorusPlugin)),
  234. class_comb (new_uri(LV2_CORE__CombPlugin)),
  235. class_compressor (new_uri(LV2_CORE__CompressorPlugin)),
  236. class_constant (new_uri(LV2_CORE__ConstantPlugin)),
  237. class_converter (new_uri(LV2_CORE__ConverterPlugin)),
  238. class_delay (new_uri(LV2_CORE__DelayPlugin)),
  239. class_distortion (new_uri(LV2_CORE__DistortionPlugin)),
  240. class_dynamics (new_uri(LV2_CORE__DynamicsPlugin)),
  241. class_eq (new_uri(LV2_CORE__EQPlugin)),
  242. class_envelope (new_uri(LV2_CORE__EnvelopePlugin)),
  243. class_expander (new_uri(LV2_CORE__ExpanderPlugin)),
  244. class_filter (new_uri(LV2_CORE__FilterPlugin)),
  245. class_flanger (new_uri(LV2_CORE__FlangerPlugin)),
  246. class_function (new_uri(LV2_CORE__FunctionPlugin)),
  247. class_gate (new_uri(LV2_CORE__GatePlugin)),
  248. class_generator (new_uri(LV2_CORE__GeneratorPlugin)),
  249. class_highpass (new_uri(LV2_CORE__HighpassPlugin)),
  250. class_instrument (new_uri(LV2_CORE__InstrumentPlugin)),
  251. class_limiter (new_uri(LV2_CORE__LimiterPlugin)),
  252. class_lowpass (new_uri(LV2_CORE__LowpassPlugin)),
  253. class_mixer (new_uri(LV2_CORE__MixerPlugin)),
  254. class_modulator (new_uri(LV2_CORE__ModulatorPlugin)),
  255. class_multiEQ (new_uri(LV2_CORE__MultiEQPlugin)),
  256. class_oscillator (new_uri(LV2_CORE__OscillatorPlugin)),
  257. class_paraEQ (new_uri(LV2_CORE__ParaEQPlugin)),
  258. class_phaser (new_uri(LV2_CORE__PhaserPlugin)),
  259. class_pitch (new_uri(LV2_CORE__PitchPlugin)),
  260. class_reverb (new_uri(LV2_CORE__ReverbPlugin)),
  261. class_simulator (new_uri(LV2_CORE__SimulatorPlugin)),
  262. class_spatial (new_uri(LV2_CORE__SpatialPlugin)),
  263. class_spectral (new_uri(LV2_CORE__SpectralPlugin)),
  264. class_utility (new_uri(LV2_CORE__UtilityPlugin)),
  265. class_waveshaper (new_uri(LV2_CORE__WaveshaperPlugin)),
  266. port_input (new_uri(LV2_CORE__InputPort)),
  267. port_output (new_uri(LV2_CORE__OutputPort)),
  268. port_control (new_uri(LV2_CORE__ControlPort)),
  269. port_audio (new_uri(LV2_CORE__AudioPort)),
  270. port_cv (new_uri(LV2_CORE__CVPort)),
  271. port_atom (new_uri(LV2_ATOM__AtomPort)),
  272. port_event (new_uri(LV2_EVENT__EventPort)),
  273. port_midi (new_uri(LV2_MIDI_LL__MidiPort)),
  274. pprop_optional (new_uri(LV2_CORE__connectionOptional)),
  275. pprop_enumeration (new_uri(LV2_CORE__enumeration)),
  276. pprop_integer (new_uri(LV2_CORE__integer)),
  277. pprop_sampleRate (new_uri(LV2_CORE__sampleRate)),
  278. pprop_toggled (new_uri(LV2_CORE__toggled)),
  279. pprop_artifacts (new_uri(LV2_PORT_PROPS__causesArtifacts)),
  280. pprop_continuousCV (new_uri(LV2_PORT_PROPS__continuousCV)),
  281. pprop_discreteCV (new_uri(LV2_PORT_PROPS__discreteCV)),
  282. pprop_expensive (new_uri(LV2_PORT_PROPS__expensive)),
  283. pprop_strictBounds (new_uri(LV2_PORT_PROPS__hasStrictBounds)),
  284. pprop_logarithmic (new_uri(LV2_PORT_PROPS__logarithmic)),
  285. pprop_notAutomatic (new_uri(LV2_PORT_PROPS__notAutomatic)),
  286. pprop_notOnGUI (new_uri(LV2_PORT_PROPS__notOnGUI)),
  287. pprop_trigger (new_uri(LV2_PORT_PROPS__trigger)),
  288. pprop_nonAutomable (new_uri(LV2_KXSTUDIO_PROPERTIES__NonAutomable)),
  289. unit_name (new_uri(LV2_UNITS__name)),
  290. unit_render (new_uri(LV2_UNITS__render)),
  291. unit_symbol (new_uri(LV2_UNITS__symbol)),
  292. unit_unit (new_uri(LV2_UNITS__unit)),
  293. ui_gtk2 (new_uri(LV2_UI__GtkUI)),
  294. ui_gtk3 (new_uri(LV2_UI__Gtk3UI)),
  295. ui_qt4 (new_uri(LV2_UI__Qt4UI)),
  296. ui_qt5 (new_uri(LV2_UI__Qt5UI)),
  297. ui_cocoa (new_uri(LV2_UI__CocoaUI)),
  298. ui_windows (new_uri(LV2_UI__WindowsUI)),
  299. ui_x11 (new_uri(LV2_UI__X11UI)),
  300. ui_external (new_uri(LV2_EXTERNAL_UI__Widget)),
  301. ui_externalOld (new_uri(LV2_EXTERNAL_UI_DEPRECATED_URI)),
  302. ui_externalOld2 (new_uri("http://nedko.arnaudov.name/lv2/external_ui/")),
  303. atom_bufferType (new_uri(LV2_ATOM__bufferType)),
  304. atom_sequence (new_uri(LV2_ATOM__Sequence)),
  305. atom_supports (new_uri(LV2_ATOM__supports)),
  306. preset_preset (new_uri(LV2_PRESETS__Preset)),
  307. state_state (new_uri(LV2_STATE__state)),
  308. value_default (new_uri(LV2_CORE__default)),
  309. value_minimum (new_uri(LV2_CORE__minimum)),
  310. value_maximum (new_uri(LV2_CORE__maximum)),
  311. rz_asLargeAs (new_uri(LV2_RESIZE_PORT__asLargeAs)),
  312. rz_minSize (new_uri(LV2_RESIZE_PORT__minimumSize)),
  313. midi_event (new_uri(LV2_MIDI__MidiEvent)),
  314. patch_message (new_uri(LV2_PATCH__Message)),
  315. time_position (new_uri(LV2_TIME__Position)),
  316. mm_defaultControl (new_uri(NS_llmm "defaultMidiController")),
  317. mm_controlType (new_uri(NS_llmm "controllerType")),
  318. mm_controlNumber (new_uri(NS_llmm "controllerNumber")),
  319. dct_replaces (new_uri(NS_dct "replaces")),
  320. doap_license (new_uri(NS_doap "license")),
  321. rdf_type (new_uri(NS_rdf "type")),
  322. rdfs_label (new_uri(NS_rdfs "label")),
  323. needsInit(true),
  324. allPlugins(nullptr),
  325. cachedPlugins(nullptr),
  326. pluginCount(0) {}
  327. ~Lv2WorldClass() override
  328. {
  329. pluginCount = 0;
  330. allPlugins = nullptr;
  331. if (cachedPlugins != nullptr)
  332. {
  333. delete[] cachedPlugins;
  334. cachedPlugins = nullptr;
  335. }
  336. }
  337. // FIXME - remove this
  338. static Lv2WorldClass& getInstance()
  339. {
  340. static Lv2WorldClass lv2World;
  341. return lv2World;
  342. }
  343. void initIfNeeded(const char* const LV2_PATH)
  344. {
  345. CARLA_SAFE_ASSERT_RETURN(LV2_PATH != nullptr,);
  346. if (! needsInit)
  347. return;
  348. needsInit = false;
  349. Lilv::World::load_all(LV2_PATH);
  350. allPlugins = lilv_world_get_all_plugins(this->me);
  351. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr,);
  352. if ((pluginCount = lilv_plugins_size(allPlugins)))
  353. {
  354. cachedPlugins = new const LilvPlugin*[pluginCount+1];
  355. carla_zeroPointers(cachedPlugins, pluginCount+1);
  356. int i = 0;
  357. for (LilvIter* it = lilv_plugins_begin(allPlugins); ! lilv_plugins_is_end(allPlugins, it); it = lilv_plugins_next(allPlugins, it))
  358. cachedPlugins[i++] = lilv_plugins_get(allPlugins, it);
  359. }
  360. }
  361. void load_bundle(const char* const bundle)
  362. {
  363. CARLA_SAFE_ASSERT_RETURN(bundle != nullptr && bundle[0] != '\0',);
  364. CARLA_SAFE_ASSERT_RETURN(needsInit,);
  365. needsInit = false;
  366. Lilv::World::load_bundle(Lilv::Node(new_uri(bundle)));
  367. allPlugins = lilv_world_get_all_plugins(this->me);
  368. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr,);
  369. if ((pluginCount = lilv_plugins_size(allPlugins)))
  370. {
  371. cachedPlugins = new const LilvPlugin*[pluginCount+1];
  372. carla_zeroPointers(cachedPlugins, pluginCount+1);
  373. int i = 0;
  374. for (LilvIter* it = lilv_plugins_begin(allPlugins); ! lilv_plugins_is_end(allPlugins, it); it = lilv_plugins_next(allPlugins, it))
  375. cachedPlugins[i++] = lilv_plugins_get(allPlugins, it);
  376. }
  377. }
  378. uint getPluginCount() const
  379. {
  380. CARLA_SAFE_ASSERT_RETURN(! needsInit, 0);
  381. return pluginCount;
  382. }
  383. const LilvPlugin* getPluginFromIndex(const uint index) const
  384. {
  385. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  386. CARLA_SAFE_ASSERT_RETURN(cachedPlugins != nullptr, nullptr);
  387. CARLA_SAFE_ASSERT_RETURN(index < pluginCount, nullptr);
  388. return cachedPlugins[index];
  389. }
  390. const LilvPlugin* getPluginFromURI(const LV2_URI uri) const
  391. {
  392. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  393. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  394. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr, nullptr);
  395. LilvNode* const uriNode(lilv_new_uri(this->me, uri));
  396. CARLA_SAFE_ASSERT_RETURN(uriNode != nullptr, nullptr);
  397. const LilvPlugin* const cPlugin(lilv_plugins_get_by_uri(allPlugins, uriNode));
  398. lilv_node_free(uriNode);
  399. return cPlugin;
  400. }
  401. LilvState* getStateFromURI(const LV2_URI uri, const LV2_URID_Map* const uridMap) const
  402. {
  403. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  404. CARLA_SAFE_ASSERT_RETURN(uridMap != nullptr, nullptr);
  405. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  406. LilvNode* const uriNode(lilv_new_uri(this->me, uri));
  407. CARLA_SAFE_ASSERT_RETURN(uriNode != nullptr, nullptr);
  408. CARLA_SAFE_ASSERT(lilv_world_load_resource(this->me, uriNode) >= 0);
  409. LilvState* const cState(lilv_state_new_from_world(this->me, uridMap, uriNode));
  410. lilv_node_free(uriNode);
  411. return cState;
  412. }
  413. CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
  414. CARLA_DECLARE_NON_COPY_STRUCT(Lv2WorldClass)
  415. };
  416. // -----------------------------------------------------------------------
  417. // Create new RDF object (using lilv)
  418. static inline
  419. const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
  420. {
  421. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  422. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  423. const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(uri));
  424. CARLA_SAFE_ASSERT_RETURN(cPlugin != nullptr, nullptr);
  425. Lilv::Plugin lilvPlugin(cPlugin);
  426. LV2_RDF_Descriptor* const rdfDescriptor(new LV2_RDF_Descriptor());
  427. // -------------------------------------------------------------------
  428. // Set Plugin Type
  429. {
  430. Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
  431. if (typeNodes.size() > 0)
  432. {
  433. if (typeNodes.contains(lv2World.class_allpass))
  434. rdfDescriptor->Type[0] |= LV2_PLUGIN_ALLPASS;
  435. if (typeNodes.contains(lv2World.class_amplifier))
  436. rdfDescriptor->Type[0] |= LV2_PLUGIN_AMPLIFIER;
  437. if (typeNodes.contains(lv2World.class_analyzer))
  438. rdfDescriptor->Type[1] |= LV2_PLUGIN_ANALYSER;
  439. if (typeNodes.contains(lv2World.class_bandpass))
  440. rdfDescriptor->Type[0] |= LV2_PLUGIN_BANDPASS;
  441. if (typeNodes.contains(lv2World.class_chorus))
  442. rdfDescriptor->Type[1] |= LV2_PLUGIN_CHORUS;
  443. if (typeNodes.contains(lv2World.class_comb))
  444. rdfDescriptor->Type[1] |= LV2_PLUGIN_COMB;
  445. if (typeNodes.contains(lv2World.class_compressor))
  446. rdfDescriptor->Type[0] |= LV2_PLUGIN_COMPRESSOR;
  447. if (typeNodes.contains(lv2World.class_constant))
  448. rdfDescriptor->Type[1] |= LV2_PLUGIN_CONSTANT;
  449. if (typeNodes.contains(lv2World.class_converter))
  450. rdfDescriptor->Type[1] |= LV2_PLUGIN_CONVERTER;
  451. if (typeNodes.contains(lv2World.class_delay))
  452. rdfDescriptor->Type[0] |= LV2_PLUGIN_DELAY;
  453. if (typeNodes.contains(lv2World.class_distortion))
  454. rdfDescriptor->Type[0] |= LV2_PLUGIN_DISTORTION;
  455. if (typeNodes.contains(lv2World.class_dynamics))
  456. rdfDescriptor->Type[0] |= LV2_PLUGIN_DYNAMICS;
  457. if (typeNodes.contains(lv2World.class_eq))
  458. rdfDescriptor->Type[0] |= LV2_PLUGIN_EQ;
  459. if (typeNodes.contains(lv2World.class_envelope))
  460. rdfDescriptor->Type[0] |= LV2_PLUGIN_ENVELOPE;
  461. if (typeNodes.contains(lv2World.class_expander))
  462. rdfDescriptor->Type[0] |= LV2_PLUGIN_EXPANDER;
  463. if (typeNodes.contains(lv2World.class_filter))
  464. rdfDescriptor->Type[0] |= LV2_PLUGIN_FILTER;
  465. if (typeNodes.contains(lv2World.class_flanger))
  466. rdfDescriptor->Type[1] |= LV2_PLUGIN_FLANGER;
  467. if (typeNodes.contains(lv2World.class_function))
  468. rdfDescriptor->Type[1] |= LV2_PLUGIN_FUNCTION;
  469. if (typeNodes.contains(lv2World.class_gate))
  470. rdfDescriptor->Type[0] |= LV2_PLUGIN_GATE;
  471. if (typeNodes.contains(lv2World.class_generator))
  472. rdfDescriptor->Type[1] |= LV2_PLUGIN_GENERATOR;
  473. if (typeNodes.contains(lv2World.class_highpass))
  474. rdfDescriptor->Type[0] |= LV2_PLUGIN_HIGHPASS;
  475. if (typeNodes.contains(lv2World.class_instrument))
  476. rdfDescriptor->Type[1] |= LV2_PLUGIN_INSTRUMENT;
  477. if (typeNodes.contains(lv2World.class_limiter))
  478. rdfDescriptor->Type[0] |= LV2_PLUGIN_LIMITER;
  479. if (typeNodes.contains(lv2World.class_lowpass))
  480. rdfDescriptor->Type[0] |= LV2_PLUGIN_LOWPASS;
  481. if (typeNodes.contains(lv2World.class_mixer))
  482. rdfDescriptor->Type[1] |= LV2_PLUGIN_MIXER;
  483. if (typeNodes.contains(lv2World.class_modulator))
  484. rdfDescriptor->Type[1] |= LV2_PLUGIN_MODULATOR;
  485. if (typeNodes.contains(lv2World.class_multiEQ))
  486. rdfDescriptor->Type[0] |= LV2_PLUGIN_MULTI_EQ;
  487. if (typeNodes.contains(lv2World.class_oscillator))
  488. rdfDescriptor->Type[1] |= LV2_PLUGIN_OSCILLATOR;
  489. if (typeNodes.contains(lv2World.class_paraEQ))
  490. rdfDescriptor->Type[0] |= LV2_PLUGIN_PARA_EQ;
  491. if (typeNodes.contains(lv2World.class_phaser))
  492. rdfDescriptor->Type[1] |= LV2_PLUGIN_PHASER;
  493. if (typeNodes.contains(lv2World.class_pitch))
  494. rdfDescriptor->Type[1] |= LV2_PLUGIN_PITCH;
  495. if (typeNodes.contains(lv2World.class_reverb))
  496. rdfDescriptor->Type[0] |= LV2_PLUGIN_REVERB;
  497. if (typeNodes.contains(lv2World.class_simulator))
  498. rdfDescriptor->Type[0] |= LV2_PLUGIN_SIMULATOR;
  499. if (typeNodes.contains(lv2World.class_spatial))
  500. rdfDescriptor->Type[1] |= LV2_PLUGIN_SPATIAL;
  501. if (typeNodes.contains(lv2World.class_spectral))
  502. rdfDescriptor->Type[1] |= LV2_PLUGIN_SPECTRAL;
  503. if (typeNodes.contains(lv2World.class_utility))
  504. rdfDescriptor->Type[1] |= LV2_PLUGIN_UTILITY;
  505. if (typeNodes.contains(lv2World.class_waveshaper))
  506. rdfDescriptor->Type[0] |= LV2_PLUGIN_WAVESHAPER;
  507. }
  508. lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
  509. }
  510. // -------------------------------------------------------------------
  511. // Set Plugin Information
  512. {
  513. rdfDescriptor->URI = carla_strdup(uri);
  514. if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
  515. {
  516. if (const char* const name = lilv_node_as_string(nameNode))
  517. rdfDescriptor->Name = carla_strdup(name);
  518. lilv_node_free(nameNode);
  519. }
  520. if (const char* const author = lilvPlugin.get_author_name().as_string())
  521. rdfDescriptor->Author = carla_strdup(author);
  522. if (const char* const binary = lilvPlugin.get_library_uri().as_string())
  523. rdfDescriptor->Binary = carla_strdup_free(lilv_file_uri_parse(binary, nullptr));
  524. if (const char* const bundle = lilvPlugin.get_bundle_uri().as_string())
  525. rdfDescriptor->Bundle = carla_strdup_free(lilv_file_uri_parse(bundle, nullptr));
  526. Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
  527. if (licenseNodes.size() > 0)
  528. {
  529. if (const char* const license = licenseNodes.get_first().as_string())
  530. rdfDescriptor->License = carla_strdup(license);
  531. }
  532. lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
  533. }
  534. // -------------------------------------------------------------------
  535. // Set Plugin UniqueID
  536. {
  537. Lilv::Nodes replaceNodes(lilvPlugin.get_value(lv2World.dct_replaces));
  538. if (replaceNodes.size() > 0)
  539. {
  540. Lilv::Node replaceNode(replaceNodes.get_first());
  541. if (replaceNode.is_uri())
  542. {
  543. #ifdef USE_QT
  544. const QString replaceURI(replaceNode.as_uri());
  545. if (replaceURI.startsWith("urn:"))
  546. {
  547. const QString replaceId(replaceURI.split(":").last());
  548. bool ok;
  549. const ulong uniqueId(replaceId.toULong(&ok));
  550. if (ok && uniqueId != 0)
  551. rdfDescriptor->UniqueID = uniqueId;
  552. }
  553. #else
  554. const juce::String replaceURI(replaceNode.as_uri());
  555. if (replaceURI.startsWith("urn:"))
  556. {
  557. const int uniqueId(replaceURI.getTrailingIntValue());
  558. if (uniqueId > 0)
  559. rdfDescriptor->UniqueID = static_cast<ulong>(uniqueId);
  560. }
  561. #endif
  562. }
  563. }
  564. lilv_nodes_free(const_cast<LilvNodes*>(replaceNodes.me));
  565. }
  566. // -------------------------------------------------------------------
  567. // Set Plugin Ports
  568. if (lilvPlugin.get_num_ports() > 0)
  569. {
  570. rdfDescriptor->PortCount = lilvPlugin.get_num_ports();
  571. rdfDescriptor->Ports = new LV2_RDF_Port[rdfDescriptor->PortCount];
  572. for (uint32_t i = 0; i < rdfDescriptor->PortCount; ++i)
  573. {
  574. Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
  575. LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[i]);
  576. // -----------------------------------------------------------
  577. // Set Port Information
  578. {
  579. if (LilvNode* const nameNode = lilv_port_get_name(lilvPlugin.me, lilvPort.me))
  580. {
  581. if (const char* const name = lilv_node_as_string(nameNode))
  582. rdfPort->Name = carla_strdup(name);
  583. lilv_node_free(nameNode);
  584. }
  585. if (const char* const symbol = lilv_node_as_string(lilvPort.get_symbol()))
  586. rdfPort->Symbol = carla_strdup(symbol);
  587. }
  588. // -----------------------------------------------------------
  589. // Set Port Mode and Type
  590. {
  591. // Input or Output
  592. /**/ if (lilvPort.is_a(lv2World.port_input))
  593. rdfPort->Types |= LV2_PORT_INPUT;
  594. else if (lilvPort.is_a(lv2World.port_output))
  595. rdfPort->Types |= LV2_PORT_OUTPUT;
  596. else
  597. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is not input or output", uri, rdfPort->Name);
  598. // Data Type
  599. /**/ if (lilvPort.is_a(lv2World.port_control))
  600. {
  601. rdfPort->Types |= LV2_PORT_CONTROL;
  602. }
  603. else if (lilvPort.is_a(lv2World.port_audio))
  604. {
  605. rdfPort->Types |= LV2_PORT_AUDIO;
  606. }
  607. else if (lilvPort.is_a(lv2World.port_cv))
  608. {
  609. rdfPort->Types |= LV2_PORT_CV;
  610. }
  611. else if (lilvPort.is_a(lv2World.port_atom))
  612. {
  613. rdfPort->Types |= LV2_PORT_ATOM;
  614. Lilv::Nodes bufferTypeNodes(lilvPort.get_value(lv2World.atom_bufferType));
  615. for (LilvIter* it = lilv_nodes_begin(bufferTypeNodes.me); ! lilv_nodes_is_end(bufferTypeNodes.me, it); it = lilv_nodes_next(bufferTypeNodes.me, it))
  616. {
  617. const Lilv::Node node(lilv_nodes_get(bufferTypeNodes.me, it));
  618. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  619. if (node.equals(lv2World.atom_sequence))
  620. rdfPort->Types |= LV2_PORT_ATOM_SEQUENCE;
  621. else
  622. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses an unknown atom buffer type '%s'", uri, rdfPort->Name, node.as_uri());
  623. }
  624. Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));
  625. for (LilvIter* it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
  626. {
  627. const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
  628. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  629. /**/ if (node.equals(lv2World.midi_event))
  630. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  631. else if (node.equals(lv2World.patch_message))
  632. rdfPort->Types |= LV2_PORT_DATA_PATCH_MESSAGE;
  633. else if (node.equals(lv2World.time_position))
  634. rdfPort->Types |= LV2_PORT_DATA_TIME_POSITION;
  635. #if 0
  636. // something new we don't support yet?
  637. else if (std::strstr(node.as_uri(), "lv2plug.in/") != nullptr)
  638. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of atom type but has unsupported data '%s'", uri, rdfPort->Name, node.as_uri());
  639. #endif
  640. }
  641. lilv_nodes_free(const_cast<LilvNodes*>(bufferTypeNodes.me));
  642. lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
  643. }
  644. else if (lilvPort.is_a(lv2World.port_event))
  645. {
  646. rdfPort->Types |= LV2_PORT_EVENT;
  647. bool supported = false;
  648. if (lilvPort.supports_event(lv2World.midi_event))
  649. {
  650. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  651. supported = true;
  652. }
  653. if (lilvPort.supports_event(lv2World.patch_message))
  654. {
  655. rdfPort->Types |= LV2_PORT_DATA_PATCH_MESSAGE;
  656. supported = true;
  657. }
  658. if (lilvPort.supports_event(lv2World.time_position))
  659. {
  660. rdfPort->Types |= LV2_PORT_DATA_TIME_POSITION;
  661. supported = true;
  662. }
  663. if (! supported)
  664. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of event type but has unsupported data", uri, rdfPort->Name);
  665. }
  666. else if (lilvPort.is_a(lv2World.port_midi))
  667. {
  668. rdfPort->Types |= LV2_PORT_MIDI_LL;
  669. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  670. }
  671. else
  672. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of unkown data type", uri, rdfPort->Name);
  673. }
  674. // -----------------------------------------------------------
  675. // Set Port Properties
  676. {
  677. if (lilvPort.has_property(lv2World.pprop_optional))
  678. rdfPort->Properties |= LV2_PORT_OPTIONAL;
  679. if (lilvPort.has_property(lv2World.pprop_enumeration))
  680. rdfPort->Properties |= LV2_PORT_ENUMERATION;
  681. if (lilvPort.has_property(lv2World.pprop_integer))
  682. rdfPort->Properties |= LV2_PORT_INTEGER;
  683. if (lilvPort.has_property(lv2World.pprop_sampleRate))
  684. rdfPort->Properties |= LV2_PORT_SAMPLE_RATE;
  685. if (lilvPort.has_property(lv2World.pprop_toggled))
  686. rdfPort->Properties |= LV2_PORT_TOGGLED;
  687. if (lilvPort.has_property(lv2World.pprop_artifacts))
  688. rdfPort->Properties |= LV2_PORT_CAUSES_ARTIFACTS;
  689. if (lilvPort.has_property(lv2World.pprop_continuousCV))
  690. rdfPort->Properties |= LV2_PORT_CONTINUOUS_CV;
  691. if (lilvPort.has_property(lv2World.pprop_discreteCV))
  692. rdfPort->Properties |= LV2_PORT_DISCRETE_CV;
  693. if (lilvPort.has_property(lv2World.pprop_expensive))
  694. rdfPort->Properties |= LV2_PORT_EXPENSIVE;
  695. if (lilvPort.has_property(lv2World.pprop_strictBounds))
  696. rdfPort->Properties |= LV2_PORT_STRICT_BOUNDS;
  697. if (lilvPort.has_property(lv2World.pprop_logarithmic))
  698. rdfPort->Properties |= LV2_PORT_LOGARITHMIC;
  699. if (lilvPort.has_property(lv2World.pprop_notAutomatic))
  700. rdfPort->Properties |= LV2_PORT_NOT_AUTOMATIC;
  701. if (lilvPort.has_property(lv2World.pprop_notOnGUI))
  702. rdfPort->Properties |= LV2_PORT_NOT_ON_GUI;
  703. if (lilvPort.has_property(lv2World.pprop_trigger))
  704. rdfPort->Properties |= LV2_PORT_TRIGGER;
  705. if (lilvPort.has_property(lv2World.pprop_nonAutomable))
  706. rdfPort->Properties |= LV2_PORT_NON_AUTOMABLE;
  707. if (lilvPort.has_property(lv2World.reportsLatency))
  708. rdfPort->Designation = LV2_PORT_DESIGNATION_LATENCY;
  709. // no port properties set, check if using old/invalid ones
  710. if (rdfPort->Properties == 0x0)
  711. {
  712. const Lilv::Node oldPropArtifacts(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#causesArtifacts"));
  713. const Lilv::Node oldPropContinuousCV(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#continuousCV"));
  714. const Lilv::Node oldPropDiscreteCV(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#discreteCV"));
  715. const Lilv::Node oldPropExpensive(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#expensive"));
  716. const Lilv::Node oldPropStrictBounds(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#hasStrictBounds"));
  717. const Lilv::Node oldPropLogarithmic(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#logarithmic"));
  718. const Lilv::Node oldPropNotAutomatic(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#notAutomatic"));
  719. const Lilv::Node oldPropNotOnGUI(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#notOnGUI"));
  720. const Lilv::Node oldPropTrigger(lv2World.new_uri("http://lv2plug.in/ns/dev/extportinfo#trigger"));
  721. if (lilvPort.has_property(oldPropArtifacts))
  722. {
  723. rdfPort->Properties |= LV2_PORT_CAUSES_ARTIFACTS;
  724. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'causesArtifacts'", uri, rdfPort->Name);
  725. }
  726. if (lilvPort.has_property(oldPropContinuousCV))
  727. {
  728. rdfPort->Properties |= LV2_PORT_CONTINUOUS_CV;
  729. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'continuousCV'", uri, rdfPort->Name);
  730. }
  731. if (lilvPort.has_property(oldPropDiscreteCV))
  732. {
  733. rdfPort->Properties |= LV2_PORT_DISCRETE_CV;
  734. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'discreteCV'", uri, rdfPort->Name);
  735. }
  736. if (lilvPort.has_property(oldPropExpensive))
  737. {
  738. rdfPort->Properties |= LV2_PORT_EXPENSIVE;
  739. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'expensive'", uri, rdfPort->Name);
  740. }
  741. if (lilvPort.has_property(oldPropStrictBounds))
  742. {
  743. rdfPort->Properties |= LV2_PORT_STRICT_BOUNDS;
  744. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'hasStrictBounds'", uri, rdfPort->Name);
  745. }
  746. if (lilvPort.has_property(oldPropLogarithmic))
  747. {
  748. rdfPort->Properties |= LV2_PORT_LOGARITHMIC;
  749. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'logarithmic'", uri, rdfPort->Name);
  750. }
  751. if (lilvPort.has_property(oldPropNotAutomatic))
  752. {
  753. rdfPort->Properties |= LV2_PORT_NOT_AUTOMATIC;
  754. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notAutomatic'", uri, rdfPort->Name);
  755. }
  756. if (lilvPort.has_property(oldPropNotOnGUI))
  757. {
  758. rdfPort->Properties |= LV2_PORT_NOT_ON_GUI;
  759. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notOnGUI'", uri, rdfPort->Name);
  760. }
  761. if (lilvPort.has_property(oldPropTrigger))
  762. {
  763. rdfPort->Properties |= LV2_PORT_TRIGGER;
  764. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'trigger'", uri, rdfPort->Name);
  765. }
  766. }
  767. }
  768. // -----------------------------------------------------------
  769. // Set Port Designation
  770. {
  771. if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
  772. {
  773. if (const char* const designation = lilv_node_as_string(designationNode))
  774. {
  775. /**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
  776. rdfPort->Designation = LV2_PORT_DESIGNATION_CONTROL;
  777. else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
  778. rdfPort->Designation = LV2_PORT_DESIGNATION_FREEWHEELING;
  779. else if (std::strcmp(designation, LV2_CORE__latency) == 0)
  780. rdfPort->Designation = LV2_PORT_DESIGNATION_LATENCY;
  781. else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
  782. rdfPort->Designation = LV2_PORT_DESIGNATION_SAMPLE_RATE;
  783. else if (std::strcmp(designation, LV2_TIME__bar) == 0)
  784. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BAR;
  785. else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
  786. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BAR_BEAT;
  787. else if (std::strcmp(designation, LV2_TIME__beat) == 0)
  788. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEAT;
  789. else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
  790. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEAT_UNIT;
  791. else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
  792. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR;
  793. else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
  794. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE;
  795. else if (std::strcmp(designation, LV2_TIME__frame) == 0)
  796. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_FRAME;
  797. else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
  798. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND;
  799. else if (std::strcmp(designation, LV2_TIME__speed) == 0)
  800. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_SPEED;
  801. else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  802. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT;
  803. else if (std::strncmp(designation, LV2_PARAMETERS_PREFIX, std::strlen(LV2_PARAMETERS_PREFIX)) == 0)
  804. pass();
  805. else if (std::strncmp(designation, LV2_PORT_GROUPS_PREFIX, std::strlen(LV2_PORT_GROUPS_PREFIX)) == 0)
  806. pass();
  807. else
  808. carla_stderr("lv2_rdf_new(\"%s\") - got unknown port designation '%s'", uri, designation);
  809. }
  810. lilv_node_free(designationNode);
  811. }
  812. }
  813. // -----------------------------------------------------------
  814. // Set Port MIDI Map
  815. {
  816. if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me))
  817. {
  818. if (lilv_node_is_blank(midiMapNode))
  819. {
  820. Lilv::Nodes midiMapTypeNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlType, nullptr));
  821. Lilv::Nodes midiMapNumberNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlNumber, nullptr));
  822. if (midiMapTypeNodes.size() == 1 && midiMapNumberNodes.size() == 1)
  823. {
  824. if (const char* const midiMapType = midiMapTypeNodes.get_first().as_string())
  825. {
  826. /**/ if (std::strcmp(midiMapType, LV2_MIDI_Map__CC) == 0)
  827. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
  828. else if (std::strcmp(midiMapType, LV2_MIDI_Map__NRPN) == 0)
  829. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_NRPN;
  830. else
  831. carla_stderr("lv2_rdf_new(\"%s\") - got unknown port Midi-Map type '%s'", uri, midiMapType);
  832. rdfPort->MidiMap.Number = static_cast<uint32_t>(midiMapNumberNodes.get_first().as_int());
  833. }
  834. }
  835. lilv_nodes_free(const_cast<LilvNodes*>(midiMapTypeNodes.me));
  836. lilv_nodes_free(const_cast<LilvNodes*>(midiMapNumberNodes.me));
  837. }
  838. lilv_node_free(midiMapNode);
  839. }
  840. // TODO - also check using new official MIDI API too
  841. }
  842. // -----------------------------------------------------------
  843. // Set Port Points
  844. {
  845. if (LilvNode* const defNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_default.me))
  846. {
  847. rdfPort->Points.Hints |= LV2_PORT_POINT_DEFAULT;
  848. rdfPort->Points.Default = lilv_node_as_float(defNode);
  849. lilv_node_free(defNode);
  850. }
  851. if (LilvNode* const minNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_minimum.me))
  852. {
  853. rdfPort->Points.Hints |= LV2_PORT_POINT_MINIMUM;
  854. rdfPort->Points.Minimum = lilv_node_as_float(minNode);
  855. lilv_node_free(minNode);
  856. }
  857. if (LilvNode* const maxNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_maximum.me))
  858. {
  859. rdfPort->Points.Hints |= LV2_PORT_POINT_MAXIMUM;
  860. rdfPort->Points.Maximum = lilv_node_as_float(maxNode);
  861. lilv_node_free(maxNode);
  862. }
  863. }
  864. // -----------------------------------------------------------
  865. // Set Port Unit
  866. {
  867. if (LilvNode* const unitUnitNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.unit_unit.me))
  868. {
  869. if (lilv_node_is_uri(unitUnitNode))
  870. {
  871. if (const char* const unitUnit = lilv_node_as_uri(unitUnitNode))
  872. {
  873. rdfPort->Unit.Hints |= LV2_PORT_UNIT_UNIT;
  874. /**/ if (std::strcmp(unitUnit, LV2_UNITS__bar) == 0)
  875. rdfPort->Unit.Unit = LV2_PORT_UNIT_BAR;
  876. else if (std::strcmp(unitUnit, LV2_UNITS__beat) == 0)
  877. rdfPort->Unit.Unit = LV2_PORT_UNIT_BEAT;
  878. else if (std::strcmp(unitUnit, LV2_UNITS__bpm) == 0)
  879. rdfPort->Unit.Unit = LV2_PORT_UNIT_BPM;
  880. else if (std::strcmp(unitUnit, LV2_UNITS__cent) == 0)
  881. rdfPort->Unit.Unit = LV2_PORT_UNIT_CENT;
  882. else if (std::strcmp(unitUnit, LV2_UNITS__cm) == 0)
  883. rdfPort->Unit.Unit = LV2_PORT_UNIT_CM;
  884. else if (std::strcmp(unitUnit, LV2_UNITS__coef) == 0)
  885. rdfPort->Unit.Unit = LV2_PORT_UNIT_COEF;
  886. else if (std::strcmp(unitUnit, LV2_UNITS__db) == 0)
  887. rdfPort->Unit.Unit = LV2_PORT_UNIT_DB;
  888. else if (std::strcmp(unitUnit, LV2_UNITS__degree) == 0)
  889. rdfPort->Unit.Unit = LV2_PORT_UNIT_DEGREE;
  890. else if (std::strcmp(unitUnit, LV2_UNITS__frame) == 0)
  891. rdfPort->Unit.Unit = LV2_PORT_UNIT_FRAME;
  892. else if (std::strcmp(unitUnit, LV2_UNITS__hz) == 0)
  893. rdfPort->Unit.Unit = LV2_PORT_UNIT_HZ;
  894. else if (std::strcmp(unitUnit, LV2_UNITS__inch) == 0)
  895. rdfPort->Unit.Unit = LV2_PORT_UNIT_INCH;
  896. else if (std::strcmp(unitUnit, LV2_UNITS__khz) == 0)
  897. rdfPort->Unit.Unit = LV2_PORT_UNIT_KHZ;
  898. else if (std::strcmp(unitUnit, LV2_UNITS__km) == 0)
  899. rdfPort->Unit.Unit = LV2_PORT_UNIT_KM;
  900. else if (std::strcmp(unitUnit, LV2_UNITS__m) == 0)
  901. rdfPort->Unit.Unit = LV2_PORT_UNIT_M;
  902. else if (std::strcmp(unitUnit, LV2_UNITS__mhz) == 0)
  903. rdfPort->Unit.Unit = LV2_PORT_UNIT_MHZ;
  904. else if (std::strcmp(unitUnit, LV2_UNITS__midiNote) == 0)
  905. rdfPort->Unit.Unit = LV2_PORT_UNIT_MIDINOTE;
  906. else if (std::strcmp(unitUnit, LV2_UNITS__mile) == 0)
  907. rdfPort->Unit.Unit = LV2_PORT_UNIT_MILE;
  908. else if (std::strcmp(unitUnit, LV2_UNITS__min) == 0)
  909. rdfPort->Unit.Unit = LV2_PORT_UNIT_MIN;
  910. else if (std::strcmp(unitUnit, LV2_UNITS__mm) == 0)
  911. rdfPort->Unit.Unit = LV2_PORT_UNIT_MM;
  912. else if (std::strcmp(unitUnit, LV2_UNITS__ms) == 0)
  913. rdfPort->Unit.Unit = LV2_PORT_UNIT_MS;
  914. else if (std::strcmp(unitUnit, LV2_UNITS__oct) == 0)
  915. rdfPort->Unit.Unit = LV2_PORT_UNIT_OCT;
  916. else if (std::strcmp(unitUnit, LV2_UNITS__pc) == 0)
  917. rdfPort->Unit.Unit = LV2_PORT_UNIT_PC;
  918. else if (std::strcmp(unitUnit, LV2_UNITS__s) == 0)
  919. rdfPort->Unit.Unit = LV2_PORT_UNIT_S;
  920. else if (std::strcmp(unitUnit, LV2_UNITS__semitone12TET) == 0)
  921. rdfPort->Unit.Unit = LV2_PORT_UNIT_SEMITONE;
  922. else
  923. carla_stderr("lv2_rdf_new(\"%s\") - got unknown unit unit '%s'", uri, unitUnit);
  924. }
  925. }
  926. if (LilvNode* const unitNameNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_name.me, nullptr))
  927. {
  928. if (const char* const unitName = lilv_node_as_string(unitNameNode))
  929. {
  930. rdfPort->Unit.Hints |= LV2_PORT_UNIT_NAME;
  931. rdfPort->Unit.Name = carla_strdup(unitName);
  932. }
  933. lilv_node_free(unitNameNode);
  934. }
  935. if (LilvNode* const unitRenderNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_render.me, nullptr))
  936. {
  937. if (const char* const unitRender = lilv_node_as_string(unitRenderNode))
  938. {
  939. rdfPort->Unit.Hints |= LV2_PORT_UNIT_RENDER;
  940. rdfPort->Unit.Render = carla_strdup(unitRender);
  941. }
  942. lilv_node_free(unitRenderNode);
  943. }
  944. if (LilvNode* const unitSymbolNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_symbol.me, nullptr))
  945. {
  946. if (const char* const unitSymbol = lilv_node_as_string(unitSymbolNode))
  947. {
  948. rdfPort->Unit.Hints |= LV2_PORT_UNIT_SYMBOL;
  949. rdfPort->Unit.Symbol = carla_strdup(unitSymbol);
  950. }
  951. lilv_node_free(unitSymbolNode);
  952. }
  953. lilv_node_free(unitUnitNode);
  954. }
  955. }
  956. // -----------------------------------------------------------
  957. // Set Port Minimum Size
  958. {
  959. if (LilvNode* const minimumSizeNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.rz_minSize.me))
  960. {
  961. const int minimumSize(lilv_node_as_int(minimumSizeNode));
  962. if (minimumSize > 0)
  963. rdfPort->MinimumSize = static_cast<uint32_t>(minimumSize);
  964. else
  965. carla_safe_assert_int("minimumSize > 0", __FILE__, __LINE__, minimumSize);
  966. lilv_node_free(minimumSizeNode);
  967. }
  968. }
  969. // -----------------------------------------------------------
  970. // Set Port Scale Points
  971. {
  972. Lilv::ScalePoints lilvScalePoints(lilvPort.get_scale_points());
  973. if (lilvScalePoints.size() > 0)
  974. {
  975. rdfPort->ScalePointCount = lilvScalePoints.size();
  976. rdfPort->ScalePoints = new LV2_RDF_PortScalePoint[rdfPort->ScalePointCount];
  977. // get all scalepoints and sort them by value
  978. LilvScalePointMap sortedpoints;
  979. LILV_FOREACH(scale_points, it, lilvScalePoints)
  980. {
  981. Lilv::ScalePoint lilvScalePoint(lilvScalePoints.get(it));
  982. CARLA_SAFE_ASSERT_CONTINUE(lilvScalePoint.get_label() != nullptr);
  983. if (const LilvNode* const valuenode = lilvScalePoint.get_value())
  984. {
  985. const double valueid = lilv_node_as_float(valuenode);
  986. sortedpoints[valueid] = lilvScalePoint.me;
  987. }
  988. }
  989. // now safe to store, sorted by using std::map
  990. uint32_t h = 0;
  991. for (LilvScalePointMap::iterator it=sortedpoints.begin(), end=sortedpoints.end(); it != end; ++it)
  992. {
  993. CARLA_SAFE_ASSERT_BREAK(h < rdfPort->ScalePointCount);
  994. LV2_RDF_PortScalePoint* const rdfScalePoint(&rdfPort->ScalePoints[h++]);
  995. const LilvScalePoint* const scalepoint = it->second;
  996. const LilvNode* const xlabel = lilv_scale_point_get_label(scalepoint);
  997. const LilvNode* const xvalue = lilv_scale_point_get_value(scalepoint);
  998. rdfScalePoint->Label = carla_strdup(lilv_node_as_string(xlabel));
  999. rdfScalePoint->Value = lilv_node_as_float(xvalue);
  1000. }
  1001. }
  1002. lilv_nodes_free(const_cast<LilvNodes*>(lilvScalePoints.me));
  1003. }
  1004. }
  1005. }
  1006. // -------------------------------------------------------------------
  1007. // Set Plugin Presets
  1008. if (loadPresets)
  1009. {
  1010. Lilv::Nodes presetNodes(lilvPlugin.get_related(lv2World.preset_preset));
  1011. if (presetNodes.size() > 0)
  1012. {
  1013. // create a list of preset URIs (for sorting and unique-ness)
  1014. #ifdef USE_QT
  1015. QStringList presetListURIs;
  1016. LILV_FOREACH(nodes, it, presetNodes)
  1017. {
  1018. Lilv::Node presetNode(presetNodes.get(it));
  1019. QString presetURI(presetNode.as_uri());
  1020. if (! (presetURI.trimmed().isEmpty() || presetListURIs.contains(presetURI)))
  1021. presetListURIs.append(presetURI);
  1022. }
  1023. presetListURIs.sort();
  1024. rdfDescriptor->PresetCount = static_cast<uint32_t>(presetListURIs.count());
  1025. #else
  1026. juce::StringArray presetListURIs;
  1027. LILV_FOREACH(nodes, it, presetNodes)
  1028. {
  1029. Lilv::Node presetNode(presetNodes.get(it));
  1030. juce::String presetURI(presetNode.as_uri());
  1031. if (presetURI.trim().isNotEmpty())
  1032. presetListURIs.addIfNotAlreadyThere(presetURI);
  1033. }
  1034. presetListURIs.sortNatural();
  1035. rdfDescriptor->PresetCount = static_cast<uint32_t>(presetListURIs.size());
  1036. #endif
  1037. // create presets with unique URIs
  1038. rdfDescriptor->Presets = new LV2_RDF_Preset[rdfDescriptor->PresetCount];
  1039. // set preset data
  1040. LILV_FOREACH(nodes, it, presetNodes)
  1041. {
  1042. Lilv::Node presetNode(presetNodes.get(it));
  1043. const char* const presetURI(presetNode.as_uri());
  1044. CARLA_SAFE_ASSERT_CONTINUE(presetURI != nullptr && presetURI[0] != '\0');
  1045. // try to find label without loading the preset resource first
  1046. Lilv::Nodes presetLabelNodes(lv2World.find_nodes(presetNode, lv2World.rdfs_label, nullptr));
  1047. // failed, try loading resource
  1048. if (presetLabelNodes.size() == 0)
  1049. {
  1050. // if loading resource fails, skip this preset
  1051. if (lv2World.load_resource(presetNode) == -1)
  1052. continue;
  1053. // ok, let's try again
  1054. presetLabelNodes = lv2World.find_nodes(presetNode, lv2World.rdfs_label, nullptr);
  1055. }
  1056. if (presetLabelNodes.size() > 0)
  1057. {
  1058. #ifdef USE_QT
  1059. const int index(presetListURIs.indexOf(QString(presetURI)));
  1060. #else
  1061. const int index(presetListURIs.indexOf(juce::String(presetURI)));
  1062. #endif
  1063. CARLA_SAFE_ASSERT_CONTINUE(index >= 0 && index < static_cast<int>(rdfDescriptor->PresetCount));
  1064. LV2_RDF_Preset* const rdfPreset(&rdfDescriptor->Presets[index]);
  1065. // ---------------------------------------------------
  1066. // Set Preset Information
  1067. rdfPreset->URI = carla_strdup(presetURI);
  1068. if (const char* const label = presetLabelNodes.get_first().as_string())
  1069. rdfPreset->Label = carla_strdup(label);
  1070. lilv_nodes_free(const_cast<LilvNodes*>(presetLabelNodes.me));
  1071. }
  1072. }
  1073. }
  1074. lilv_nodes_free(const_cast<LilvNodes*>(presetNodes.me));
  1075. }
  1076. // -------------------------------------------------------------------
  1077. // Set Plugin Features
  1078. {
  1079. Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
  1080. if (lilvFeatureNodes.size() > 0)
  1081. {
  1082. Lilv::Nodes lilvFeatureNodesR(lilvPlugin.get_required_features());
  1083. rdfDescriptor->FeatureCount = lilvFeatureNodes.size();
  1084. rdfDescriptor->Features = new LV2_RDF_Feature[rdfDescriptor->FeatureCount];
  1085. uint32_t h = 0;
  1086. LILV_FOREACH(nodes, it, lilvFeatureNodes)
  1087. {
  1088. CARLA_SAFE_ASSERT_BREAK(h < rdfDescriptor->FeatureCount);
  1089. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
  1090. LV2_RDF_Feature* const rdfFeature(&rdfDescriptor->Features[h++]);
  1091. rdfFeature->Required = lilvFeatureNodesR.contains(lilvFeatureNode);
  1092. if (const char* const featureURI = lilvFeatureNode.as_uri())
  1093. rdfFeature->URI = carla_strdup(featureURI);
  1094. else
  1095. rdfFeature->URI = nullptr;
  1096. }
  1097. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodesR.me));
  1098. }
  1099. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  1100. }
  1101. // -------------------------------------------------------------------
  1102. // Set Plugin Extensions
  1103. {
  1104. Lilv::Nodes lilvExtensionDataNodes(lilvPlugin.get_extension_data());
  1105. if (lilvExtensionDataNodes.size() > 0)
  1106. {
  1107. rdfDescriptor->ExtensionCount = lilvExtensionDataNodes.size();
  1108. rdfDescriptor->Extensions = new LV2_URI[rdfDescriptor->ExtensionCount];
  1109. uint32_t h = 0;
  1110. LILV_FOREACH(nodes, it, lilvExtensionDataNodes)
  1111. {
  1112. CARLA_SAFE_ASSERT_BREAK(h < rdfDescriptor->ExtensionCount);
  1113. Lilv::Node lilvExtensionDataNode(lilvExtensionDataNodes.get(it));
  1114. LV2_URI* const rdfExtension(&rdfDescriptor->Extensions[h++]);
  1115. if (lilvExtensionDataNode.is_uri())
  1116. {
  1117. if (const char* const extURI = lilvExtensionDataNode.as_uri())
  1118. {
  1119. *rdfExtension = carla_strdup(extURI);
  1120. continue;
  1121. }
  1122. }
  1123. *rdfExtension = nullptr;
  1124. }
  1125. for (uint32_t x=h; x < rdfDescriptor->ExtensionCount; ++x)
  1126. rdfDescriptor->Extensions[x] = nullptr;
  1127. }
  1128. lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me));
  1129. }
  1130. // -------------------------------------------------------------------
  1131. // Set Plugin UIs
  1132. {
  1133. const bool hasMODGui(lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr);
  1134. Lilv::UIs lilvUIs(lilvPlugin.get_uis());
  1135. if (lilvUIs.size() > 0 || hasMODGui)
  1136. {
  1137. rdfDescriptor->UICount = lilvUIs.size() + (hasMODGui ? 1 : 0);
  1138. rdfDescriptor->UIs = new LV2_RDF_UI[rdfDescriptor->UICount];
  1139. uint32_t h = 0;
  1140. LILV_FOREACH(uis, it, lilvUIs)
  1141. {
  1142. CARLA_SAFE_ASSERT_BREAK(h < rdfDescriptor->UICount);
  1143. Lilv::UI lilvUI(lilvUIs.get(it));
  1144. LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[h++]);
  1145. // -------------------------------------------------------
  1146. // Set UI Type
  1147. /**/ if (lilvUI.is_a(lv2World.ui_gtk2))
  1148. rdfUI->Type = LV2_UI_GTK2;
  1149. else if (lilvUI.is_a(lv2World.ui_gtk3))
  1150. rdfUI->Type = LV2_UI_GTK3;
  1151. else if (lilvUI.is_a(lv2World.ui_qt4))
  1152. rdfUI->Type = LV2_UI_QT4;
  1153. else if (lilvUI.is_a(lv2World.ui_qt5))
  1154. rdfUI->Type = LV2_UI_QT5;
  1155. else if (lilvUI.is_a(lv2World.ui_cocoa))
  1156. rdfUI->Type = LV2_UI_COCOA;
  1157. else if (lilvUI.is_a(lv2World.ui_windows))
  1158. rdfUI->Type = LV2_UI_WINDOWS;
  1159. else if (lilvUI.is_a(lv2World.ui_x11))
  1160. rdfUI->Type = LV2_UI_X11;
  1161. else if (lilvUI.is_a(lv2World.ui_external))
  1162. rdfUI->Type = LV2_UI_EXTERNAL;
  1163. else if (lilvUI.is_a(lv2World.ui_externalOld))
  1164. rdfUI->Type = LV2_UI_OLD_EXTERNAL;
  1165. else if (lilvUI.is_a(lv2World.ui_externalOld2))
  1166. pass();
  1167. else
  1168. carla_stderr("lv2_rdf_new(\"%s\") - UI '%s' is of unknown type", uri, lilvUI.get_uri().as_uri());
  1169. // -------------------------------------------------------
  1170. // Set UI Information
  1171. {
  1172. if (const char* const uiURI = lilvUI.get_uri().as_uri())
  1173. rdfUI->URI = carla_strdup(uiURI);
  1174. if (const char* const uiBinary = lilvUI.get_binary_uri().as_string())
  1175. rdfUI->Binary = carla_strdup_free(lilv_file_uri_parse(uiBinary, nullptr));
  1176. if (const char* const uiBundle = lilvUI.get_bundle_uri().as_string())
  1177. rdfUI->Bundle = carla_strdup_free(lilv_file_uri_parse(uiBundle, nullptr));
  1178. }
  1179. // -------------------------------------------------------
  1180. // Set UI Features
  1181. {
  1182. Lilv::Nodes lilvFeatureNodes(lilvUI.get_supported_features());
  1183. if (lilvFeatureNodes.size() > 0)
  1184. {
  1185. Lilv::Nodes lilvFeatureNodesR(lilvUI.get_required_features());
  1186. rdfUI->FeatureCount = lilvFeatureNodes.size();
  1187. rdfUI->Features = new LV2_RDF_Feature[rdfUI->FeatureCount];
  1188. uint32_t h2 = 0;
  1189. LILV_FOREACH(nodes, it2, lilvFeatureNodes)
  1190. {
  1191. CARLA_SAFE_ASSERT_BREAK(h2 < rdfUI->FeatureCount);
  1192. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it2));
  1193. LV2_RDF_Feature* const rdfFeature(&rdfUI->Features[h2++]);
  1194. rdfFeature->Required = lilvFeatureNodesR.contains(lilvFeatureNode);
  1195. if (const char* const featureURI = lilvFeatureNode.as_uri())
  1196. rdfFeature->URI = carla_strdup(featureURI);
  1197. else
  1198. rdfFeature->URI = nullptr;
  1199. }
  1200. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodesR.me));
  1201. }
  1202. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  1203. }
  1204. // -------------------------------------------------------
  1205. // Set UI Extensions
  1206. {
  1207. Lilv::Nodes lilvExtensionDataNodes(lilvUI.get_extension_data());
  1208. if (lilvExtensionDataNodes.size() > 0)
  1209. {
  1210. rdfUI->ExtensionCount = lilvExtensionDataNodes.size();
  1211. rdfUI->Extensions = new LV2_URI[rdfUI->ExtensionCount];
  1212. uint32_t h2 = 0;
  1213. LILV_FOREACH(nodes, it2, lilvExtensionDataNodes)
  1214. {
  1215. CARLA_SAFE_ASSERT_BREAK(h2 < rdfUI->ExtensionCount);
  1216. Lilv::Node lilvExtensionDataNode(lilvExtensionDataNodes.get(it2));
  1217. LV2_URI* const rdfExtension(&rdfUI->Extensions[h2++]);
  1218. if (lilvExtensionDataNode.is_uri())
  1219. {
  1220. if (const char* const extURI = lilvExtensionDataNode.as_uri())
  1221. {
  1222. *rdfExtension = carla_strdup(extURI);
  1223. continue;
  1224. }
  1225. }
  1226. *rdfExtension = nullptr;
  1227. }
  1228. for (uint32_t x2=h2; x2 < rdfUI->ExtensionCount; ++x2)
  1229. rdfUI->Extensions[x2] = nullptr;
  1230. }
  1231. lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me));
  1232. }
  1233. }
  1234. for (; hasMODGui;)
  1235. {
  1236. CARLA_SAFE_ASSERT_BREAK(h == rdfDescriptor->UICount-1);
  1237. LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[h++]);
  1238. // -------------------------------------------------------
  1239. // Set UI Type
  1240. rdfUI->Type = LV2_UI_MOD;
  1241. // -------------------------------------------------------
  1242. // Set UI Information
  1243. if (const char* const resDir = lilvPlugin.get_modgui_resources_directory().as_uri())
  1244. rdfUI->URI = carla_strdup_free(lilv_file_uri_parse(resDir, nullptr));
  1245. if (rdfDescriptor->Bundle != nullptr)
  1246. rdfUI->Bundle = carla_strdup(rdfDescriptor->Bundle);
  1247. break;
  1248. }
  1249. }
  1250. lilv_nodes_free(const_cast<LilvNodes*>(lilvUIs.me));
  1251. }
  1252. return rdfDescriptor;
  1253. }
  1254. // -----------------------------------------------------------------------
  1255. // Check if we support a plugin port
  1256. static inline
  1257. bool is_lv2_port_supported(const LV2_Property types) noexcept
  1258. {
  1259. if (LV2_IS_PORT_CONTROL(types))
  1260. return true;
  1261. if (LV2_IS_PORT_AUDIO(types))
  1262. return true;
  1263. if (LV2_IS_PORT_CV(types))
  1264. return true;
  1265. if (LV2_IS_PORT_ATOM_SEQUENCE(types))
  1266. return true;
  1267. if (LV2_IS_PORT_EVENT(types))
  1268. return true;
  1269. if (LV2_IS_PORT_MIDI_LL(types))
  1270. return true;
  1271. return false;
  1272. }
  1273. // -----------------------------------------------------------------------
  1274. // Check if we support a plugin feature
  1275. static inline
  1276. bool is_lv2_feature_supported(const LV2_URI uri) noexcept
  1277. {
  1278. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', false);
  1279. if (std::strcmp(uri, LV2_BUF_SIZE__boundedBlockLength) == 0)
  1280. return true;
  1281. if (std::strcmp(uri, LV2_BUF_SIZE__fixedBlockLength) == 0)
  1282. return true;
  1283. if (std::strcmp(uri, LV2_BUF_SIZE__powerOf2BlockLength) == 0)
  1284. return true;
  1285. if (std::strcmp(uri, LV2_CORE__hardRTCapable) == 0)
  1286. return true;
  1287. if (std::strcmp(uri, LV2_CORE__inPlaceBroken) == 0)
  1288. return true;
  1289. if (std::strcmp(uri, LV2_CORE__isLive) == 0)
  1290. return true;
  1291. if (std::strcmp(uri, LV2_EVENT_URI) == 0)
  1292. return true;
  1293. if (std::strcmp(uri, LV2_LOG__log) == 0)
  1294. return true;
  1295. if (std::strcmp(uri, LV2_OPTIONS__options) == 0)
  1296. return true;
  1297. if (std::strcmp(uri, LV2_PROGRAMS__Host) == 0)
  1298. return true;
  1299. if (std::strcmp(uri, LV2_RESIZE_PORT__resize) == 0)
  1300. return true;
  1301. if (std::strcmp(uri, LV2_RTSAFE_MEMORY_POOL__Pool) == 0)
  1302. return true;
  1303. if (std::strcmp(uri, LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI) == 0)
  1304. return true;
  1305. if (std::strcmp(uri, LV2_STATE__loadDefaultState) == 0)
  1306. return true;
  1307. if (std::strcmp(uri, LV2_STATE__makePath) == 0)
  1308. return true;
  1309. if (std::strcmp(uri, LV2_STATE__mapPath) == 0)
  1310. return true;
  1311. if (std::strcmp(uri, LV2_PORT_PROPS__supportsStrictBounds) == 0)
  1312. return true;
  1313. if (std::strcmp(uri, LV2_URI_MAP_URI) == 0)
  1314. return true;
  1315. if (std::strcmp(uri, LV2_URID__map) == 0)
  1316. return true;
  1317. if (std::strcmp(uri, LV2_URID__unmap) == 0)
  1318. return true;
  1319. if (std::strcmp(uri, LV2_WORKER__schedule) == 0)
  1320. return true;
  1321. return false;
  1322. }
  1323. // -----------------------------------------------------------------------
  1324. // Check if we support a plugin or UI feature
  1325. static inline
  1326. bool is_lv2_ui_feature_supported(const LV2_URI uri) noexcept
  1327. {
  1328. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', false);
  1329. if (is_lv2_feature_supported(uri))
  1330. return true;
  1331. #ifndef BUILD_BRIDGE_UI
  1332. if (std::strcmp(uri, LV2_DATA_ACCESS_URI) == 0)
  1333. return true;
  1334. if (std::strcmp(uri, LV2_INSTANCE_ACCESS_URI) == 0)
  1335. return true;
  1336. #endif
  1337. if (std::strcmp(uri, LV2_UI__fixedSize) == 0)
  1338. return true;
  1339. if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
  1340. return true;
  1341. if (std::strcmp(uri, LV2_UI__makeResident) == 0)
  1342. return true;
  1343. if (std::strcmp(uri, LV2_UI__makeSONameResident) == 0)
  1344. return true;
  1345. if (std::strcmp(uri, LV2_UI__noUserResize) == 0)
  1346. return true;
  1347. if (std::strcmp(uri, LV2_UI__parent) == 0)
  1348. return true;
  1349. if (std::strcmp(uri, LV2_UI__portMap) == 0)
  1350. return true;
  1351. if (std::strcmp(uri, LV2_UI__portSubscribe) == 0)
  1352. return true;
  1353. if (std::strcmp(uri, LV2_UI__resize) == 0)
  1354. return true;
  1355. if (std::strcmp(uri, LV2_UI__touch) == 0)
  1356. return true;
  1357. if (std::strcmp(uri, LV2_EXTERNAL_UI__Widget) == 0)
  1358. return true;
  1359. if (std::strcmp(uri, LV2_EXTERNAL_UI_DEPRECATED_URI) == 0)
  1360. return true;
  1361. return false;
  1362. }
  1363. // -----------------------------------------------------------------------
  1364. #endif // CARLA_LV2_UTILS_HPP_INCLUDED