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 136KB

11 years ago
11 years ago
10 years ago
10 years ago
12 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
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
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
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
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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283
  1. /*
  2. * Carla LV2 utils
  3. * Copyright (C) 2011-2023 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 "CarlaMathUtils.hpp"
  20. #include "CarlaStringList.hpp"
  21. #include "CarlaMIDI.h"
  22. #ifndef nullptr
  23. # undef NULL
  24. # define NULL nullptr
  25. #endif
  26. // disable -Wdocumentation for LV2 headers
  27. #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
  28. # pragma clang diagnostic push
  29. # pragma clang diagnostic ignored "-Wdocumentation"
  30. #endif
  31. #include "lv2/lv2.h"
  32. #include "lv2/atom.h"
  33. #include "lv2/atom-forge.h"
  34. #include "lv2/atom-helpers.h"
  35. #include "lv2/atom-util.h"
  36. #include "lv2/buf-size.h"
  37. #include "lv2/data-access.h"
  38. // dynmanifest
  39. #include "lv2/event.h"
  40. #include "lv2/event-helpers.h"
  41. #include "lv2/inline-display.h"
  42. #include "lv2/instance-access.h"
  43. #include "lv2/log.h"
  44. // logger
  45. #include "lv2/midi.h"
  46. #include "lv2/midnam.h"
  47. // morph
  48. #include "lv2/options.h"
  49. #include "lv2/parameters.h"
  50. #include "lv2/patch.h"
  51. #include "lv2/port-groups.h"
  52. #include "lv2/port-props.h"
  53. #include "lv2/presets.h"
  54. #include "lv2/resize-port.h"
  55. #include "lv2/state.h"
  56. #include "lv2/time.h"
  57. #include "lv2/ui.h"
  58. #include "lv2/units.h"
  59. #include "lv2/uri-map.h"
  60. #include "lv2/urid.h"
  61. #include "lv2/worker.h"
  62. #include "lv2/lv2-miditype.h"
  63. #include "lv2/lv2-midifunctions.h"
  64. #include "lv2/lv2_external_ui.h"
  65. #include "lv2/lv2_kxstudio_properties.h"
  66. #include "lv2/lv2_programs.h"
  67. #include "lv2/lv2_rtmempool.h"
  68. #include "lv2/control-input-port-change-request.h"
  69. #include "lilv/lilvmm.hpp"
  70. #include "sratom/sratom.h"
  71. #include "lilv/config/lilv_config.h"
  72. // enable -Wdocumentation again
  73. #if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) > 300
  74. # pragma clang diagnostic pop
  75. #endif
  76. #include "lv2_rdf.hpp"
  77. #if defined(CARLA_UTILS_USE_QT)
  78. # include <QtCore/QStringList>
  79. #else
  80. # include "water/text/StringArray.h"
  81. #endif
  82. // used for scalepoint sorting
  83. #include <map>
  84. typedef std::map<double,const LilvScalePoint*> LilvScalePointMap;
  85. // --------------------------------------------------------------------------------------------------------------------
  86. // Define namespaces and missing prefixes
  87. #define NS_dct "http://purl.org/dc/terms/"
  88. #define NS_doap "http://usefulinc.com/ns/doap#"
  89. #define NS_rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  90. #define NS_rdfs "http://www.w3.org/2000/01/rdf-schema#"
  91. #define NS_llmm "http://ll-plugins.nongnu.org/lv2/ext/midimap#"
  92. #define NS_devp "http://lv2plug.in/ns/dev/extportinfo#"
  93. #define NS_mod "http://moddevices.com/ns/modgui#"
  94. #define LV2_MIDI_Map__CC "http://ll-plugins.nongnu.org/lv2/namespace#CC"
  95. #define LV2_MIDI_Map__NRPN "http://ll-plugins.nongnu.org/lv2/namespace#NRPN"
  96. #define LV2_MIDI_LL__MidiPort "http://ll-plugins.nongnu.org/lv2/ext/MidiPort"
  97. #define LV2_UI__makeResident LV2_UI_PREFIX "makeResident"
  98. #define LV2_UI__makeSONameResident LV2_UI_PREFIX "makeSONameResident"
  99. // TODO: update LV2 headers once again
  100. #define LV2_CORE__Parameter LV2_CORE_PREFIX "Parameter" ///< http://lv2plug.in/ns/lv2core#Parameter
  101. #define LV2_CORE__enabled LV2_CORE_PREFIX "enabled" ///< http://lv2plug.in/ns/lv2core#enabled
  102. #define LV2_CORE__isSideChain LV2_CORE_PREFIX "isSideChain" ///< http://lv2plug.in/ns/lv2core#isSideChain
  103. // --------------------------------------------------------------------------------------------------------------------
  104. // Custom Atom types
  105. struct LV2_Atom_MidiEvent {
  106. LV2_Atom atom; /**< Atom header. */
  107. uint8_t data[4]; /**< MIDI data (body). */
  108. };
  109. static inline
  110. uint32_t lv2_atom_total_size(const LV2_Atom_MidiEvent& midiEv)
  111. {
  112. return static_cast<uint32_t>(sizeof(LV2_Atom)) + midiEv.atom.size;
  113. }
  114. // ---------------------------------------------------------------------------------------------------------------------
  115. // -Weffc++ compat ext widget
  116. extern "C" {
  117. typedef struct _LV2_External_UI_Widget_Compat {
  118. void (*run )(struct _LV2_External_UI_Widget_Compat*);
  119. void (*show)(struct _LV2_External_UI_Widget_Compat*);
  120. void (*hide)(struct _LV2_External_UI_Widget_Compat*);
  121. _LV2_External_UI_Widget_Compat() noexcept
  122. : run(nullptr), show(nullptr), hide(nullptr) {}
  123. } LV2_External_UI_Widget_Compat;
  124. }
  125. // --------------------------------------------------------------------------------------------------------------------
  126. // Our LV2 World class
  127. class Lv2WorldClass : public Lilv::World
  128. {
  129. public:
  130. // Base Types
  131. Lilv::Node port;
  132. Lilv::Node symbol;
  133. Lilv::Node designation;
  134. Lilv::Node freeWheeling;
  135. Lilv::Node reportsLatency;
  136. // Plugin Types
  137. Lilv::Node class_allpass;
  138. Lilv::Node class_amplifier;
  139. Lilv::Node class_analyzer;
  140. Lilv::Node class_bandpass;
  141. Lilv::Node class_chorus;
  142. Lilv::Node class_comb;
  143. Lilv::Node class_compressor;
  144. Lilv::Node class_constant;
  145. Lilv::Node class_converter;
  146. Lilv::Node class_delay;
  147. Lilv::Node class_distortion;
  148. Lilv::Node class_dynamics;
  149. Lilv::Node class_eq;
  150. Lilv::Node class_envelope;
  151. Lilv::Node class_expander;
  152. Lilv::Node class_filter;
  153. Lilv::Node class_flanger;
  154. Lilv::Node class_function;
  155. Lilv::Node class_gate;
  156. Lilv::Node class_generator;
  157. Lilv::Node class_highpass;
  158. Lilv::Node class_instrument;
  159. Lilv::Node class_limiter;
  160. Lilv::Node class_lowpass;
  161. Lilv::Node class_mixer;
  162. Lilv::Node class_modulator;
  163. Lilv::Node class_multiEQ;
  164. Lilv::Node class_oscillator;
  165. Lilv::Node class_paraEQ;
  166. Lilv::Node class_phaser;
  167. Lilv::Node class_pitch;
  168. Lilv::Node class_reverb;
  169. Lilv::Node class_simulator;
  170. Lilv::Node class_spatial;
  171. Lilv::Node class_spectral;
  172. Lilv::Node class_utility;
  173. Lilv::Node class_waveshaper;
  174. // Port Types
  175. Lilv::Node port_input;
  176. Lilv::Node port_output;
  177. Lilv::Node port_control;
  178. Lilv::Node port_audio;
  179. Lilv::Node port_cv;
  180. Lilv::Node port_atom;
  181. Lilv::Node port_event;
  182. Lilv::Node port_midi;
  183. // Port Properties
  184. Lilv::Node pprop_optional;
  185. Lilv::Node pprop_enumeration;
  186. Lilv::Node pprop_integer;
  187. Lilv::Node pprop_isSideChain;
  188. Lilv::Node pprop_sampleRate;
  189. Lilv::Node pprop_toggled;
  190. Lilv::Node pprop_artifacts;
  191. Lilv::Node pprop_continuousCV;
  192. Lilv::Node pprop_discreteCV;
  193. Lilv::Node pprop_expensive;
  194. Lilv::Node pprop_strictBounds;
  195. Lilv::Node pprop_logarithmic;
  196. Lilv::Node pprop_notAutomatic;
  197. Lilv::Node pprop_notOnGUI;
  198. Lilv::Node pprop_trigger;
  199. Lilv::Node pprop_nonAutomatable;
  200. // Unit Hints
  201. Lilv::Node unit_name;
  202. Lilv::Node unit_render;
  203. Lilv::Node unit_symbol;
  204. Lilv::Node unit_unit;
  205. // UI Types
  206. Lilv::Node ui;
  207. Lilv::Node ui_gtk2;
  208. Lilv::Node ui_gtk3;
  209. Lilv::Node ui_qt4;
  210. Lilv::Node ui_qt5;
  211. Lilv::Node ui_cocoa;
  212. Lilv::Node ui_windows;
  213. Lilv::Node ui_x11;
  214. Lilv::Node ui_external;
  215. Lilv::Node ui_externalOld;
  216. // Misc
  217. Lilv::Node atom_bufferType;
  218. Lilv::Node atom_sequence;
  219. Lilv::Node atom_supports;
  220. Lilv::Node lv2_name;
  221. Lilv::Node lv2_symbol;
  222. Lilv::Node patch_readable;
  223. Lilv::Node patch_writable;
  224. Lilv::Node pg_group;
  225. Lilv::Node pg_sideChainOf;
  226. Lilv::Node preset_preset;
  227. Lilv::Node state_state;
  228. Lilv::Node ui_portIndex;
  229. Lilv::Node ui_portNotif;
  230. Lilv::Node ui_protocol;
  231. Lilv::Node value_default;
  232. Lilv::Node value_minimum;
  233. Lilv::Node value_maximum;
  234. Lilv::Node rz_asLargeAs;
  235. Lilv::Node rz_minSize;
  236. // Port Data Types
  237. Lilv::Node midi_binding;
  238. Lilv::Node midi_ctlrNumber;
  239. Lilv::Node midi_event;
  240. Lilv::Node patch_message;
  241. Lilv::Node time_position;
  242. // MIDI CC
  243. Lilv::Node mm_defaultControl;
  244. Lilv::Node mm_controlType;
  245. Lilv::Node mm_controlNumber;
  246. // Other
  247. Lilv::Node dct_replaces;
  248. Lilv::Node doap_license;
  249. Lilv::Node rdf_type;
  250. Lilv::Node rdfs_comment;
  251. Lilv::Node rdfs_label;
  252. Lilv::Node rdfs_range;
  253. bool needsInit;
  254. const LilvPlugins* allPlugins;
  255. const LilvPlugin** cachedPlugins;
  256. uint pluginCount;
  257. // ----------------------------------------------------------------------------------------------------------------
  258. Lv2WorldClass()
  259. : Lilv::World(),
  260. port (new_uri(LV2_CORE__port)),
  261. symbol (new_uri(LV2_CORE__symbol)),
  262. designation (new_uri(LV2_CORE__designation)),
  263. freeWheeling (new_uri(LV2_CORE__freeWheeling)),
  264. reportsLatency (new_uri(LV2_CORE__reportsLatency)),
  265. class_allpass (new_uri(LV2_CORE__AllpassPlugin)),
  266. class_amplifier (new_uri(LV2_CORE__AmplifierPlugin)),
  267. class_analyzer (new_uri(LV2_CORE__AnalyserPlugin)),
  268. class_bandpass (new_uri(LV2_CORE__BandpassPlugin)),
  269. class_chorus (new_uri(LV2_CORE__ChorusPlugin)),
  270. class_comb (new_uri(LV2_CORE__CombPlugin)),
  271. class_compressor (new_uri(LV2_CORE__CompressorPlugin)),
  272. class_constant (new_uri(LV2_CORE__ConstantPlugin)),
  273. class_converter (new_uri(LV2_CORE__ConverterPlugin)),
  274. class_delay (new_uri(LV2_CORE__DelayPlugin)),
  275. class_distortion (new_uri(LV2_CORE__DistortionPlugin)),
  276. class_dynamics (new_uri(LV2_CORE__DynamicsPlugin)),
  277. class_eq (new_uri(LV2_CORE__EQPlugin)),
  278. class_envelope (new_uri(LV2_CORE__EnvelopePlugin)),
  279. class_expander (new_uri(LV2_CORE__ExpanderPlugin)),
  280. class_filter (new_uri(LV2_CORE__FilterPlugin)),
  281. class_flanger (new_uri(LV2_CORE__FlangerPlugin)),
  282. class_function (new_uri(LV2_CORE__FunctionPlugin)),
  283. class_gate (new_uri(LV2_CORE__GatePlugin)),
  284. class_generator (new_uri(LV2_CORE__GeneratorPlugin)),
  285. class_highpass (new_uri(LV2_CORE__HighpassPlugin)),
  286. class_instrument (new_uri(LV2_CORE__InstrumentPlugin)),
  287. class_limiter (new_uri(LV2_CORE__LimiterPlugin)),
  288. class_lowpass (new_uri(LV2_CORE__LowpassPlugin)),
  289. class_mixer (new_uri(LV2_CORE__MixerPlugin)),
  290. class_modulator (new_uri(LV2_CORE__ModulatorPlugin)),
  291. class_multiEQ (new_uri(LV2_CORE__MultiEQPlugin)),
  292. class_oscillator (new_uri(LV2_CORE__OscillatorPlugin)),
  293. class_paraEQ (new_uri(LV2_CORE__ParaEQPlugin)),
  294. class_phaser (new_uri(LV2_CORE__PhaserPlugin)),
  295. class_pitch (new_uri(LV2_CORE__PitchPlugin)),
  296. class_reverb (new_uri(LV2_CORE__ReverbPlugin)),
  297. class_simulator (new_uri(LV2_CORE__SimulatorPlugin)),
  298. class_spatial (new_uri(LV2_CORE__SpatialPlugin)),
  299. class_spectral (new_uri(LV2_CORE__SpectralPlugin)),
  300. class_utility (new_uri(LV2_CORE__UtilityPlugin)),
  301. class_waveshaper (new_uri(LV2_CORE__WaveshaperPlugin)),
  302. port_input (new_uri(LV2_CORE__InputPort)),
  303. port_output (new_uri(LV2_CORE__OutputPort)),
  304. port_control (new_uri(LV2_CORE__ControlPort)),
  305. port_audio (new_uri(LV2_CORE__AudioPort)),
  306. port_cv (new_uri(LV2_CORE__CVPort)),
  307. port_atom (new_uri(LV2_ATOM__AtomPort)),
  308. port_event (new_uri(LV2_EVENT__EventPort)),
  309. port_midi (new_uri(LV2_MIDI_LL__MidiPort)),
  310. pprop_optional (new_uri(LV2_CORE__connectionOptional)),
  311. pprop_enumeration (new_uri(LV2_CORE__enumeration)),
  312. pprop_integer (new_uri(LV2_CORE__integer)),
  313. pprop_isSideChain (new_uri(LV2_CORE__isSideChain)),
  314. pprop_sampleRate (new_uri(LV2_CORE__sampleRate)),
  315. pprop_toggled (new_uri(LV2_CORE__toggled)),
  316. pprop_artifacts (new_uri(LV2_PORT_PROPS__causesArtifacts)),
  317. pprop_continuousCV (new_uri(LV2_PORT_PROPS__continuousCV)),
  318. pprop_discreteCV (new_uri(LV2_PORT_PROPS__discreteCV)),
  319. pprop_expensive (new_uri(LV2_PORT_PROPS__expensive)),
  320. pprop_strictBounds (new_uri(LV2_PORT_PROPS__hasStrictBounds)),
  321. pprop_logarithmic (new_uri(LV2_PORT_PROPS__logarithmic)),
  322. pprop_notAutomatic (new_uri(LV2_PORT_PROPS__notAutomatic)),
  323. pprop_notOnGUI (new_uri(LV2_PORT_PROPS__notOnGUI)),
  324. pprop_trigger (new_uri(LV2_PORT_PROPS__trigger)),
  325. pprop_nonAutomatable (new_uri(LV2_KXSTUDIO_PROPERTIES__NonAutomatable)),
  326. unit_name (new_uri(LV2_UNITS__name)),
  327. unit_render (new_uri(LV2_UNITS__render)),
  328. unit_symbol (new_uri(LV2_UNITS__symbol)),
  329. unit_unit (new_uri(LV2_UNITS__unit)),
  330. ui (new_uri(LV2_UI__UI)),
  331. ui_gtk2 (new_uri(LV2_UI__GtkUI)),
  332. ui_gtk3 (new_uri(LV2_UI__Gtk3UI)),
  333. ui_qt4 (new_uri(LV2_UI__Qt4UI)),
  334. ui_qt5 (new_uri(LV2_UI__Qt5UI)),
  335. ui_cocoa (new_uri(LV2_UI__CocoaUI)),
  336. ui_windows (new_uri(LV2_UI__WindowsUI)),
  337. ui_x11 (new_uri(LV2_UI__X11UI)),
  338. ui_external (new_uri(LV2_EXTERNAL_UI__Widget)),
  339. ui_externalOld (new_uri(LV2_EXTERNAL_UI_DEPRECATED_URI)),
  340. atom_bufferType (new_uri(LV2_ATOM__bufferType)),
  341. atom_sequence (new_uri(LV2_ATOM__Sequence)),
  342. atom_supports (new_uri(LV2_ATOM__supports)),
  343. lv2_name (new_uri(LV2_CORE__name)),
  344. lv2_symbol (new_uri(LV2_CORE__symbol)),
  345. patch_readable (new_uri(LV2_PATCH__readable)),
  346. patch_writable (new_uri(LV2_PATCH__writable)),
  347. pg_group (new_uri(LV2_PORT_GROUPS__group)),
  348. pg_sideChainOf (new_uri(LV2_PORT_GROUPS__sideChainOf)),
  349. preset_preset (new_uri(LV2_PRESETS__Preset)),
  350. state_state (new_uri(LV2_STATE__state)),
  351. ui_portIndex (new_uri(LV2_UI__portIndex)),
  352. ui_portNotif (new_uri(LV2_UI__portNotification)),
  353. ui_protocol (new_uri(LV2_UI__protocol)),
  354. value_default (new_uri(LV2_CORE__default)),
  355. value_minimum (new_uri(LV2_CORE__minimum)),
  356. value_maximum (new_uri(LV2_CORE__maximum)),
  357. rz_asLargeAs (new_uri(LV2_RESIZE_PORT__asLargeAs)),
  358. rz_minSize (new_uri(LV2_RESIZE_PORT__minimumSize)),
  359. midi_binding (new_uri(LV2_MIDI__binding)),
  360. midi_ctlrNumber (new_uri(LV2_MIDI__controllerNumber)),
  361. midi_event (new_uri(LV2_MIDI__MidiEvent)),
  362. patch_message (new_uri(LV2_PATCH__Message)),
  363. time_position (new_uri(LV2_TIME__Position)),
  364. mm_defaultControl (new_uri(NS_llmm "defaultMidiController")),
  365. mm_controlType (new_uri(NS_llmm "controllerType")),
  366. mm_controlNumber (new_uri(NS_llmm "controllerNumber")),
  367. dct_replaces (new_uri(NS_dct "replaces")),
  368. doap_license (new_uri(NS_doap "license")),
  369. rdf_type (new_uri(NS_rdf "type")),
  370. rdfs_comment (new_uri(NS_rdfs "comment")),
  371. rdfs_label (new_uri(NS_rdfs "label")),
  372. rdfs_range (new_uri(NS_rdfs "range")),
  373. needsInit(true),
  374. allPlugins(nullptr),
  375. cachedPlugins(nullptr),
  376. pluginCount(0) {}
  377. ~Lv2WorldClass() override
  378. {
  379. pluginCount = 0;
  380. allPlugins = nullptr;
  381. if (cachedPlugins != nullptr)
  382. {
  383. delete[] cachedPlugins;
  384. cachedPlugins = nullptr;
  385. }
  386. }
  387. // FIXME - remove this
  388. static Lv2WorldClass& getInstance()
  389. {
  390. static Lv2WorldClass lv2World;
  391. return lv2World;
  392. }
  393. void initIfNeeded(const char* LV2_PATH)
  394. {
  395. if (LV2_PATH == nullptr || LV2_PATH[0] == '\0')
  396. {
  397. static const char* const DEFAULT_LV2_PATH = LILV_DEFAULT_LV2_PATH;
  398. LV2_PATH = DEFAULT_LV2_PATH;
  399. }
  400. if (! needsInit)
  401. return;
  402. needsInit = false;
  403. Lilv::World::load_all(LV2_PATH);
  404. allPlugins = lilv_world_get_all_plugins(this->me);
  405. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr,);
  406. if ((pluginCount = lilv_plugins_size(allPlugins)))
  407. {
  408. cachedPlugins = new const LilvPlugin*[pluginCount+1];
  409. carla_zeroPointers(cachedPlugins, pluginCount+1);
  410. int i = 0;
  411. for (LilvIter* it = lilv_plugins_begin(allPlugins); ! lilv_plugins_is_end(allPlugins, it); it = lilv_plugins_next(allPlugins, it))
  412. cachedPlugins[i++] = lilv_plugins_get(allPlugins, it);
  413. }
  414. }
  415. void load_bundle(const char* const bundle)
  416. {
  417. CARLA_SAFE_ASSERT_RETURN(bundle != nullptr && bundle[0] != '\0',);
  418. CARLA_SAFE_ASSERT_RETURN(needsInit,);
  419. needsInit = false;
  420. Lilv::World::load_bundle(Lilv::Node(new_uri(bundle)));
  421. allPlugins = lilv_world_get_all_plugins(this->me);
  422. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr,);
  423. if ((pluginCount = lilv_plugins_size(allPlugins)))
  424. {
  425. cachedPlugins = new const LilvPlugin*[pluginCount+1];
  426. carla_zeroPointers(cachedPlugins, pluginCount+1);
  427. int i = 0;
  428. for (LilvIter* it = lilv_plugins_begin(allPlugins); ! lilv_plugins_is_end(allPlugins, it); it = lilv_plugins_next(allPlugins, it))
  429. cachedPlugins[i++] = lilv_plugins_get(allPlugins, it);
  430. }
  431. }
  432. uint getPluginCount() const
  433. {
  434. CARLA_SAFE_ASSERT_RETURN(! needsInit, 0);
  435. return pluginCount;
  436. }
  437. const LilvPlugin* getPluginFromIndex(const uint index) const
  438. {
  439. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  440. CARLA_SAFE_ASSERT_RETURN(cachedPlugins != nullptr, nullptr);
  441. CARLA_SAFE_ASSERT_RETURN(index < pluginCount, nullptr);
  442. return cachedPlugins[index];
  443. }
  444. const LilvPlugin* getPluginFromURI(const LV2_URI uri) const
  445. {
  446. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  447. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  448. CARLA_SAFE_ASSERT_RETURN(allPlugins != nullptr, nullptr);
  449. LilvNode* const uriNode(lilv_new_uri(this->me, uri));
  450. CARLA_SAFE_ASSERT_RETURN(uriNode != nullptr, nullptr);
  451. const LilvPlugin* const cPlugin(lilv_plugins_get_by_uri(allPlugins, uriNode));
  452. lilv_node_free(uriNode);
  453. return cPlugin;
  454. }
  455. LilvState* getStateFromURI(const LV2_URI uri, const LV2_URID_Map* const uridMap) const
  456. {
  457. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  458. CARLA_SAFE_ASSERT_RETURN(uridMap != nullptr, nullptr);
  459. CARLA_SAFE_ASSERT_RETURN(! needsInit, nullptr);
  460. LilvNode* const uriNode(lilv_new_uri(this->me, uri));
  461. CARLA_SAFE_ASSERT_RETURN(uriNode != nullptr, nullptr);
  462. CARLA_SAFE_ASSERT(lilv_world_load_resource(this->me, uriNode) >= 0);
  463. LilvState* const cState(lilv_state_new_from_world(this->me, uridMap, uriNode));
  464. lilv_node_free(uriNode);
  465. return cState;
  466. }
  467. CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
  468. CARLA_DECLARE_NON_COPYABLE(Lv2WorldClass)
  469. };
  470. // --------------------------------------------------------------------------------------------------------------------
  471. // Our LV2 Plugin base class
  472. #if defined(__clang__)
  473. # pragma clang diagnostic push
  474. # pragma clang diagnostic ignored "-Weffc++"
  475. # pragma clang diagnostic ignored "-Wnon-virtual-dtor"
  476. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  477. # pragma GCC diagnostic push
  478. # pragma GCC diagnostic ignored "-Weffc++"
  479. # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
  480. #endif
  481. template<class TimeInfoStruct>
  482. class Lv2PluginBaseClass : public LV2_External_UI_Widget_Compat
  483. {
  484. #if defined(__clang__)
  485. # pragma clang diagnostic pop
  486. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  487. # pragma GCC diagnostic pop
  488. #endif
  489. public:
  490. Lv2PluginBaseClass(const double sampleRate, const LV2_Feature* const* const features)
  491. : fIsActive(false),
  492. fIsOffline(false),
  493. fUsingNominal(false),
  494. fBufferSize(0),
  495. fSampleRate(sampleRate),
  496. fFreePath(nullptr),
  497. fUridMap(nullptr),
  498. fUridUnmap(nullptr),
  499. fWorker(nullptr),
  500. fInlineDisplay(nullptr),
  501. fTimeInfo(),
  502. fLastPositionData(),
  503. fPorts(),
  504. fURIs(),
  505. fUI()
  506. {
  507. run = extui_run;
  508. show = extui_show;
  509. hide = extui_hide;
  510. if (fSampleRate < 1.0)
  511. {
  512. carla_stderr("Host doesn't provide a valid sample rate");
  513. return;
  514. }
  515. const LV2_State_Free_Path* freePath = nullptr;
  516. const LV2_Options_Option* options = nullptr;
  517. const LV2_URID_Map* uridMap = nullptr;
  518. const LV2_URID_Unmap* uridUnmap = nullptr;
  519. const LV2_Worker_Schedule* worker = nullptr;
  520. const LV2_Inline_Display* idisp = nullptr;
  521. for (int i=0; features[i] != nullptr; ++i)
  522. {
  523. /**/ if (std::strcmp(features[i]->URI, LV2_STATE__freePath) == 0)
  524. freePath = (const LV2_State_Free_Path*)features[i]->data;
  525. else if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
  526. options = (const LV2_Options_Option*)features[i]->data;
  527. else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
  528. uridMap = (const LV2_URID_Map*)features[i]->data;
  529. else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
  530. uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
  531. else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0)
  532. worker = (const LV2_Worker_Schedule*)features[i]->data;
  533. else if (std::strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw) == 0)
  534. idisp = (const LV2_Inline_Display*)features[i]->data;
  535. }
  536. if (options == nullptr || uridMap == nullptr)
  537. {
  538. carla_stderr("Host doesn't provide option and urid-map features");
  539. return;
  540. }
  541. for (int i=0; options[i].key != 0; ++i)
  542. {
  543. if (uridUnmap != nullptr) {
  544. carla_debug("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
  545. }
  546. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
  547. {
  548. if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
  549. {
  550. const int32_t value(*(const int32_t*)options[i].value);
  551. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  552. fBufferSize = static_cast<uint32_t>(value);
  553. fUsingNominal = true;
  554. }
  555. else
  556. {
  557. carla_stderr("Host provides nominalBlockLength but has wrong value type");
  558. }
  559. break;
  560. }
  561. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
  562. {
  563. if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
  564. {
  565. const int32_t value(*(const int32_t*)options[i].value);
  566. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  567. fBufferSize = static_cast<uint32_t>(value);
  568. }
  569. else
  570. {
  571. carla_stderr("Host provides maxBlockLength but has wrong value type");
  572. }
  573. // no break, continue in case host supports nominalBlockLength
  574. }
  575. }
  576. if (fBufferSize == 0)
  577. {
  578. carla_stderr("Host doesn't provide buffer-size feature");
  579. //return;
  580. // as testing, continue for now
  581. fBufferSize = 1024;
  582. }
  583. fUridMap = uridMap;
  584. fURIs.map(uridMap);
  585. fFreePath = freePath;
  586. fUridUnmap = uridUnmap;
  587. fWorker = worker;
  588. fInlineDisplay = idisp;
  589. clearTimeData();
  590. }
  591. virtual ~Lv2PluginBaseClass() {}
  592. bool loadedInProperHost() const noexcept
  593. {
  594. return fUridMap != nullptr && fBufferSize != 0;
  595. }
  596. // ----------------------------------------------------------------------------------------------------------------
  597. void lv2_connect_port(const uint32_t port, void* const dataLocation) noexcept
  598. {
  599. fPorts.connectPort(port, dataLocation);
  600. }
  601. bool lv2_pre_run(const uint32_t frames)
  602. {
  603. CARLA_SAFE_ASSERT_RETURN(fIsActive, false);
  604. fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);
  605. // cache midi events and time information first
  606. if (fPorts.usesTime)
  607. {
  608. LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[0], event)
  609. {
  610. if (event == nullptr)
  611. continue;
  612. if (event->body.type != fURIs.atomBlank && event->body.type != fURIs.atomObject)
  613. continue;
  614. const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body);
  615. if (obj->body.otype != fURIs.timePos)
  616. continue;
  617. LV2_Atom* bar = nullptr;
  618. LV2_Atom* barBeat = nullptr;
  619. LV2_Atom* beatUnit = nullptr;
  620. LV2_Atom* beatsPerBar = nullptr;
  621. LV2_Atom* beatsPerMinute = nullptr;
  622. LV2_Atom* frame = nullptr;
  623. LV2_Atom* speed = nullptr;
  624. LV2_Atom* ticksPerBeat = nullptr;
  625. lv2_atom_object_get(obj,
  626. fURIs.timeBar, &bar,
  627. fURIs.timeBarBeat, &barBeat,
  628. fURIs.timeBeatUnit, &beatUnit,
  629. fURIs.timeBeatsPerBar, &beatsPerBar,
  630. fURIs.timeBeatsPerMinute, &beatsPerMinute,
  631. fURIs.timeFrame, &frame,
  632. fURIs.timeSpeed, &speed,
  633. fURIs.timeTicksPerBeat, &ticksPerBeat,
  634. 0);
  635. // need to handle this first as other values depend on it
  636. if (ticksPerBeat != nullptr)
  637. {
  638. double ticksPerBeatValue = -1.0;
  639. /**/ if (ticksPerBeat->type == fURIs.atomDouble)
  640. ticksPerBeatValue = ((LV2_Atom_Double*)ticksPerBeat)->body;
  641. else if (ticksPerBeat->type == fURIs.atomFloat)
  642. ticksPerBeatValue = ((LV2_Atom_Float*)ticksPerBeat)->body;
  643. else if (ticksPerBeat->type == fURIs.atomInt)
  644. ticksPerBeatValue = static_cast<double>(((LV2_Atom_Int*)ticksPerBeat)->body);
  645. else if (ticksPerBeat->type == fURIs.atomLong)
  646. ticksPerBeatValue = static_cast<double>(((LV2_Atom_Long*)ticksPerBeat)->body);
  647. else
  648. carla_stderr("Unknown lv2 ticksPerBeat value type");
  649. if (ticksPerBeatValue > 0.0)
  650. fTimeInfo.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat = ticksPerBeatValue;
  651. else
  652. carla_stderr("Invalid lv2 ticksPerBeat value");
  653. }
  654. // same
  655. if (speed != nullptr)
  656. {
  657. /**/ if (speed->type == fURIs.atomDouble)
  658. fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
  659. else if (speed->type == fURIs.atomFloat)
  660. fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
  661. else if (speed->type == fURIs.atomInt)
  662. fLastPositionData.speed = static_cast<double>(((LV2_Atom_Int*)speed)->body);
  663. else if (speed->type == fURIs.atomLong)
  664. fLastPositionData.speed = static_cast<double>(((LV2_Atom_Long*)speed)->body);
  665. else
  666. carla_stderr("Unknown lv2 speed value type");
  667. fTimeInfo.playing = carla_isNotZero(fLastPositionData.speed);
  668. if (fTimeInfo.playing && fLastPositionData.beatsPerMinute > 0.0)
  669. {
  670. fTimeInfo.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute*
  671. std::abs(fLastPositionData.speed);
  672. }
  673. }
  674. if (bar != nullptr)
  675. {
  676. int64_t barValue = -1;
  677. /**/ if (bar->type == fURIs.atomDouble)
  678. barValue = static_cast<int64_t>(((LV2_Atom_Double*)bar)->body);
  679. else if (bar->type == fURIs.atomFloat)
  680. barValue = static_cast<int64_t>(((LV2_Atom_Float*)bar)->body);
  681. else if (bar->type == fURIs.atomInt)
  682. barValue = ((LV2_Atom_Int*)bar)->body;
  683. else if (bar->type == fURIs.atomLong)
  684. barValue = ((LV2_Atom_Long*)bar)->body;
  685. else
  686. carla_stderr("Unknown lv2 bar value type");
  687. if (barValue >= 0 && barValue < INT32_MAX)
  688. {
  689. fLastPositionData.bar = static_cast<int32_t>(barValue);
  690. fLastPositionData.bar_f = static_cast<float>(barValue);
  691. fTimeInfo.bbt.bar = fLastPositionData.bar + 1;
  692. }
  693. else
  694. {
  695. carla_stderr("Invalid lv2 bar value");
  696. }
  697. }
  698. if (barBeat != nullptr)
  699. {
  700. double barBeatValue = -1.0;
  701. /**/ if (barBeat->type == fURIs.atomDouble)
  702. barBeatValue = ((LV2_Atom_Double*)barBeat)->body;
  703. else if (barBeat->type == fURIs.atomFloat)
  704. barBeatValue = ((LV2_Atom_Float*)barBeat)->body;
  705. else if (barBeat->type == fURIs.atomInt)
  706. barBeatValue = static_cast<float>(((LV2_Atom_Int*)barBeat)->body);
  707. else if (barBeat->type == fURIs.atomLong)
  708. barBeatValue = static_cast<float>(((LV2_Atom_Long*)barBeat)->body);
  709. else
  710. carla_stderr("Unknown lv2 barBeat value type");
  711. if (barBeatValue >= 0.0)
  712. {
  713. fLastPositionData.barBeat = static_cast<float>(barBeatValue);
  714. const double rest = std::fmod(barBeatValue, 1.0);
  715. fTimeInfo.bbt.beat = static_cast<int32_t>(barBeatValue-rest+1.0);
  716. fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5);
  717. }
  718. else
  719. {
  720. carla_stderr("Invalid lv2 barBeat value");
  721. }
  722. }
  723. if (beatUnit != nullptr)
  724. {
  725. int64_t beatUnitValue = -1;
  726. /**/ if (beatUnit->type == fURIs.atomDouble)
  727. beatUnitValue = static_cast<int64_t>(((LV2_Atom_Double*)beatUnit)->body);
  728. else if (beatUnit->type == fURIs.atomFloat)
  729. beatUnitValue = static_cast<int64_t>(((LV2_Atom_Float*)beatUnit)->body);
  730. else if (beatUnit->type == fURIs.atomInt)
  731. beatUnitValue = ((LV2_Atom_Int*)beatUnit)->body;
  732. else if (beatUnit->type == fURIs.atomLong)
  733. beatUnitValue = ((LV2_Atom_Long*)beatUnit)->body;
  734. else
  735. carla_stderr("Unknown lv2 beatUnit value type");
  736. if (beatUnitValue > 0 && beatUnitValue < UINT32_MAX)
  737. {
  738. fLastPositionData.beatUnit = static_cast<uint32_t>(beatUnitValue);
  739. fTimeInfo.bbt.beatType = static_cast<float>(beatUnitValue);
  740. }
  741. else
  742. {
  743. carla_stderr("Invalid lv2 beatUnit value");
  744. }
  745. }
  746. if (beatsPerBar != nullptr)
  747. {
  748. float beatsPerBarValue = -1.0f;
  749. /**/ if (beatsPerBar->type == fURIs.atomDouble)
  750. beatsPerBarValue = static_cast<float>(((LV2_Atom_Double*)beatsPerBar)->body);
  751. else if (beatsPerBar->type == fURIs.atomFloat)
  752. beatsPerBarValue = ((LV2_Atom_Float*)beatsPerBar)->body;
  753. else if (beatsPerBar->type == fURIs.atomInt)
  754. beatsPerBarValue = static_cast<float>(((LV2_Atom_Int*)beatsPerBar)->body);
  755. else if (beatsPerBar->type == fURIs.atomLong)
  756. beatsPerBarValue = static_cast<float>(((LV2_Atom_Long*)beatsPerBar)->body);
  757. else
  758. carla_stderr("Unknown lv2 beatsPerBar value type");
  759. if (beatsPerBarValue > 0.0f)
  760. fTimeInfo.bbt.beatsPerBar = fLastPositionData.beatsPerBar = beatsPerBarValue;
  761. else
  762. carla_stderr("Invalid lv2 beatsPerBar value");
  763. }
  764. if (beatsPerMinute != nullptr)
  765. {
  766. double beatsPerMinuteValue = -1.0;
  767. /**/ if (beatsPerMinute->type == fURIs.atomDouble)
  768. beatsPerMinuteValue = ((LV2_Atom_Double*)beatsPerMinute)->body;
  769. else if (beatsPerMinute->type == fURIs.atomFloat)
  770. beatsPerMinuteValue = ((LV2_Atom_Float*)beatsPerMinute)->body;
  771. else if (beatsPerMinute->type == fURIs.atomInt)
  772. beatsPerMinuteValue = static_cast<double>(((LV2_Atom_Int*)beatsPerMinute)->body);
  773. else if (beatsPerMinute->type == fURIs.atomLong)
  774. beatsPerMinuteValue = static_cast<double>(((LV2_Atom_Long*)beatsPerMinute)->body);
  775. else
  776. carla_stderr("Unknown lv2 beatsPerMinute value type");
  777. if (beatsPerMinuteValue >= 12.0 && beatsPerMinuteValue <= 999.0)
  778. {
  779. fTimeInfo.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute = beatsPerMinuteValue;
  780. if (carla_isNotZero(fLastPositionData.speed))
  781. fTimeInfo.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed);
  782. }
  783. else
  784. {
  785. carla_stderr("Invalid lv2 beatsPerMinute value");
  786. }
  787. }
  788. if (frame != nullptr)
  789. {
  790. int64_t frameValue = -1;
  791. /**/ if (frame->type == fURIs.atomDouble)
  792. frameValue = static_cast<int64_t>(((LV2_Atom_Double*)frame)->body);
  793. else if (frame->type == fURIs.atomFloat)
  794. frameValue = static_cast<int64_t>(((LV2_Atom_Float*)frame)->body);
  795. else if (frame->type == fURIs.atomInt)
  796. frameValue = ((LV2_Atom_Int*)frame)->body;
  797. else if (frame->type == fURIs.atomLong)
  798. frameValue = ((LV2_Atom_Long*)frame)->body;
  799. else
  800. carla_stderr("Unknown lv2 frame value type");
  801. if (frameValue >= 0)
  802. fTimeInfo.frame = fLastPositionData.frame = static_cast<uint64_t>(frameValue);
  803. else
  804. carla_stderr("Invalid lv2 frame value");
  805. }
  806. fTimeInfo.bbt.barStartTick = static_cast<double>(fTimeInfo.bbt.ticksPerBeat) *
  807. static_cast<double>(fTimeInfo.bbt.beatsPerBar) *
  808. (fTimeInfo.bbt.bar-1);
  809. fTimeInfo.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 &&
  810. fLastPositionData.beatUnit > 0 &&
  811. fLastPositionData.beatsPerBar > 0.0f);
  812. }
  813. }
  814. // Check for updated parameters
  815. float curValue;
  816. for (uint32_t i=0; i < fPorts.numParams; ++i)
  817. {
  818. if (fPorts.paramsOut[i])
  819. continue;
  820. CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr)
  821. curValue = *fPorts.paramsPtr[i];
  822. if (carla_isEqual(fPorts.paramsLast[i], curValue))
  823. continue;
  824. fPorts.paramsLast[i] = curValue;
  825. handleParameterValueChanged(i, curValue);
  826. }
  827. // init event out data
  828. if (fPorts.numMidiOuts > 0 || fPorts.hasUI)
  829. {
  830. const uint32_t count = fPorts.numMidiOuts > 0 ? fPorts.numMidiOuts : 1;
  831. for (uint32_t i=0; i < count; ++i)
  832. {
  833. LV2_Atom_Sequence* const seq(fPorts.eventsOut[i]);
  834. CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr);
  835. fPorts.eventsOutData[i].capacity = seq->atom.size;
  836. fPorts.eventsOutData[i].offset = 0;
  837. seq->atom.size = sizeof(LV2_Atom_Sequence_Body);
  838. seq->atom.type = fURIs.atomSequence;
  839. seq->body.unit = 0;
  840. seq->body.pad = 0;
  841. }
  842. }
  843. if (frames == 0)
  844. return false;
  845. return true;
  846. }
  847. void lv2_post_run(const uint32_t frames)
  848. {
  849. // update timePos for next callback
  850. if (carla_isZero(fLastPositionData.speed))
  851. return;
  852. if (fLastPositionData.speed > 0.0)
  853. {
  854. // playing forwards
  855. fLastPositionData.frame += frames;
  856. }
  857. else
  858. {
  859. // playing backwards
  860. if (frames >= fLastPositionData.frame)
  861. fLastPositionData.frame = 0;
  862. else
  863. fLastPositionData.frame -= frames;
  864. }
  865. fTimeInfo.frame = fLastPositionData.frame;
  866. if (fTimeInfo.bbt.valid)
  867. {
  868. const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
  869. const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute;
  870. const double addedBarBeats = double(frames) / framesPerBeat;
  871. if (fLastPositionData.barBeat >= 0.0f)
  872. {
  873. fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+static_cast<float>(addedBarBeats),
  874. fLastPositionData.beatsPerBar);
  875. const double rest = std::fmod(fLastPositionData.barBeat, 1.0f);
  876. fTimeInfo.bbt.beat = static_cast<int32_t>(static_cast<double>(fLastPositionData.barBeat)-rest+1.0);
  877. fTimeInfo.bbt.tick = rest * fTimeInfo.bbt.ticksPerBeat;
  878. if (fLastPositionData.bar_f >= 0.0f)
  879. {
  880. fLastPositionData.bar_f += std::floor((fLastPositionData.barBeat+static_cast<float>(addedBarBeats))/
  881. fLastPositionData.beatsPerBar);
  882. if (fLastPositionData.bar_f <= 0.0f)
  883. {
  884. fLastPositionData.bar = 0;
  885. fLastPositionData.bar_f = 0.0f;
  886. }
  887. else
  888. {
  889. fLastPositionData.bar = static_cast<int32_t>(fLastPositionData.bar_f+0.5f);
  890. }
  891. fTimeInfo.bbt.bar = fLastPositionData.bar + 1;
  892. fTimeInfo.bbt.barStartTick = static_cast<double>(fTimeInfo.bbt.ticksPerBeat) *
  893. static_cast<double>(fTimeInfo.bbt.beatsPerBar) *
  894. (fTimeInfo.bbt.bar-1);
  895. }
  896. }
  897. }
  898. }
  899. // ----------------------------------------------------------------------------------------------------------------
  900. uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) const
  901. {
  902. // currently unused
  903. return LV2_OPTIONS_SUCCESS;
  904. }
  905. uint32_t lv2_set_options(const LV2_Options_Option* const options)
  906. {
  907. for (int i=0; options[i].key != 0; ++i)
  908. {
  909. if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
  910. {
  911. if (options[i].type == fURIs.atomInt)
  912. {
  913. const int32_t value(*(const int32_t*)options[i].value);
  914. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  915. const uint32_t newBufferSize = static_cast<uint32_t>(value);
  916. if (fBufferSize != newBufferSize)
  917. {
  918. fBufferSize = newBufferSize;
  919. handleBufferSizeChanged(newBufferSize);
  920. }
  921. }
  922. else
  923. {
  924. carla_stderr("Host changed nominalBlockLength but with wrong value type");
  925. }
  926. }
  927. else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal)
  928. {
  929. if (options[i].type == fURIs.atomInt)
  930. {
  931. const int32_t value(*(const int32_t*)options[i].value);
  932. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  933. const uint32_t newBufferSize = static_cast<uint32_t>(value);
  934. if (fBufferSize != newBufferSize)
  935. {
  936. fBufferSize = newBufferSize;
  937. handleBufferSizeChanged(newBufferSize);
  938. }
  939. }
  940. else
  941. {
  942. carla_stderr("Host changed maxBlockLength but with wrong value type");
  943. }
  944. }
  945. else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate))
  946. {
  947. if (options[i].type == fURIs.atomFloat)
  948. {
  949. const double value(*(const float*)options[i].value);
  950. CARLA_SAFE_ASSERT_CONTINUE(value > 0.0);
  951. if (carla_isNotEqual(fSampleRate, value))
  952. {
  953. fSampleRate = value;
  954. handleSampleRateChanged(value);
  955. }
  956. }
  957. else
  958. {
  959. carla_stderr("Host changed sampleRate but with wrong value type");
  960. }
  961. }
  962. }
  963. return LV2_OPTIONS_SUCCESS;
  964. }
  965. // ----------------------------------------------------------------------------------------------------------------
  966. int lv2ui_idle() const
  967. {
  968. if (! fUI.isVisible)
  969. return 1;
  970. handleUiRun();
  971. return 0;
  972. }
  973. int lv2ui_show()
  974. {
  975. handleUiShow();
  976. return 0;
  977. }
  978. int lv2ui_hide()
  979. {
  980. handleUiHide();
  981. return 0;
  982. }
  983. void lv2ui_cleanup()
  984. {
  985. if (fUI.isVisible)
  986. handleUiHide();
  987. fUI.host = nullptr;
  988. fUI.touch = nullptr;
  989. fUI.writeFunction = nullptr;
  990. fUI.controller = nullptr;
  991. }
  992. // ----------------------------------------------------------------------------------------------------------------
  993. protected:
  994. virtual void handleUiRun() const = 0;
  995. virtual void handleUiShow() = 0;
  996. virtual void handleUiHide() = 0;
  997. virtual void handleParameterValueChanged(const uint32_t index, const float value) = 0;
  998. virtual void handleBufferSizeChanged(const uint32_t bufferSize) = 0;
  999. virtual void handleSampleRateChanged(const double sampleRate) = 0;
  1000. void resetTimeInfo() noexcept
  1001. {
  1002. clearTimeData();
  1003. // hosts may not send all values, resulting on some invalid data
  1004. fTimeInfo.bbt.bar = 1;
  1005. fTimeInfo.bbt.beat = 1;
  1006. fTimeInfo.bbt.beatsPerBar = 4;
  1007. fTimeInfo.bbt.beatType = 4;
  1008. fTimeInfo.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat = 960.0;
  1009. fTimeInfo.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute = 120.0;
  1010. }
  1011. // LV2 host data
  1012. bool fIsActive : 1;
  1013. bool fIsOffline : 1;
  1014. bool fUsingNominal : 1;
  1015. uint32_t fBufferSize;
  1016. double fSampleRate;
  1017. // LV2 host features
  1018. const LV2_State_Free_Path* fFreePath;
  1019. const LV2_URID_Map* fUridMap;
  1020. const LV2_URID_Unmap* fUridUnmap;
  1021. const LV2_Worker_Schedule* fWorker;
  1022. const LV2_Inline_Display* fInlineDisplay;
  1023. // Time info stuff
  1024. TimeInfoStruct fTimeInfo;
  1025. struct Lv2PositionData {
  1026. int32_t bar;
  1027. float bar_f;
  1028. float barBeat;
  1029. uint32_t beatUnit;
  1030. float beatsPerBar;
  1031. double beatsPerMinute;
  1032. uint64_t frame;
  1033. double speed;
  1034. double ticksPerBeat;
  1035. Lv2PositionData()
  1036. : bar(-1),
  1037. bar_f(-1.0f),
  1038. barBeat(-1.0f),
  1039. beatUnit(0),
  1040. beatsPerBar(0.0f),
  1041. beatsPerMinute(-1.0),
  1042. frame(0),
  1043. speed(0.0),
  1044. ticksPerBeat(-1.0) {}
  1045. void clear()
  1046. {
  1047. bar = -1;
  1048. bar_f = -1.0f;
  1049. barBeat = -1.0f;
  1050. beatUnit = 0;
  1051. beatsPerBar = 0.0f;
  1052. beatsPerMinute = -1.0;
  1053. frame = 0;
  1054. speed = 0.0;
  1055. ticksPerBeat = -1.0;
  1056. }
  1057. } fLastPositionData;
  1058. // Port stuff
  1059. struct Ports {
  1060. // need to save current state
  1061. struct EventsOutData {
  1062. uint32_t capacity;
  1063. uint32_t offset;
  1064. EventsOutData()
  1065. : capacity(0),
  1066. offset(0) {}
  1067. };
  1068. // store port info
  1069. uint32_t indexOffset;
  1070. uint32_t numAudioIns;
  1071. uint32_t numAudioOuts;
  1072. uint32_t numCVIns;
  1073. uint32_t numCVOuts;
  1074. uint32_t numMidiIns;
  1075. uint32_t numMidiOuts;
  1076. uint32_t numParams;
  1077. bool hasUI;
  1078. bool usesTime;
  1079. // port buffers
  1080. const LV2_Atom_Sequence** eventsIn;
  1081. /* */ LV2_Atom_Sequence** eventsOut;
  1082. /* */ EventsOutData* eventsOutData;
  1083. /* */ float** audioCVIns;
  1084. /* */ float** audioCVOuts;
  1085. /* */ float* freewheel;
  1086. // cached parameter values
  1087. float* paramsLast;
  1088. float** paramsPtr;
  1089. bool* paramsOut;
  1090. Ports()
  1091. : indexOffset(0),
  1092. numAudioIns(0),
  1093. numAudioOuts(0),
  1094. numCVIns(0),
  1095. numCVOuts(0),
  1096. numMidiIns(0),
  1097. numMidiOuts(0),
  1098. numParams(0),
  1099. hasUI(false),
  1100. usesTime(false),
  1101. eventsIn(nullptr),
  1102. eventsOut(nullptr),
  1103. eventsOutData(nullptr),
  1104. audioCVIns(nullptr),
  1105. audioCVOuts(nullptr),
  1106. freewheel(nullptr),
  1107. paramsLast(nullptr),
  1108. paramsPtr(nullptr),
  1109. paramsOut(nullptr) {}
  1110. ~Ports()
  1111. {
  1112. if (eventsIn != nullptr)
  1113. {
  1114. delete[] eventsIn;
  1115. eventsIn = nullptr;
  1116. }
  1117. if (eventsOut != nullptr)
  1118. {
  1119. delete[] eventsOut;
  1120. eventsOut = nullptr;
  1121. }
  1122. if (eventsOutData != nullptr)
  1123. {
  1124. delete[] eventsOutData;
  1125. eventsOutData = nullptr;
  1126. }
  1127. if (audioCVIns != nullptr)
  1128. {
  1129. delete[] audioCVIns;
  1130. audioCVIns = nullptr;
  1131. }
  1132. if (audioCVOuts != nullptr)
  1133. {
  1134. delete[] audioCVOuts;
  1135. audioCVOuts = nullptr;
  1136. }
  1137. if (paramsLast != nullptr)
  1138. {
  1139. delete[] paramsLast;
  1140. paramsLast = nullptr;
  1141. }
  1142. if (paramsPtr != nullptr)
  1143. {
  1144. delete[] paramsPtr;
  1145. paramsPtr = nullptr;
  1146. }
  1147. if (paramsOut != nullptr)
  1148. {
  1149. delete[] paramsOut;
  1150. paramsOut = nullptr;
  1151. }
  1152. }
  1153. // NOTE: assumes num* has been filled by parent class
  1154. void init()
  1155. {
  1156. if (numMidiIns > 0)
  1157. {
  1158. eventsIn = new const LV2_Atom_Sequence*[numMidiIns];
  1159. for (uint32_t i=0; i < numMidiIns; ++i)
  1160. eventsIn[i] = nullptr;
  1161. }
  1162. else if (usesTime || hasUI)
  1163. {
  1164. eventsIn = new const LV2_Atom_Sequence*[1];
  1165. eventsIn[0] = nullptr;
  1166. }
  1167. if (numMidiOuts > 0)
  1168. {
  1169. eventsOut = new LV2_Atom_Sequence*[numMidiOuts];
  1170. eventsOutData = new EventsOutData[numMidiOuts];
  1171. for (uint32_t i=0; i < numMidiOuts; ++i)
  1172. eventsOut[i] = nullptr;
  1173. }
  1174. else if (hasUI)
  1175. {
  1176. eventsOut = new LV2_Atom_Sequence*[1];
  1177. eventsOut[0] = nullptr;
  1178. eventsOutData = new EventsOutData[1];
  1179. }
  1180. if (const uint32_t numAudioCVIns = numAudioIns+numCVIns)
  1181. {
  1182. audioCVIns = new float*[numAudioCVIns];
  1183. carla_zeroPointers(audioCVIns, numAudioCVIns);
  1184. }
  1185. if (const uint32_t numAudioCVOuts = numAudioOuts+numCVOuts)
  1186. {
  1187. audioCVOuts = new float*[numAudioCVOuts];
  1188. carla_zeroPointers(audioCVOuts, numAudioCVOuts);
  1189. }
  1190. if (numParams > 0)
  1191. {
  1192. paramsLast = new float[numParams];
  1193. paramsPtr = new float*[numParams];
  1194. paramsOut = new bool[numParams];
  1195. carla_zeroFloats(paramsLast, numParams);
  1196. carla_zeroPointers(paramsPtr, numParams);
  1197. carla_zeroStructs(paramsOut, numParams);
  1198. // NOTE: need to be filled in by the parent class
  1199. }
  1200. indexOffset = numAudioIns + numAudioOuts + numCVIns + numCVOuts;
  1201. // 1 event port for time or ui if no midi input is used
  1202. indexOffset += numMidiIns > 0 ? numMidiIns : ((usesTime || hasUI) ? 1 : 0);
  1203. // 1 event port for ui if no midi output is used
  1204. indexOffset += numMidiOuts > 0 ? numMidiOuts : (hasUI ? 1 : 0);
  1205. // 1 extra for freewheel port
  1206. indexOffset += 1;
  1207. }
  1208. void connectPort(const uint32_t port, void* const dataLocation)
  1209. {
  1210. uint32_t index = 0;
  1211. if (numMidiIns > 0 || usesTime || hasUI)
  1212. {
  1213. if (port == index++)
  1214. {
  1215. eventsIn[0] = (LV2_Atom_Sequence*)dataLocation;
  1216. return;
  1217. }
  1218. }
  1219. for (uint32_t i=1; i < numMidiIns; ++i)
  1220. {
  1221. if (port == index++)
  1222. {
  1223. eventsIn[i] = (LV2_Atom_Sequence*)dataLocation;
  1224. return;
  1225. }
  1226. }
  1227. if (numMidiOuts > 0 || hasUI)
  1228. {
  1229. if (port == index++)
  1230. {
  1231. eventsOut[0] = (LV2_Atom_Sequence*)dataLocation;
  1232. return;
  1233. }
  1234. }
  1235. for (uint32_t i=1; i < numMidiOuts; ++i)
  1236. {
  1237. if (port == index++)
  1238. {
  1239. eventsOut[i] = (LV2_Atom_Sequence*)dataLocation;
  1240. return;
  1241. }
  1242. }
  1243. if (port == index++)
  1244. {
  1245. freewheel = (float*)dataLocation;
  1246. return;
  1247. }
  1248. for (uint32_t i=0; i < numAudioIns; ++i)
  1249. {
  1250. if (port == index++)
  1251. {
  1252. audioCVIns[i] = (float*)dataLocation;
  1253. return;
  1254. }
  1255. }
  1256. for (uint32_t i=0; i < numAudioOuts; ++i)
  1257. {
  1258. if (port == index++)
  1259. {
  1260. audioCVOuts[i] = (float*)dataLocation;
  1261. return;
  1262. }
  1263. }
  1264. for (uint32_t i=0; i < numCVIns; ++i)
  1265. {
  1266. if (port == index++)
  1267. {
  1268. audioCVIns[numAudioIns+i] = (float*)dataLocation;
  1269. return;
  1270. }
  1271. }
  1272. for (uint32_t i=0; i < numCVOuts; ++i)
  1273. {
  1274. if (port == index++)
  1275. {
  1276. audioCVOuts[numAudioOuts+i] = (float*)dataLocation;
  1277. return;
  1278. }
  1279. }
  1280. for (uint32_t i=0; i < numParams; ++i)
  1281. {
  1282. if (port == index++)
  1283. {
  1284. paramsPtr[i] = (float*)dataLocation;
  1285. return;
  1286. }
  1287. }
  1288. }
  1289. CARLA_DECLARE_NON_COPYABLE(Ports);
  1290. } fPorts;
  1291. // Rest of host<->plugin support
  1292. struct URIDs {
  1293. LV2_URID atomBlank;
  1294. LV2_URID atomBool;
  1295. LV2_URID atomObject;
  1296. LV2_URID atomDouble;
  1297. LV2_URID atomFloat;
  1298. LV2_URID atomInt;
  1299. LV2_URID atomLong;
  1300. LV2_URID atomPath;
  1301. LV2_URID atomSequence;
  1302. LV2_URID atomString;
  1303. LV2_URID atomURID;
  1304. LV2_URID carlaFile;
  1305. LV2_URID carlaFileAudio;
  1306. LV2_URID carlaFileMIDI;
  1307. LV2_URID carlaPreview;
  1308. LV2_URID midiEvent;
  1309. LV2_URID patchProperty;
  1310. LV2_URID patchGet;
  1311. LV2_URID patchSet;
  1312. LV2_URID patchValue;
  1313. LV2_URID timePos;
  1314. LV2_URID timeBar;
  1315. LV2_URID timeBarBeat;
  1316. LV2_URID timeBeatsPerBar;
  1317. LV2_URID timeBeatsPerMinute;
  1318. LV2_URID timeBeatUnit;
  1319. LV2_URID timeFrame;
  1320. LV2_URID timeSpeed;
  1321. LV2_URID timeTicksPerBeat;
  1322. LV2_URID carlaRequestIdle;
  1323. LV2_URID carlaUiEvents;
  1324. URIDs()
  1325. : atomBlank(0),
  1326. atomBool(0),
  1327. atomObject(0),
  1328. atomDouble(0),
  1329. atomFloat(0),
  1330. atomInt(0),
  1331. atomLong(0),
  1332. atomPath(0),
  1333. atomSequence(0),
  1334. atomString(0),
  1335. atomURID(0),
  1336. carlaFile(0),
  1337. carlaFileAudio(0),
  1338. carlaFileMIDI(0),
  1339. carlaPreview(0),
  1340. midiEvent(0),
  1341. patchProperty(0),
  1342. patchGet(0),
  1343. patchSet(0),
  1344. patchValue(0),
  1345. timePos(0),
  1346. timeBar(0),
  1347. timeBarBeat(0),
  1348. timeBeatsPerBar(0),
  1349. timeBeatsPerMinute(0),
  1350. timeBeatUnit(0),
  1351. timeFrame(0),
  1352. timeSpeed(0),
  1353. timeTicksPerBeat(0),
  1354. carlaRequestIdle(0),
  1355. carlaUiEvents(0) {}
  1356. void map(const LV2_URID_Map* const uridMap)
  1357. {
  1358. atomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank);
  1359. atomBool = uridMap->map(uridMap->handle, LV2_ATOM__Bool);
  1360. atomObject = uridMap->map(uridMap->handle, LV2_ATOM__Object);
  1361. atomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double);
  1362. atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
  1363. atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
  1364. atomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
  1365. atomPath = uridMap->map(uridMap->handle, LV2_ATOM__Path);
  1366. atomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
  1367. atomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
  1368. atomURID = uridMap->map(uridMap->handle, LV2_ATOM__URID);
  1369. carlaFile = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file");
  1370. carlaFileAudio = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file/audio");
  1371. carlaFileMIDI = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file/midi");
  1372. carlaPreview = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/preview");
  1373. midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
  1374. patchProperty = uridMap->map(uridMap->handle, LV2_PATCH__property);
  1375. patchGet = uridMap->map(uridMap->handle, LV2_PATCH__Get);
  1376. patchSet = uridMap->map(uridMap->handle, LV2_PATCH__Set);
  1377. patchValue = uridMap->map(uridMap->handle, LV2_PATCH__value);
  1378. timePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
  1379. timeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
  1380. timeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);
  1381. timeBeatUnit = uridMap->map(uridMap->handle, LV2_TIME__beatUnit);
  1382. timeFrame = uridMap->map(uridMap->handle, LV2_TIME__frame);
  1383. timeSpeed = uridMap->map(uridMap->handle, LV2_TIME__speed);
  1384. timeBeatsPerBar = uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar);
  1385. timeBeatsPerMinute = uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute);
  1386. timeTicksPerBeat = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat);
  1387. carlaRequestIdle = uridMap->map(uridMap->handle, "urn:carla:idle");
  1388. carlaUiEvents = uridMap->map(uridMap->handle, "urn:carla:uiEvents");
  1389. }
  1390. } fURIs;
  1391. struct UI {
  1392. const LV2_External_UI_Host* host;
  1393. const LV2UI_Touch* touch;
  1394. LV2UI_Write_Function writeFunction;
  1395. LV2UI_Controller controller;
  1396. bool isVisible;
  1397. UI()
  1398. : host(nullptr),
  1399. touch(nullptr),
  1400. writeFunction(nullptr),
  1401. controller(nullptr),
  1402. isVisible(false) {}
  1403. } fUI;
  1404. private:
  1405. // ----------------------------------------------------------------------------------------------------------------
  1406. #define handlePtr ((Lv2PluginBaseClass*)handle)
  1407. static void extui_run(LV2_External_UI_Widget_Compat* handle)
  1408. {
  1409. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  1410. handlePtr->handleUiRun();
  1411. }
  1412. static void extui_show(LV2_External_UI_Widget_Compat* handle)
  1413. {
  1414. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  1415. carla_debug("extui_show(%p)", handle);
  1416. handlePtr->handleUiShow();
  1417. }
  1418. static void extui_hide(LV2_External_UI_Widget_Compat* handle)
  1419. {
  1420. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  1421. carla_debug("extui_hide(%p)", handle);
  1422. handlePtr->handleUiHide();
  1423. }
  1424. #undef handlePtr
  1425. // ----------------------------------------------------------------------------------------------------------------
  1426. void clearTimeData() noexcept;
  1427. // ----------------------------------------------------------------------------------------------------------------
  1428. CARLA_DECLARE_NON_COPYABLE(Lv2PluginBaseClass)
  1429. };
  1430. // --------------------------------------------------------------------------------------------------------------------
  1431. // Create new RDF object (using lilv)
  1432. static inline
  1433. const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
  1434. {
  1435. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', nullptr);
  1436. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  1437. const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(uri));
  1438. CARLA_SAFE_ASSERT_RETURN(cPlugin != nullptr, nullptr);
  1439. Lilv::Plugin lilvPlugin(cPlugin);
  1440. LV2_RDF_Descriptor* const rdfDescriptor(new LV2_RDF_Descriptor());
  1441. CarlaStringList portGroupURIs(false); // does not allocate own elements
  1442. LinkedList<LilvNode*> portGroupNodes;
  1443. // ----------------------------------------------------------------------------------------------------------------
  1444. // Set Plugin Type
  1445. {
  1446. Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
  1447. if (typeNodes.size() > 0)
  1448. {
  1449. if (typeNodes.contains(lv2World.class_allpass))
  1450. rdfDescriptor->Type[0] |= LV2_PLUGIN_ALLPASS;
  1451. if (typeNodes.contains(lv2World.class_amplifier))
  1452. rdfDescriptor->Type[0] |= LV2_PLUGIN_AMPLIFIER;
  1453. if (typeNodes.contains(lv2World.class_analyzer))
  1454. rdfDescriptor->Type[1] |= LV2_PLUGIN_ANALYSER;
  1455. if (typeNodes.contains(lv2World.class_bandpass))
  1456. rdfDescriptor->Type[0] |= LV2_PLUGIN_BANDPASS;
  1457. if (typeNodes.contains(lv2World.class_chorus))
  1458. rdfDescriptor->Type[1] |= LV2_PLUGIN_CHORUS;
  1459. if (typeNodes.contains(lv2World.class_comb))
  1460. rdfDescriptor->Type[1] |= LV2_PLUGIN_COMB;
  1461. if (typeNodes.contains(lv2World.class_compressor))
  1462. rdfDescriptor->Type[0] |= LV2_PLUGIN_COMPRESSOR;
  1463. if (typeNodes.contains(lv2World.class_constant))
  1464. rdfDescriptor->Type[1] |= LV2_PLUGIN_CONSTANT;
  1465. if (typeNodes.contains(lv2World.class_converter))
  1466. rdfDescriptor->Type[1] |= LV2_PLUGIN_CONVERTER;
  1467. if (typeNodes.contains(lv2World.class_delay))
  1468. rdfDescriptor->Type[0] |= LV2_PLUGIN_DELAY;
  1469. if (typeNodes.contains(lv2World.class_distortion))
  1470. rdfDescriptor->Type[0] |= LV2_PLUGIN_DISTORTION;
  1471. if (typeNodes.contains(lv2World.class_dynamics))
  1472. rdfDescriptor->Type[0] |= LV2_PLUGIN_DYNAMICS;
  1473. if (typeNodes.contains(lv2World.class_eq))
  1474. rdfDescriptor->Type[0] |= LV2_PLUGIN_EQ;
  1475. if (typeNodes.contains(lv2World.class_envelope))
  1476. rdfDescriptor->Type[0] |= LV2_PLUGIN_ENVELOPE;
  1477. if (typeNodes.contains(lv2World.class_expander))
  1478. rdfDescriptor->Type[0] |= LV2_PLUGIN_EXPANDER;
  1479. if (typeNodes.contains(lv2World.class_filter))
  1480. rdfDescriptor->Type[0] |= LV2_PLUGIN_FILTER;
  1481. if (typeNodes.contains(lv2World.class_flanger))
  1482. rdfDescriptor->Type[1] |= LV2_PLUGIN_FLANGER;
  1483. if (typeNodes.contains(lv2World.class_function))
  1484. rdfDescriptor->Type[1] |= LV2_PLUGIN_FUNCTION;
  1485. if (typeNodes.contains(lv2World.class_gate))
  1486. rdfDescriptor->Type[0] |= LV2_PLUGIN_GATE;
  1487. if (typeNodes.contains(lv2World.class_generator))
  1488. rdfDescriptor->Type[1] |= LV2_PLUGIN_GENERATOR;
  1489. if (typeNodes.contains(lv2World.class_highpass))
  1490. rdfDescriptor->Type[0] |= LV2_PLUGIN_HIGHPASS;
  1491. if (typeNodes.contains(lv2World.class_instrument))
  1492. rdfDescriptor->Type[1] |= LV2_PLUGIN_INSTRUMENT;
  1493. if (typeNodes.contains(lv2World.class_limiter))
  1494. rdfDescriptor->Type[0] |= LV2_PLUGIN_LIMITER;
  1495. if (typeNodes.contains(lv2World.class_lowpass))
  1496. rdfDescriptor->Type[0] |= LV2_PLUGIN_LOWPASS;
  1497. if (typeNodes.contains(lv2World.class_mixer))
  1498. rdfDescriptor->Type[1] |= LV2_PLUGIN_MIXER;
  1499. if (typeNodes.contains(lv2World.class_modulator))
  1500. rdfDescriptor->Type[1] |= LV2_PLUGIN_MODULATOR;
  1501. if (typeNodes.contains(lv2World.class_multiEQ))
  1502. rdfDescriptor->Type[0] |= LV2_PLUGIN_MULTI_EQ;
  1503. if (typeNodes.contains(lv2World.class_oscillator))
  1504. rdfDescriptor->Type[1] |= LV2_PLUGIN_OSCILLATOR;
  1505. if (typeNodes.contains(lv2World.class_paraEQ))
  1506. rdfDescriptor->Type[0] |= LV2_PLUGIN_PARA_EQ;
  1507. if (typeNodes.contains(lv2World.class_phaser))
  1508. rdfDescriptor->Type[1] |= LV2_PLUGIN_PHASER;
  1509. if (typeNodes.contains(lv2World.class_pitch))
  1510. rdfDescriptor->Type[1] |= LV2_PLUGIN_PITCH;
  1511. if (typeNodes.contains(lv2World.class_reverb))
  1512. rdfDescriptor->Type[0] |= LV2_PLUGIN_REVERB;
  1513. if (typeNodes.contains(lv2World.class_simulator))
  1514. rdfDescriptor->Type[0] |= LV2_PLUGIN_SIMULATOR;
  1515. if (typeNodes.contains(lv2World.class_spatial))
  1516. rdfDescriptor->Type[1] |= LV2_PLUGIN_SPATIAL;
  1517. if (typeNodes.contains(lv2World.class_spectral))
  1518. rdfDescriptor->Type[1] |= LV2_PLUGIN_SPECTRAL;
  1519. if (typeNodes.contains(lv2World.class_utility))
  1520. rdfDescriptor->Type[1] |= LV2_PLUGIN_UTILITY;
  1521. if (typeNodes.contains(lv2World.class_waveshaper))
  1522. rdfDescriptor->Type[0] |= LV2_PLUGIN_WAVESHAPER;
  1523. }
  1524. lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
  1525. }
  1526. // ----------------------------------------------------------------------------------------------------------------
  1527. // Set Plugin Information
  1528. {
  1529. rdfDescriptor->URI = carla_strdup(uri);
  1530. if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
  1531. {
  1532. if (const char* const name = lilv_node_as_string(nameNode))
  1533. rdfDescriptor->Name = carla_strdup(name);
  1534. lilv_node_free(nameNode);
  1535. }
  1536. if (const char* const author = lilvPlugin.get_author_name().as_string())
  1537. rdfDescriptor->Author = carla_strdup(author);
  1538. if (const char* const binary = lilvPlugin.get_library_uri().as_string())
  1539. rdfDescriptor->Binary = carla_strdup_free(lilv_file_uri_parse(binary, nullptr));
  1540. if (const char* const bundle = lilvPlugin.get_bundle_uri().as_string())
  1541. rdfDescriptor->Bundle = carla_strdup_free(lilv_file_uri_parse(bundle, nullptr));
  1542. Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
  1543. if (licenseNodes.size() > 0)
  1544. {
  1545. if (const char* const license = licenseNodes.get_first().as_string())
  1546. rdfDescriptor->License = carla_strdup(license);
  1547. }
  1548. lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
  1549. }
  1550. // ----------------------------------------------------------------------------------------------------------------
  1551. // Set Plugin UniqueID
  1552. {
  1553. Lilv::Nodes replaceNodes(lilvPlugin.get_value(lv2World.dct_replaces));
  1554. if (replaceNodes.size() > 0)
  1555. {
  1556. Lilv::Node replaceNode(replaceNodes.get_first());
  1557. if (replaceNode.is_uri())
  1558. {
  1559. #if defined(CARLA_UTILS_USE_QT)
  1560. const QString replaceURI(replaceNode.as_uri());
  1561. if (replaceURI.startsWith("urn:"))
  1562. {
  1563. const QString replaceId(replaceURI.split(":").last());
  1564. bool ok;
  1565. const ulong uniqueId(replaceId.toULong(&ok));
  1566. if (ok && uniqueId != 0)
  1567. rdfDescriptor->UniqueID = uniqueId;
  1568. }
  1569. #else
  1570. const water::String replaceURI(replaceNode.as_uri());
  1571. if (replaceURI.startsWith("urn:"))
  1572. {
  1573. const int uniqueId(replaceURI.getTrailingIntValue());
  1574. if (uniqueId > 0)
  1575. rdfDescriptor->UniqueID = static_cast<ulong>(uniqueId);
  1576. }
  1577. #endif
  1578. }
  1579. }
  1580. lilv_nodes_free(const_cast<LilvNodes*>(replaceNodes.me));
  1581. }
  1582. // ----------------------------------------------------------------------------------------------------------------
  1583. // Set Plugin Ports
  1584. if (const uint numPorts = lilvPlugin.get_num_ports())
  1585. {
  1586. rdfDescriptor->PortCount = numPorts;
  1587. rdfDescriptor->Ports = new LV2_RDF_Port[numPorts];
  1588. for (uint i = 0; i < numPorts; ++i)
  1589. {
  1590. Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
  1591. CARLA_SAFE_ASSERT_CONTINUE(lilvPort.me != nullptr);
  1592. LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[i]);
  1593. // --------------------------------------------------------------------------------------------------------
  1594. // Set Port Information
  1595. {
  1596. if (LilvNode* const nameNode = lilv_port_get_name(lilvPlugin.me, lilvPort.me))
  1597. {
  1598. if (const char* const name = lilv_node_as_string(nameNode))
  1599. rdfPort->Name = carla_strdup(name);
  1600. lilv_node_free(nameNode);
  1601. }
  1602. if (const char* const symbol = lilv_node_as_string(lilvPort.get_symbol()))
  1603. rdfPort->Symbol = carla_strdup(symbol);
  1604. if (LilvNode* const commentNode = lilvPort.get(lv2World.rdfs_comment.me))
  1605. {
  1606. rdfPort->Comment = carla_strdup(lilv_node_as_string(commentNode));
  1607. lilv_node_free(commentNode);
  1608. }
  1609. if (LilvNode* const groupNode = lilvPort.get(lv2World.pg_group.me))
  1610. {
  1611. rdfPort->GroupURI = carla_strdup(lilv_node_as_uri(groupNode));
  1612. if (portGroupURIs.appendUnique(rdfPort->GroupURI))
  1613. portGroupNodes.append(groupNode);
  1614. else
  1615. lilv_node_free(groupNode);
  1616. }
  1617. }
  1618. // --------------------------------------------------------------------------------------------------------
  1619. // Set Port Mode and Type
  1620. {
  1621. // Input or Output
  1622. /**/ if (lilvPort.is_a(lv2World.port_input))
  1623. rdfPort->Types |= LV2_PORT_INPUT;
  1624. else if (lilvPort.is_a(lv2World.port_output))
  1625. rdfPort->Types |= LV2_PORT_OUTPUT;
  1626. else
  1627. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is not input or output", uri, rdfPort->Name);
  1628. // Data Type
  1629. /**/ if (lilvPort.is_a(lv2World.port_control))
  1630. {
  1631. rdfPort->Types |= LV2_PORT_CONTROL;
  1632. }
  1633. else if (lilvPort.is_a(lv2World.port_audio))
  1634. {
  1635. rdfPort->Types |= LV2_PORT_AUDIO;
  1636. }
  1637. else if (lilvPort.is_a(lv2World.port_cv))
  1638. {
  1639. rdfPort->Types |= LV2_PORT_CV;
  1640. }
  1641. else if (lilvPort.is_a(lv2World.port_atom))
  1642. {
  1643. rdfPort->Types |= LV2_PORT_ATOM;
  1644. Lilv::Nodes bufferTypeNodes(lilvPort.get_value(lv2World.atom_bufferType));
  1645. for (LilvIter* it = lilv_nodes_begin(bufferTypeNodes.me); ! lilv_nodes_is_end(bufferTypeNodes.me, it); it = lilv_nodes_next(bufferTypeNodes.me, it))
  1646. {
  1647. const Lilv::Node node(lilv_nodes_get(bufferTypeNodes.me, it));
  1648. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  1649. if (node.equals(lv2World.atom_sequence))
  1650. rdfPort->Types |= LV2_PORT_ATOM_SEQUENCE;
  1651. else
  1652. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses an unknown atom buffer type '%s'", uri, rdfPort->Name, node.as_uri());
  1653. }
  1654. Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));
  1655. for (LilvIter* it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
  1656. {
  1657. const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
  1658. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  1659. /**/ if (node.equals(lv2World.midi_event))
  1660. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  1661. else if (node.equals(lv2World.patch_message))
  1662. rdfPort->Types |= LV2_PORT_DATA_PATCH_MESSAGE;
  1663. else if (node.equals(lv2World.time_position))
  1664. rdfPort->Types |= LV2_PORT_DATA_TIME_POSITION;
  1665. #if 0
  1666. // something new we don't support yet?
  1667. else if (std::strstr(node.as_uri(), "lv2plug.in/") != nullptr)
  1668. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of atom type but has unsupported data '%s'", uri, rdfPort->Name, node.as_uri());
  1669. #endif
  1670. }
  1671. lilv_nodes_free(const_cast<LilvNodes*>(bufferTypeNodes.me));
  1672. lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
  1673. }
  1674. else if (lilvPort.is_a(lv2World.port_event))
  1675. {
  1676. rdfPort->Types |= LV2_PORT_EVENT;
  1677. bool supported = false;
  1678. if (lilvPort.supports_event(lv2World.midi_event))
  1679. {
  1680. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  1681. supported = true;
  1682. }
  1683. if (lilvPort.supports_event(lv2World.patch_message))
  1684. {
  1685. rdfPort->Types |= LV2_PORT_DATA_PATCH_MESSAGE;
  1686. supported = true;
  1687. }
  1688. if (lilvPort.supports_event(lv2World.time_position))
  1689. {
  1690. rdfPort->Types |= LV2_PORT_DATA_TIME_POSITION;
  1691. supported = true;
  1692. }
  1693. if (! supported)
  1694. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of event type but has unsupported data", uri, rdfPort->Name);
  1695. }
  1696. else if (lilvPort.is_a(lv2World.port_midi))
  1697. {
  1698. rdfPort->Types |= LV2_PORT_MIDI_LL;
  1699. rdfPort->Types |= LV2_PORT_DATA_MIDI_EVENT;
  1700. }
  1701. else
  1702. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' is of unknown data type", uri, rdfPort->Name);
  1703. }
  1704. // --------------------------------------------------------------------------------------------------------
  1705. // Set Port Properties
  1706. {
  1707. if (lilvPort.has_property(lv2World.pprop_optional))
  1708. rdfPort->Properties |= LV2_PORT_OPTIONAL;
  1709. if (lilvPort.has_property(lv2World.pprop_enumeration))
  1710. rdfPort->Properties |= LV2_PORT_ENUMERATION;
  1711. if (lilvPort.has_property(lv2World.pprop_integer))
  1712. rdfPort->Properties |= LV2_PORT_INTEGER;
  1713. if (lilvPort.has_property(lv2World.pprop_isSideChain))
  1714. rdfPort->Properties |= LV2_PORT_SIDECHAIN;
  1715. if (lilvPort.has_property(lv2World.pprop_sampleRate))
  1716. rdfPort->Properties |= LV2_PORT_SAMPLE_RATE;
  1717. if (lilvPort.has_property(lv2World.pprop_toggled))
  1718. rdfPort->Properties |= LV2_PORT_TOGGLED;
  1719. if (lilvPort.has_property(lv2World.pprop_artifacts))
  1720. rdfPort->Properties |= LV2_PORT_CAUSES_ARTIFACTS;
  1721. if (lilvPort.has_property(lv2World.pprop_continuousCV))
  1722. rdfPort->Properties |= LV2_PORT_CONTINUOUS_CV;
  1723. if (lilvPort.has_property(lv2World.pprop_discreteCV))
  1724. rdfPort->Properties |= LV2_PORT_DISCRETE_CV;
  1725. if (lilvPort.has_property(lv2World.pprop_expensive))
  1726. rdfPort->Properties |= LV2_PORT_EXPENSIVE;
  1727. if (lilvPort.has_property(lv2World.pprop_strictBounds))
  1728. rdfPort->Properties |= LV2_PORT_STRICT_BOUNDS;
  1729. if (lilvPort.has_property(lv2World.pprop_logarithmic))
  1730. rdfPort->Properties |= LV2_PORT_LOGARITHMIC;
  1731. if (lilvPort.has_property(lv2World.pprop_notAutomatic))
  1732. rdfPort->Properties |= LV2_PORT_NOT_AUTOMATIC;
  1733. if (lilvPort.has_property(lv2World.pprop_notOnGUI))
  1734. rdfPort->Properties |= LV2_PORT_NOT_ON_GUI;
  1735. if (lilvPort.has_property(lv2World.pprop_trigger))
  1736. rdfPort->Properties |= LV2_PORT_TRIGGER;
  1737. if (lilvPort.has_property(lv2World.pprop_nonAutomatable))
  1738. rdfPort->Properties |= LV2_PORT_NON_AUTOMATABLE;
  1739. if (lilvPort.has_property(lv2World.reportsLatency))
  1740. rdfPort->Designation = LV2_PORT_DESIGNATION_LATENCY;
  1741. // check if sidechain (some plugins use sidechain groups instead of isSidechain)
  1742. if (LilvNode* const portGroupNode = lilvPort.get(lv2World.pg_group.me))
  1743. {
  1744. if (LilvNode* const portSideChainOfNode = lilv_world_get(lv2World.me, portGroupNode,
  1745. lv2World.pg_sideChainOf.me, nullptr))
  1746. {
  1747. rdfPort->Properties |= LV2_PORT_SIDECHAIN;
  1748. lilv_node_free(portSideChainOfNode);
  1749. }
  1750. lilv_node_free(portGroupNode);
  1751. }
  1752. // no port properties set, check if using old/invalid ones
  1753. if (rdfPort->Properties == 0x0)
  1754. {
  1755. const Lilv::Node oldPropArtifacts(lv2World.new_uri(NS_devp "causesArtifacts"));
  1756. const Lilv::Node oldPropContinuousCV(lv2World.new_uri(NS_devp "continuousCV"));
  1757. const Lilv::Node oldPropDiscreteCV(lv2World.new_uri(NS_devp "discreteCV"));
  1758. const Lilv::Node oldPropExpensive(lv2World.new_uri(NS_devp "expensive"));
  1759. const Lilv::Node oldPropStrictBounds(lv2World.new_uri(NS_devp "hasStrictBounds"));
  1760. const Lilv::Node oldPropLogarithmic(lv2World.new_uri(NS_devp "logarithmic"));
  1761. const Lilv::Node oldPropNotAutomatic(lv2World.new_uri(NS_devp "notAutomatic"));
  1762. const Lilv::Node oldPropNotOnGUI(lv2World.new_uri(NS_devp "notOnGUI"));
  1763. const Lilv::Node oldPropTrigger(lv2World.new_uri(NS_devp "trigger"));
  1764. if (lilvPort.has_property(oldPropArtifacts))
  1765. {
  1766. rdfPort->Properties |= LV2_PORT_CAUSES_ARTIFACTS;
  1767. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'causesArtifacts'", uri, rdfPort->Name);
  1768. }
  1769. if (lilvPort.has_property(oldPropContinuousCV))
  1770. {
  1771. rdfPort->Properties |= LV2_PORT_CONTINUOUS_CV;
  1772. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'continuousCV'", uri, rdfPort->Name);
  1773. }
  1774. if (lilvPort.has_property(oldPropDiscreteCV))
  1775. {
  1776. rdfPort->Properties |= LV2_PORT_DISCRETE_CV;
  1777. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'discreteCV'", uri, rdfPort->Name);
  1778. }
  1779. if (lilvPort.has_property(oldPropExpensive))
  1780. {
  1781. rdfPort->Properties |= LV2_PORT_EXPENSIVE;
  1782. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'expensive'", uri, rdfPort->Name);
  1783. }
  1784. if (lilvPort.has_property(oldPropStrictBounds))
  1785. {
  1786. rdfPort->Properties |= LV2_PORT_STRICT_BOUNDS;
  1787. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'hasStrictBounds'", uri, rdfPort->Name);
  1788. }
  1789. if (lilvPort.has_property(oldPropLogarithmic))
  1790. {
  1791. rdfPort->Properties |= LV2_PORT_LOGARITHMIC;
  1792. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'logarithmic'", uri, rdfPort->Name);
  1793. }
  1794. if (lilvPort.has_property(oldPropNotAutomatic))
  1795. {
  1796. rdfPort->Properties |= LV2_PORT_NOT_AUTOMATIC;
  1797. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notAutomatic'", uri, rdfPort->Name);
  1798. }
  1799. if (lilvPort.has_property(oldPropNotOnGUI))
  1800. {
  1801. rdfPort->Properties |= LV2_PORT_NOT_ON_GUI;
  1802. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'notOnGUI'", uri, rdfPort->Name);
  1803. }
  1804. if (lilvPort.has_property(oldPropTrigger))
  1805. {
  1806. rdfPort->Properties |= LV2_PORT_TRIGGER;
  1807. carla_stderr("lv2_rdf_new(\"%s\") - port '%s' uses old/invalid LV2 property for 'trigger'", uri, rdfPort->Name);
  1808. }
  1809. }
  1810. }
  1811. // --------------------------------------------------------------------------------------------------------
  1812. // Set Port Designation
  1813. {
  1814. if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
  1815. {
  1816. if (const char* const designation = lilv_node_as_string(designationNode))
  1817. {
  1818. /**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
  1819. rdfPort->Designation = LV2_PORT_DESIGNATION_CONTROL;
  1820. else if (std::strcmp(designation, LV2_CORE__enabled) == 0)
  1821. rdfPort->Designation = LV2_PORT_DESIGNATION_ENABLED;
  1822. else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
  1823. rdfPort->Designation = LV2_PORT_DESIGNATION_FREEWHEELING;
  1824. else if (std::strcmp(designation, LV2_CORE__latency) == 0)
  1825. rdfPort->Designation = LV2_PORT_DESIGNATION_LATENCY;
  1826. else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
  1827. rdfPort->Designation = LV2_PORT_DESIGNATION_SAMPLE_RATE;
  1828. else if (std::strcmp(designation, LV2_TIME__bar) == 0)
  1829. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BAR;
  1830. else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
  1831. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BAR_BEAT;
  1832. else if (std::strcmp(designation, LV2_TIME__beat) == 0)
  1833. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEAT;
  1834. else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
  1835. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEAT_UNIT;
  1836. else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
  1837. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR;
  1838. else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
  1839. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE;
  1840. else if (std::strcmp(designation, LV2_TIME__frame) == 0)
  1841. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_FRAME;
  1842. else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
  1843. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND;
  1844. else if (std::strcmp(designation, LV2_TIME__speed) == 0)
  1845. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_SPEED;
  1846. else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  1847. rdfPort->Designation = LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT;
  1848. else if (std::strncmp(designation, LV2_PARAMETERS_PREFIX, std::strlen(LV2_PARAMETERS_PREFIX)) == 0)
  1849. pass();
  1850. else if (std::strncmp(designation, LV2_PORT_GROUPS_PREFIX, std::strlen(LV2_PORT_GROUPS_PREFIX)) == 0)
  1851. pass();
  1852. else
  1853. carla_stderr("lv2_rdf_new(\"%s\") - got unknown port designation '%s'", uri, designation);
  1854. }
  1855. lilv_node_free(designationNode);
  1856. }
  1857. }
  1858. // --------------------------------------------------------------------------------------------------------
  1859. // Set Port MIDI Map
  1860. if (LilvNode* const bindingNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.midi_binding.me))
  1861. {
  1862. if (lilv_node_is_string(bindingNode))
  1863. {
  1864. if (const char* const bindingAsString = lilv_node_as_string(bindingNode))
  1865. {
  1866. if (std::strncmp(bindingAsString, "B0", 2) == 0 && std::strlen(bindingAsString) == 6)
  1867. {
  1868. const char binding[3] = { bindingAsString[2], bindingAsString[3], '\0' };
  1869. const long number = std::strtol(binding, nullptr, 16);
  1870. if (number >= 0 && number <= 0xff)
  1871. {
  1872. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
  1873. rdfPort->MidiMap.Number = static_cast<uint32_t>(number);
  1874. }
  1875. }
  1876. }
  1877. }
  1878. else
  1879. {
  1880. if (lilv_node_is_blank(bindingNode))
  1881. {
  1882. Lilv::Nodes ctrlNumNodes(lv2World.find_nodes(bindingNode, lv2World.midi_ctlrNumber, nullptr));
  1883. if (ctrlNumNodes.size() == 1)
  1884. {
  1885. const int midiCC = ctrlNumNodes.get_first().as_int();
  1886. if (midiCC >= 0 && midiCC <= 0xff)
  1887. {
  1888. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
  1889. rdfPort->MidiMap.Number = static_cast<uint32_t>(midiCC);
  1890. }
  1891. }
  1892. lilv_nodes_free(const_cast<LilvNodes*>(ctrlNumNodes.me));
  1893. }
  1894. }
  1895. lilv_node_free(bindingNode);
  1896. }
  1897. else if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me))
  1898. {
  1899. if (lilv_node_is_blank(midiMapNode))
  1900. {
  1901. Lilv::Nodes midiMapTypeNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlType, nullptr));
  1902. Lilv::Nodes midiMapNumberNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlNumber, nullptr));
  1903. if (midiMapTypeNodes.size() == 1 && midiMapNumberNodes.size() == 1)
  1904. {
  1905. if (const char* const midiMapType = midiMapTypeNodes.get_first().as_string())
  1906. {
  1907. /**/ if (std::strcmp(midiMapType, LV2_MIDI_Map__CC) == 0)
  1908. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
  1909. else if (std::strcmp(midiMapType, LV2_MIDI_Map__NRPN) == 0)
  1910. rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_NRPN;
  1911. else
  1912. carla_stderr("lv2_rdf_new(\"%s\") - got unknown port Midi-Map type '%s'", uri, midiMapType);
  1913. rdfPort->MidiMap.Number = static_cast<uint32_t>(midiMapNumberNodes.get_first().as_int());
  1914. }
  1915. }
  1916. lilv_nodes_free(const_cast<LilvNodes*>(midiMapTypeNodes.me));
  1917. lilv_nodes_free(const_cast<LilvNodes*>(midiMapNumberNodes.me));
  1918. }
  1919. lilv_node_free(midiMapNode);
  1920. }
  1921. // --------------------------------------------------------------------------------------------------------
  1922. // Set Port Points
  1923. {
  1924. if (LilvNode* const defNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_default.me))
  1925. {
  1926. rdfPort->Points.Hints |= LV2_PORT_POINT_DEFAULT;
  1927. rdfPort->Points.Default = lilv_node_as_float(defNode);
  1928. lilv_node_free(defNode);
  1929. }
  1930. if (LilvNode* const minNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_minimum.me))
  1931. {
  1932. rdfPort->Points.Hints |= LV2_PORT_POINT_MINIMUM;
  1933. rdfPort->Points.Minimum = lilv_node_as_float(minNode);
  1934. lilv_node_free(minNode);
  1935. }
  1936. if (LilvNode* const maxNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.value_maximum.me))
  1937. {
  1938. rdfPort->Points.Hints |= LV2_PORT_POINT_MAXIMUM;
  1939. rdfPort->Points.Maximum = lilv_node_as_float(maxNode);
  1940. lilv_node_free(maxNode);
  1941. }
  1942. }
  1943. // --------------------------------------------------------------------------------------------------------
  1944. // Set Port Unit
  1945. {
  1946. if (LilvNode* const unitUnitNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.unit_unit.me))
  1947. {
  1948. if (lilv_node_is_uri(unitUnitNode))
  1949. {
  1950. if (const char* const unitUnit = lilv_node_as_uri(unitUnitNode))
  1951. {
  1952. rdfPort->Unit.Hints |= LV2_PORT_UNIT_UNIT;
  1953. /**/ if (std::strcmp(unitUnit, LV2_UNITS__bar) == 0)
  1954. rdfPort->Unit.Unit = LV2_PORT_UNIT_BAR;
  1955. else if (std::strcmp(unitUnit, LV2_UNITS__beat) == 0)
  1956. rdfPort->Unit.Unit = LV2_PORT_UNIT_BEAT;
  1957. else if (std::strcmp(unitUnit, LV2_UNITS__bpm) == 0)
  1958. rdfPort->Unit.Unit = LV2_PORT_UNIT_BPM;
  1959. else if (std::strcmp(unitUnit, LV2_UNITS__cent) == 0)
  1960. rdfPort->Unit.Unit = LV2_PORT_UNIT_CENT;
  1961. else if (std::strcmp(unitUnit, LV2_UNITS__cm) == 0)
  1962. rdfPort->Unit.Unit = LV2_PORT_UNIT_CM;
  1963. else if (std::strcmp(unitUnit, LV2_UNITS__coef) == 0)
  1964. rdfPort->Unit.Unit = LV2_PORT_UNIT_COEF;
  1965. else if (std::strcmp(unitUnit, LV2_UNITS__db) == 0)
  1966. rdfPort->Unit.Unit = LV2_PORT_UNIT_DB;
  1967. else if (std::strcmp(unitUnit, LV2_UNITS__degree) == 0)
  1968. rdfPort->Unit.Unit = LV2_PORT_UNIT_DEGREE;
  1969. else if (std::strcmp(unitUnit, LV2_UNITS__frame) == 0)
  1970. rdfPort->Unit.Unit = LV2_PORT_UNIT_FRAME;
  1971. else if (std::strcmp(unitUnit, LV2_UNITS__hz) == 0)
  1972. rdfPort->Unit.Unit = LV2_PORT_UNIT_HZ;
  1973. else if (std::strcmp(unitUnit, LV2_UNITS__inch) == 0)
  1974. rdfPort->Unit.Unit = LV2_PORT_UNIT_INCH;
  1975. else if (std::strcmp(unitUnit, LV2_UNITS__khz) == 0)
  1976. rdfPort->Unit.Unit = LV2_PORT_UNIT_KHZ;
  1977. else if (std::strcmp(unitUnit, LV2_UNITS__km) == 0)
  1978. rdfPort->Unit.Unit = LV2_PORT_UNIT_KM;
  1979. else if (std::strcmp(unitUnit, LV2_UNITS__m) == 0)
  1980. rdfPort->Unit.Unit = LV2_PORT_UNIT_M;
  1981. else if (std::strcmp(unitUnit, LV2_UNITS__mhz) == 0)
  1982. rdfPort->Unit.Unit = LV2_PORT_UNIT_MHZ;
  1983. else if (std::strcmp(unitUnit, LV2_UNITS__midiNote) == 0)
  1984. rdfPort->Unit.Unit = LV2_PORT_UNIT_MIDINOTE;
  1985. else if (std::strcmp(unitUnit, LV2_UNITS__mile) == 0)
  1986. rdfPort->Unit.Unit = LV2_PORT_UNIT_MILE;
  1987. else if (std::strcmp(unitUnit, LV2_UNITS__min) == 0)
  1988. rdfPort->Unit.Unit = LV2_PORT_UNIT_MIN;
  1989. else if (std::strcmp(unitUnit, LV2_UNITS__mm) == 0)
  1990. rdfPort->Unit.Unit = LV2_PORT_UNIT_MM;
  1991. else if (std::strcmp(unitUnit, LV2_UNITS__ms) == 0)
  1992. rdfPort->Unit.Unit = LV2_PORT_UNIT_MS;
  1993. else if (std::strcmp(unitUnit, LV2_UNITS__oct) == 0)
  1994. rdfPort->Unit.Unit = LV2_PORT_UNIT_OCT;
  1995. else if (std::strcmp(unitUnit, LV2_UNITS__pc) == 0)
  1996. rdfPort->Unit.Unit = LV2_PORT_UNIT_PC;
  1997. else if (std::strcmp(unitUnit, LV2_UNITS__s) == 0)
  1998. rdfPort->Unit.Unit = LV2_PORT_UNIT_S;
  1999. else if (std::strcmp(unitUnit, LV2_UNITS__semitone12TET) == 0)
  2000. rdfPort->Unit.Unit = LV2_PORT_UNIT_SEMITONE;
  2001. else if (std::strcmp(unitUnit, "http://moddevices.com/ns/mod#volts") == 0)
  2002. rdfPort->Unit.Unit = LV2_PORT_UNIT_VOLTS;
  2003. else
  2004. carla_stderr("lv2_rdf_new(\"%s\") - got unknown unit '%s'", uri, unitUnit);
  2005. }
  2006. }
  2007. if (LilvNode* const unitNameNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_name.me, nullptr))
  2008. {
  2009. if (const char* const unitName = lilv_node_as_string(unitNameNode))
  2010. {
  2011. rdfPort->Unit.Hints |= LV2_PORT_UNIT_NAME;
  2012. rdfPort->Unit.Name = carla_strdup(unitName);
  2013. }
  2014. lilv_node_free(unitNameNode);
  2015. }
  2016. if (LilvNode* const unitRenderNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_render.me, nullptr))
  2017. {
  2018. if (const char* const unitRender = lilv_node_as_string(unitRenderNode))
  2019. {
  2020. rdfPort->Unit.Hints |= LV2_PORT_UNIT_RENDER;
  2021. rdfPort->Unit.Render = carla_strdup(unitRender);
  2022. }
  2023. lilv_node_free(unitRenderNode);
  2024. }
  2025. if (LilvNode* const unitSymbolNode = lilv_world_get(lv2World.me, unitUnitNode, lv2World.unit_symbol.me, nullptr))
  2026. {
  2027. if (const char* const unitSymbol = lilv_node_as_string(unitSymbolNode))
  2028. {
  2029. rdfPort->Unit.Hints |= LV2_PORT_UNIT_SYMBOL;
  2030. rdfPort->Unit.Symbol = carla_strdup(unitSymbol);
  2031. }
  2032. lilv_node_free(unitSymbolNode);
  2033. }
  2034. lilv_node_free(unitUnitNode);
  2035. }
  2036. }
  2037. // --------------------------------------------------------------------------------------------------------
  2038. // Set Port Minimum Size
  2039. {
  2040. if (LilvNode* const minimumSizeNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.rz_minSize.me))
  2041. {
  2042. const int minimumSize(lilv_node_as_int(minimumSizeNode));
  2043. if (minimumSize > 0)
  2044. rdfPort->MinimumSize = static_cast<uint32_t>(minimumSize);
  2045. else
  2046. carla_safe_assert_int("minimumSize > 0", __FILE__, __LINE__, minimumSize);
  2047. lilv_node_free(minimumSizeNode);
  2048. }
  2049. }
  2050. // --------------------------------------------------------------------------------------------------------
  2051. // Set Port Scale Points
  2052. {
  2053. Lilv::ScalePoints lilvScalePoints(lilvPort.get_scale_points());
  2054. if (const uint numScalePoints = lilvScalePoints.size())
  2055. {
  2056. rdfPort->ScalePoints = new LV2_RDF_PortScalePoint[numScalePoints];
  2057. // get all scalepoints and sort them by value
  2058. LilvScalePointMap sortedpoints;
  2059. LILV_FOREACH(scale_points, it, lilvScalePoints)
  2060. {
  2061. Lilv::ScalePoint lilvScalePoint(lilvScalePoints.get(it));
  2062. CARLA_SAFE_ASSERT_CONTINUE(lilvScalePoint.get_label() != nullptr);
  2063. if (const LilvNode* const valuenode = lilvScalePoint.get_value())
  2064. {
  2065. const double valueid = lilv_node_as_float(valuenode);
  2066. sortedpoints[valueid] = lilvScalePoint.me;
  2067. }
  2068. }
  2069. // now safe to store, sorted by using std::map
  2070. uint numUsed = 0;
  2071. for (LilvScalePointMap::iterator it=sortedpoints.begin(), end=sortedpoints.end(); it != end; ++it)
  2072. {
  2073. CARLA_SAFE_ASSERT_BREAK(numUsed < numScalePoints);
  2074. LV2_RDF_PortScalePoint* const rdfScalePoint(&rdfPort->ScalePoints[numUsed++]);
  2075. const LilvScalePoint* const scalepoint = it->second;
  2076. const LilvNode* const xlabel = lilv_scale_point_get_label(scalepoint);
  2077. const LilvNode* const xvalue = lilv_scale_point_get_value(scalepoint);
  2078. rdfScalePoint->Label = carla_strdup(lilv_node_as_string(xlabel));
  2079. rdfScalePoint->Value = lilv_node_as_float(xvalue);
  2080. }
  2081. rdfPort->ScalePointCount = numUsed;
  2082. }
  2083. lilv_nodes_free(const_cast<LilvNodes*>(lilvScalePoints.me));
  2084. }
  2085. }
  2086. }
  2087. // ----------------------------------------------------------------------------------------------------------------
  2088. // Set Plugin Parameters
  2089. {
  2090. std::map<std::string, LV2_RDF_Parameter> parameters;
  2091. Lilv::Nodes patchReadableNodes(lilvPlugin.get_value(lv2World.patch_readable));
  2092. Lilv::Nodes patchWritableNodes(lilvPlugin.get_value(lv2World.patch_writable));
  2093. if (const uint numParameters = patchWritableNodes.size())
  2094. {
  2095. uint numUsed = 0;
  2096. LILV_FOREACH(nodes, it, patchWritableNodes)
  2097. {
  2098. CARLA_SAFE_ASSERT_BREAK(numUsed < numParameters);
  2099. Lilv::Node patchWritableNode(patchWritableNodes.get(it));
  2100. if (LilvNode* const typeNode = lilv_world_get(lv2World.me, patchWritableNode,
  2101. lv2World.rdf_type.me, nullptr))
  2102. {
  2103. const char* const type = lilv_node_as_uri(typeNode);
  2104. if (std::strcmp(type, LV2_CORE__Parameter) != 0)
  2105. {
  2106. lilv_node_free(typeNode);
  2107. continue;
  2108. }
  2109. lilv_node_free(typeNode);
  2110. }
  2111. else
  2112. {
  2113. continue;
  2114. }
  2115. CARLA_SAFE_ASSERT_CONTINUE(patchWritableNode.is_uri());
  2116. ++numUsed;
  2117. LV2_RDF_Parameter rdfParam;
  2118. rdfParam.URI = carla_strdup(patchWritableNode.as_uri());
  2119. rdfParam.Flags = LV2_PARAMETER_FLAG_INPUT;
  2120. if (patchReadableNodes.contains(patchWritableNode))
  2121. rdfParam.Flags |= LV2_PARAMETER_FLAG_OUTPUT;
  2122. // ----------------------------------------------------------------------------------------------------
  2123. // Set Basics
  2124. if (LilvNode* const rangeNode = lilv_world_get(lv2World.me, patchWritableNode,
  2125. lv2World.rdfs_range.me, nullptr))
  2126. {
  2127. const char* const rangeURI = lilv_node_as_string(rangeNode);
  2128. /**/ if (std::strcmp(rangeURI, LV2_ATOM__Bool) == 0)
  2129. rdfParam.Type = LV2_PARAMETER_TYPE_BOOL;
  2130. else if (std::strcmp(rangeURI, LV2_ATOM__Int) == 0)
  2131. rdfParam.Type = LV2_PARAMETER_TYPE_INT;
  2132. else if (std::strcmp(rangeURI, LV2_ATOM__Long) == 0)
  2133. rdfParam.Type = LV2_PARAMETER_TYPE_LONG;
  2134. else if (std::strcmp(rangeURI, LV2_ATOM__Float) == 0)
  2135. rdfParam.Type = LV2_PARAMETER_TYPE_FLOAT;
  2136. else if (std::strcmp(rangeURI, LV2_ATOM__Double) == 0)
  2137. rdfParam.Type = LV2_PARAMETER_TYPE_DOUBLE;
  2138. else if (std::strcmp(rangeURI, LV2_ATOM__Path) == 0)
  2139. rdfParam.Type = LV2_PARAMETER_TYPE_PATH;
  2140. else if (std::strcmp(rangeURI, LV2_ATOM__String) == 0)
  2141. rdfParam.Type = LV2_PARAMETER_TYPE_STRING;
  2142. else
  2143. carla_stderr("lv2_rdf_new(\"%s\") - got unknown parameter type '%s'", uri, rangeURI);
  2144. lilv_node_free(rangeNode);
  2145. }
  2146. if (LilvNode* const labelNode = lilv_world_get(lv2World.me, patchWritableNode,
  2147. lv2World.rdfs_label.me, nullptr))
  2148. {
  2149. rdfParam.Label = carla_strdup(lilv_node_as_string(labelNode));
  2150. lilv_node_free(labelNode);
  2151. }
  2152. if (LilvNode* const commentNode = lilv_world_get(lv2World.me, patchWritableNode,
  2153. lv2World.rdfs_comment.me, nullptr))
  2154. {
  2155. rdfParam.Comment = carla_strdup_safe(lilv_node_as_string(commentNode));
  2156. lilv_node_free(commentNode);
  2157. }
  2158. if (LilvNode* const groupNode = lilv_world_get(lv2World.me, patchWritableNode,
  2159. lv2World.pg_group.me, nullptr))
  2160. {
  2161. rdfParam.GroupURI = carla_strdup_safe(lilv_node_as_uri(groupNode));
  2162. if (portGroupURIs.appendUnique(rdfParam.GroupURI))
  2163. portGroupNodes.append(groupNode);
  2164. else
  2165. lilv_node_free(groupNode);
  2166. }
  2167. // ----------------------------------------------------------------------------------------------------
  2168. // Set Port MIDI Map
  2169. if (LilvNode* const bindingNode = lilv_world_get(lv2World.me, patchWritableNode,
  2170. lv2World.midi_binding.me, nullptr))
  2171. {
  2172. if (const char* const bindingAsString = lilv_node_as_string(bindingNode))
  2173. {
  2174. if (std::strncmp(bindingAsString, "B0", 2) == 0 && std::strlen(bindingAsString) == 6)
  2175. {
  2176. const char binding[3] = { bindingAsString[2], bindingAsString[3], '\0' };
  2177. const long number = std::strtol(binding, nullptr, 16);
  2178. if (number >= 0 && number <= 0xff)
  2179. {
  2180. rdfParam.MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
  2181. rdfParam.MidiMap.Number = static_cast<uint32_t>(number);
  2182. }
  2183. }
  2184. }
  2185. lilv_node_free(bindingNode);
  2186. }
  2187. // ----------------------------------------------------------------------------------------------------
  2188. // Set Port Points
  2189. if (LilvNode* const defNode = lilv_world_get(lv2World.me, patchWritableNode,
  2190. lv2World.value_default.me, nullptr))
  2191. {
  2192. rdfParam.Points.Hints |= LV2_PORT_POINT_DEFAULT;
  2193. rdfParam.Points.Default = lilv_node_as_float(defNode);
  2194. lilv_node_free(defNode);
  2195. }
  2196. if (LilvNode* const minNode = lilv_world_get(lv2World.me, patchWritableNode,
  2197. lv2World.value_minimum.me, nullptr))
  2198. {
  2199. rdfParam.Points.Hints |= LV2_PORT_POINT_MINIMUM;
  2200. rdfParam.Points.Minimum = lilv_node_as_float(minNode);
  2201. lilv_node_free(minNode);
  2202. }
  2203. if (LilvNode* const maxNode = lilv_world_get(lv2World.me, patchWritableNode,
  2204. lv2World.value_maximum.me, nullptr))
  2205. {
  2206. rdfParam.Points.Hints |= LV2_PORT_POINT_MAXIMUM;
  2207. rdfParam.Points.Maximum = lilv_node_as_float(maxNode);
  2208. lilv_node_free(maxNode);
  2209. }
  2210. // ----------------------------------------------------------------------------------------------------
  2211. // Set Port Unit
  2212. if (LilvNode* const unitUnitNode = lilv_world_get(lv2World.me, patchWritableNode,
  2213. lv2World.unit_unit.me, nullptr))
  2214. {
  2215. if (lilv_node_is_uri(unitUnitNode))
  2216. {
  2217. if (const char* const unitUnit = lilv_node_as_uri(unitUnitNode))
  2218. {
  2219. rdfParam.Unit.Hints |= LV2_PORT_UNIT_UNIT;
  2220. /**/ if (std::strcmp(unitUnit, LV2_UNITS__bar) == 0)
  2221. rdfParam.Unit.Unit = LV2_PORT_UNIT_BAR;
  2222. else if (std::strcmp(unitUnit, LV2_UNITS__beat) == 0)
  2223. rdfParam.Unit.Unit = LV2_PORT_UNIT_BEAT;
  2224. else if (std::strcmp(unitUnit, LV2_UNITS__bpm) == 0)
  2225. rdfParam.Unit.Unit = LV2_PORT_UNIT_BPM;
  2226. else if (std::strcmp(unitUnit, LV2_UNITS__cent) == 0)
  2227. rdfParam.Unit.Unit = LV2_PORT_UNIT_CENT;
  2228. else if (std::strcmp(unitUnit, LV2_UNITS__cm) == 0)
  2229. rdfParam.Unit.Unit = LV2_PORT_UNIT_CM;
  2230. else if (std::strcmp(unitUnit, LV2_UNITS__coef) == 0)
  2231. rdfParam.Unit.Unit = LV2_PORT_UNIT_COEF;
  2232. else if (std::strcmp(unitUnit, LV2_UNITS__db) == 0)
  2233. rdfParam.Unit.Unit = LV2_PORT_UNIT_DB;
  2234. else if (std::strcmp(unitUnit, LV2_UNITS__degree) == 0)
  2235. rdfParam.Unit.Unit = LV2_PORT_UNIT_DEGREE;
  2236. else if (std::strcmp(unitUnit, LV2_UNITS__frame) == 0)
  2237. rdfParam.Unit.Unit = LV2_PORT_UNIT_FRAME;
  2238. else if (std::strcmp(unitUnit, LV2_UNITS__hz) == 0)
  2239. rdfParam.Unit.Unit = LV2_PORT_UNIT_HZ;
  2240. else if (std::strcmp(unitUnit, LV2_UNITS__inch) == 0)
  2241. rdfParam.Unit.Unit = LV2_PORT_UNIT_INCH;
  2242. else if (std::strcmp(unitUnit, LV2_UNITS__khz) == 0)
  2243. rdfParam.Unit.Unit = LV2_PORT_UNIT_KHZ;
  2244. else if (std::strcmp(unitUnit, LV2_UNITS__km) == 0)
  2245. rdfParam.Unit.Unit = LV2_PORT_UNIT_KM;
  2246. else if (std::strcmp(unitUnit, LV2_UNITS__m) == 0)
  2247. rdfParam.Unit.Unit = LV2_PORT_UNIT_M;
  2248. else if (std::strcmp(unitUnit, LV2_UNITS__mhz) == 0)
  2249. rdfParam.Unit.Unit = LV2_PORT_UNIT_MHZ;
  2250. else if (std::strcmp(unitUnit, LV2_UNITS__midiNote) == 0)
  2251. rdfParam.Unit.Unit = LV2_PORT_UNIT_MIDINOTE;
  2252. else if (std::strcmp(unitUnit, LV2_UNITS__mile) == 0)
  2253. rdfParam.Unit.Unit = LV2_PORT_UNIT_MILE;
  2254. else if (std::strcmp(unitUnit, LV2_UNITS__min) == 0)
  2255. rdfParam.Unit.Unit = LV2_PORT_UNIT_MIN;
  2256. else if (std::strcmp(unitUnit, LV2_UNITS__mm) == 0)
  2257. rdfParam.Unit.Unit = LV2_PORT_UNIT_MM;
  2258. else if (std::strcmp(unitUnit, LV2_UNITS__ms) == 0)
  2259. rdfParam.Unit.Unit = LV2_PORT_UNIT_MS;
  2260. else if (std::strcmp(unitUnit, LV2_UNITS__oct) == 0)
  2261. rdfParam.Unit.Unit = LV2_PORT_UNIT_OCT;
  2262. else if (std::strcmp(unitUnit, LV2_UNITS__pc) == 0)
  2263. rdfParam.Unit.Unit = LV2_PORT_UNIT_PC;
  2264. else if (std::strcmp(unitUnit, LV2_UNITS__s) == 0)
  2265. rdfParam.Unit.Unit = LV2_PORT_UNIT_S;
  2266. else if (std::strcmp(unitUnit, LV2_UNITS__semitone12TET) == 0)
  2267. rdfParam.Unit.Unit = LV2_PORT_UNIT_SEMITONE;
  2268. else if (std::strcmp(unitUnit, "http://moddevices.com/ns/mod#volts") == 0)
  2269. rdfParam.Unit.Unit = LV2_PORT_UNIT_VOLTS;
  2270. else
  2271. carla_stderr("lv2_rdf_new(\"%s\") - got unknown unit '%s'", uri, unitUnit);
  2272. }
  2273. }
  2274. if (LilvNode* const unitNameNode = lilv_world_get(lv2World.me, unitUnitNode,
  2275. lv2World.unit_name.me, nullptr))
  2276. {
  2277. if (const char* const unitName = lilv_node_as_string(unitNameNode))
  2278. {
  2279. rdfParam.Unit.Hints |= LV2_PORT_UNIT_NAME;
  2280. rdfParam.Unit.Name = carla_strdup(unitName);
  2281. }
  2282. lilv_node_free(unitNameNode);
  2283. }
  2284. if (LilvNode* const unitRenderNode = lilv_world_get(lv2World.me, unitUnitNode,
  2285. lv2World.unit_render.me, nullptr))
  2286. {
  2287. if (const char* const unitRender = lilv_node_as_string(unitRenderNode))
  2288. {
  2289. rdfParam.Unit.Hints |= LV2_PORT_UNIT_RENDER;
  2290. rdfParam.Unit.Render = carla_strdup(unitRender);
  2291. }
  2292. lilv_node_free(unitRenderNode);
  2293. }
  2294. if (LilvNode* const unitSymbolNode = lilv_world_get(lv2World.me, unitUnitNode,
  2295. lv2World.unit_symbol.me, nullptr))
  2296. {
  2297. if (const char* const unitSymbol = lilv_node_as_string(unitSymbolNode))
  2298. {
  2299. rdfParam.Unit.Hints |= LV2_PORT_UNIT_SYMBOL;
  2300. rdfParam.Unit.Symbol = carla_strdup(unitSymbol);
  2301. }
  2302. lilv_node_free(unitSymbolNode);
  2303. }
  2304. lilv_node_free(unitUnitNode);
  2305. }
  2306. parameters[rdfParam.URI].copyAndReplace(rdfParam);
  2307. }
  2308. CARLA_SAFE_ASSERT_UINT2(parameters.size() == numUsed, parameters.size(), numUsed);
  2309. rdfDescriptor->Parameters = new LV2_RDF_Parameter[numUsed];
  2310. rdfDescriptor->ParameterCount = numUsed;
  2311. numUsed = 0;
  2312. for (std::map<std::string, LV2_RDF_Parameter>::iterator it = parameters.begin(), end = parameters.end();
  2313. it != end; ++it)
  2314. {
  2315. rdfDescriptor->Parameters[numUsed++].copyAndReplace(it->second);
  2316. }
  2317. }
  2318. lilv_nodes_free(const_cast<LilvNodes*>(patchReadableNodes.me));
  2319. lilv_nodes_free(const_cast<LilvNodes*>(patchWritableNodes.me));
  2320. }
  2321. // ----------------------------------------------------------------------------------------------------------------
  2322. // Set Plugin Port Groups
  2323. if (const size_t portGroupCount = portGroupURIs.count())
  2324. {
  2325. rdfDescriptor->PortGroups = new LV2_RDF_PortGroup[portGroupCount];
  2326. uint32_t count = 0;
  2327. CarlaStringList::Itenerator itu = portGroupURIs.begin2();
  2328. LinkedList<LilvNode*>::Itenerator itn = portGroupNodes.begin2();
  2329. for (; itu.valid() && itn.valid(); itu.next(), itn.next())
  2330. {
  2331. const char* const portGroupURI = itu.getValue(nullptr);
  2332. CARLA_SAFE_ASSERT_CONTINUE(portGroupURI != nullptr);
  2333. LilvNode* const portGroupNode = itn.getValue(nullptr);
  2334. CARLA_SAFE_ASSERT_CONTINUE(portGroupNode != nullptr);
  2335. LV2_RDF_PortGroup& portGroup(rdfDescriptor->PortGroups[count]);
  2336. portGroup.URI = portGroupURI;
  2337. if (LilvNode* const portGroupNameNode = lilv_world_get(lv2World.me, portGroupNode,
  2338. lv2World.lv2_name.me, nullptr))
  2339. {
  2340. portGroup.Name = carla_strdup_safe(lilv_node_as_string(portGroupNameNode));
  2341. lilv_node_free(portGroupNameNode);
  2342. }
  2343. // some plugins use rdfs:label, spec was not clear which one to use
  2344. else if (LilvNode* const portGroupLabelNode = lilv_world_get(lv2World.me, portGroupNode,
  2345. lv2World.rdfs_label.me, nullptr))
  2346. {
  2347. portGroup.Name = carla_strdup_safe(lilv_node_as_string(portGroupLabelNode));
  2348. lilv_node_free(portGroupLabelNode);
  2349. }
  2350. if (LilvNode* const portGroupSymbolNode = lilv_world_get(lv2World.me, portGroupNode,
  2351. lv2World.lv2_symbol.me, nullptr))
  2352. {
  2353. portGroup.Symbol = carla_strdup_safe(lilv_node_as_string(portGroupSymbolNode));
  2354. lilv_node_free(portGroupSymbolNode);
  2355. }
  2356. ++count;
  2357. lilv_node_free(portGroupNode);
  2358. }
  2359. rdfDescriptor->PortGroupCount = count;
  2360. portGroupNodes.clear();
  2361. }
  2362. // ----------------------------------------------------------------------------------------------------------------
  2363. // Set Plugin Presets
  2364. if (loadPresets)
  2365. {
  2366. Lilv::Nodes presetNodes(lilvPlugin.get_related(lv2World.preset_preset));
  2367. if (presetNodes.size() > 0)
  2368. {
  2369. // create a list of preset URIs (for sorting and unique-ness)
  2370. #if defined(CARLA_UTILS_USE_QT)
  2371. QStringList presetListURIs;
  2372. LILV_FOREACH(nodes, it, presetNodes)
  2373. {
  2374. Lilv::Node presetNode(presetNodes.get(it));
  2375. QString presetURI(presetNode.as_uri());
  2376. if (! (presetURI.trimmed().isEmpty() || presetListURIs.contains(presetURI)))
  2377. presetListURIs.append(presetURI);
  2378. }
  2379. presetListURIs.sort();
  2380. rdfDescriptor->PresetCount = static_cast<uint32_t>(presetListURIs.count());
  2381. #else
  2382. water::StringArray presetListURIs;
  2383. LILV_FOREACH(nodes, it, presetNodes)
  2384. {
  2385. Lilv::Node presetNode(presetNodes.get(it));
  2386. water::String presetURI(presetNode.as_uri());
  2387. if (presetURI.trim().isNotEmpty())
  2388. presetListURIs.addIfNotAlreadyThere(presetURI);
  2389. }
  2390. presetListURIs.sortNatural();
  2391. rdfDescriptor->PresetCount = static_cast<uint32_t>(presetListURIs.size());
  2392. #endif
  2393. // create presets with unique URIs
  2394. rdfDescriptor->Presets = new LV2_RDF_Preset[rdfDescriptor->PresetCount];
  2395. // set preset data
  2396. LILV_FOREACH(nodes, it, presetNodes)
  2397. {
  2398. Lilv::Node presetNode(presetNodes.get(it));
  2399. const char* const presetURI(presetNode.as_uri());
  2400. CARLA_SAFE_ASSERT_CONTINUE(presetURI != nullptr && presetURI[0] != '\0');
  2401. // try to find label without loading the preset resource first
  2402. Lilv::Nodes presetLabelNodes(lv2World.find_nodes(presetNode, lv2World.rdfs_label, nullptr));
  2403. // failed, try loading resource
  2404. if (presetLabelNodes.size() == 0)
  2405. {
  2406. // if loading resource fails, skip this preset
  2407. if (lv2World.load_resource(presetNode) == -1)
  2408. continue;
  2409. // ok, let's try again
  2410. presetLabelNodes = lv2World.find_nodes(presetNode, lv2World.rdfs_label, nullptr);
  2411. }
  2412. if (presetLabelNodes.size() > 0)
  2413. {
  2414. #if defined(CARLA_UTILS_USE_QT)
  2415. const int index = presetListURIs.indexOf(QString(presetURI));
  2416. #else
  2417. const int index = presetListURIs.indexOf(water::String(presetURI));
  2418. #endif
  2419. CARLA_SAFE_ASSERT_CONTINUE(index >= 0 && index < static_cast<int>(rdfDescriptor->PresetCount));
  2420. LV2_RDF_Preset* const rdfPreset(&rdfDescriptor->Presets[index]);
  2421. // ---------------------------------------------------
  2422. // Set Preset Information
  2423. rdfPreset->URI = carla_strdup(presetURI);
  2424. if (const char* const label = presetLabelNodes.get_first().as_string())
  2425. rdfPreset->Label = carla_strdup(label);
  2426. lilv_nodes_free(const_cast<LilvNodes*>(presetLabelNodes.me));
  2427. }
  2428. }
  2429. }
  2430. lilv_nodes_free(const_cast<LilvNodes*>(presetNodes.me));
  2431. }
  2432. // ----------------------------------------------------------------------------------------------------------------
  2433. // Set Plugin Features
  2434. {
  2435. Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
  2436. if (const uint numFeatures = lilvFeatureNodes.size())
  2437. {
  2438. Lilv::Nodes lilvFeatureNodesR(lilvPlugin.get_required_features());
  2439. rdfDescriptor->Features = new LV2_RDF_Feature[numFeatures];
  2440. uint numUsed = 0;
  2441. LILV_FOREACH(nodes, it, lilvFeatureNodes)
  2442. {
  2443. CARLA_SAFE_ASSERT_BREAK(numUsed < numFeatures);
  2444. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
  2445. LV2_RDF_Feature* const rdfFeature(&rdfDescriptor->Features[numUsed++]);
  2446. rdfFeature->Required = lilvFeatureNodesR.contains(lilvFeatureNode);
  2447. if (const char* const featureURI = lilvFeatureNode.as_uri())
  2448. rdfFeature->URI = carla_strdup(featureURI);
  2449. else
  2450. rdfFeature->URI = nullptr;
  2451. }
  2452. rdfDescriptor->FeatureCount = numUsed;
  2453. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodesR.me));
  2454. }
  2455. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  2456. }
  2457. // ----------------------------------------------------------------------------------------------------------------
  2458. // Set Plugin Extensions
  2459. {
  2460. Lilv::Nodes lilvExtensionDataNodes(lilvPlugin.get_extension_data());
  2461. if (const uint numExtensions = lilvExtensionDataNodes.size())
  2462. {
  2463. rdfDescriptor->Extensions = new LV2_URI[numExtensions];
  2464. uint numUsed = 0;
  2465. LILV_FOREACH(nodes, it, lilvExtensionDataNodes)
  2466. {
  2467. CARLA_SAFE_ASSERT_BREAK(numUsed < numExtensions);
  2468. Lilv::Node lilvExtensionDataNode(lilvExtensionDataNodes.get(it));
  2469. LV2_URI* const rdfExtension(&rdfDescriptor->Extensions[numUsed++]);
  2470. if (lilvExtensionDataNode.is_uri())
  2471. {
  2472. if (const char* const extURI = lilvExtensionDataNode.as_uri())
  2473. {
  2474. *rdfExtension = carla_strdup(extURI);
  2475. continue;
  2476. }
  2477. }
  2478. *rdfExtension = nullptr;
  2479. }
  2480. for (uint32_t x=numUsed; x < rdfDescriptor->ExtensionCount; ++x)
  2481. rdfDescriptor->Extensions[x] = nullptr;
  2482. rdfDescriptor->ExtensionCount = numUsed;
  2483. }
  2484. lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me));
  2485. }
  2486. // ----------------------------------------------------------------------------------------------------------------
  2487. // Set Plugin UIs
  2488. {
  2489. #ifdef CARLA_OS_LINUX
  2490. const bool hasMODGui = lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr;
  2491. #else
  2492. const bool hasMODGui = false;
  2493. #endif
  2494. Lilv::UIs lilvUIs(lilvPlugin.get_uis());
  2495. const uint numUIs = lilvUIs.size() + (hasMODGui ? 1 : 0);
  2496. if (numUIs > 0)
  2497. {
  2498. rdfDescriptor->UIs = new LV2_RDF_UI[numUIs];
  2499. uint numUsed = 0;
  2500. LILV_FOREACH(uis, it, lilvUIs)
  2501. {
  2502. CARLA_SAFE_ASSERT_BREAK(numUsed < numUIs);
  2503. Lilv::UI lilvUI(lilvUIs.get(it));
  2504. LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[numUsed++]);
  2505. lv2World.load_resource(lilvUI.get_uri());
  2506. // ----------------------------------------------------------------------------------------------------
  2507. // Set UI Type
  2508. /**/ if (lilvUI.is_a(lv2World.ui_gtk2))
  2509. rdfUI->Type = LV2_UI_GTK2;
  2510. else if (lilvUI.is_a(lv2World.ui_gtk3))
  2511. rdfUI->Type = LV2_UI_GTK3;
  2512. else if (lilvUI.is_a(lv2World.ui_qt4))
  2513. rdfUI->Type = LV2_UI_QT4;
  2514. else if (lilvUI.is_a(lv2World.ui_qt5))
  2515. rdfUI->Type = LV2_UI_QT5;
  2516. else if (lilvUI.is_a(lv2World.ui_cocoa))
  2517. rdfUI->Type = LV2_UI_COCOA;
  2518. else if (lilvUI.is_a(lv2World.ui_windows))
  2519. rdfUI->Type = LV2_UI_WINDOWS;
  2520. else if (lilvUI.is_a(lv2World.ui_x11))
  2521. rdfUI->Type = LV2_UI_X11;
  2522. else if (lilvUI.is_a(lv2World.ui_external))
  2523. rdfUI->Type = LV2_UI_EXTERNAL;
  2524. else if (lilvUI.is_a(lv2World.ui_externalOld))
  2525. rdfUI->Type = LV2_UI_OLD_EXTERNAL;
  2526. else if (lilvUI.is_a(lv2World.ui))
  2527. rdfUI->Type = LV2_UI_NONE;
  2528. else
  2529. carla_stderr("lv2_rdf_new(\"%s\") - UI '%s' is of unknown type", uri, lilvUI.get_uri().as_uri());
  2530. // ----------------------------------------------------------------------------------------------------
  2531. // Set UI Information
  2532. {
  2533. if (const char* const uiURI = lilvUI.get_uri().as_uri())
  2534. rdfUI->URI = carla_strdup(uiURI);
  2535. if (const char* const uiBinary = lilvUI.get_binary_uri().as_string())
  2536. rdfUI->Binary = carla_strdup_free(lilv_file_uri_parse(uiBinary, nullptr));
  2537. if (const char* const uiBundle = lilvUI.get_bundle_uri().as_string())
  2538. rdfUI->Bundle = carla_strdup_free(lilv_file_uri_parse(uiBundle, nullptr));
  2539. }
  2540. // ----------------------------------------------------------------------------------------------------
  2541. // Set UI Features
  2542. {
  2543. Lilv::Nodes lilvFeatureNodes(lilvUI.get_supported_features());
  2544. if (const uint numFeatures = lilvFeatureNodes.size())
  2545. {
  2546. Lilv::Nodes lilvFeatureNodesR(lilvUI.get_required_features());
  2547. rdfUI->Features = new LV2_RDF_Feature[numFeatures];
  2548. uint numUsed2 = 0;
  2549. LILV_FOREACH(nodes, it2, lilvFeatureNodes)
  2550. {
  2551. CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2 < numFeatures, numUsed2, numFeatures);
  2552. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it2));
  2553. LV2_RDF_Feature* const rdfFeature(&rdfUI->Features[numUsed2++]);
  2554. rdfFeature->Required = lilvFeatureNodesR.contains(lilvFeatureNode);
  2555. if (const char* const featureURI = lilvFeatureNode.as_uri())
  2556. rdfFeature->URI = carla_strdup(featureURI);
  2557. else
  2558. rdfFeature->URI = nullptr;
  2559. }
  2560. rdfUI->FeatureCount = numUsed2;
  2561. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodesR.me));
  2562. }
  2563. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  2564. }
  2565. // ----------------------------------------------------------------------------------------------------
  2566. // Set UI Extensions
  2567. {
  2568. Lilv::Nodes lilvExtensionDataNodes(lilvUI.get_extension_data());
  2569. if (const uint numExtensions = lilvExtensionDataNodes.size())
  2570. {
  2571. rdfUI->Extensions = new LV2_URI[numExtensions];
  2572. uint numUsed2 = 0;
  2573. LILV_FOREACH(nodes, it2, lilvExtensionDataNodes)
  2574. {
  2575. CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2 < numExtensions, numUsed2, numExtensions);
  2576. Lilv::Node lilvExtensionDataNode(lilvExtensionDataNodes.get(it2));
  2577. LV2_URI* const rdfExtension(&rdfUI->Extensions[numUsed2++]);
  2578. if (lilvExtensionDataNode.is_uri())
  2579. {
  2580. if (const char* const extURI = lilvExtensionDataNode.as_uri())
  2581. {
  2582. *rdfExtension = carla_strdup(extURI);
  2583. continue;
  2584. }
  2585. }
  2586. *rdfExtension = nullptr;
  2587. }
  2588. for (uint x2=numUsed2; x2 < rdfUI->ExtensionCount; ++x2)
  2589. rdfUI->Extensions[x2] = nullptr;
  2590. rdfUI->ExtensionCount = numUsed2;
  2591. }
  2592. lilv_nodes_free(const_cast<LilvNodes*>(lilvExtensionDataNodes.me));
  2593. }
  2594. // ----------------------------------------------------------------------------------------------------
  2595. // Set UI Port Notifications
  2596. {
  2597. Lilv::Nodes portNotifNodes(lv2World.find_nodes(lilvUI.get_uri(), lv2World.ui_portNotif.me, nullptr));
  2598. if (const uint portNotifCount = portNotifNodes.size())
  2599. {
  2600. rdfUI->PortNotificationCount = portNotifCount;
  2601. rdfUI->PortNotifications = new LV2_RDF_UI_PortNotification[portNotifCount];
  2602. uint numUsed2 = 0;
  2603. LILV_FOREACH(nodes, it2, portNotifNodes)
  2604. {
  2605. CARLA_SAFE_ASSERT_UINT2_BREAK(numUsed2 < portNotifCount, numUsed2, portNotifCount);
  2606. Lilv::Node portNotifNode(portNotifNodes.get(it2));
  2607. LV2_RDF_UI_PortNotification* const rdfPortNotif(&rdfUI->PortNotifications[numUsed2++]);
  2608. LilvNode* const protocolNode = lilv_world_get(lv2World.me, portNotifNode,
  2609. lv2World.ui_protocol.me, nullptr);
  2610. if (protocolNode != nullptr)
  2611. {
  2612. CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_uri(protocolNode));
  2613. const char* const protocol = lilv_node_as_uri(protocolNode);
  2614. CARLA_SAFE_ASSERT_CONTINUE(protocol != nullptr && protocol[0] != '\0');
  2615. /**/ if (std::strcmp(protocol, LV2_UI__floatProtocol) == 0)
  2616. rdfPortNotif->Protocol = LV2_UI_PORT_PROTOCOL_FLOAT;
  2617. else if (std::strcmp(protocol, LV2_UI__peakProtocol) == 0)
  2618. rdfPortNotif->Protocol = LV2_UI_PORT_PROTOCOL_PEAK;
  2619. }
  2620. else
  2621. {
  2622. rdfPortNotif->Protocol = LV2_UI_PORT_PROTOCOL_FLOAT;
  2623. }
  2624. /**/ if (LilvNode* const symbolNode = lilv_world_get(lv2World.me, portNotifNode,
  2625. lv2World.symbol.me, nullptr))
  2626. {
  2627. CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_string(symbolNode));
  2628. const char* const symbol = lilv_node_as_string(symbolNode);
  2629. CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr && symbol[0] != '\0');
  2630. rdfPortNotif->Symbol = carla_strdup(symbol);
  2631. lilv_node_free(symbolNode);
  2632. }
  2633. else if (LilvNode* const indexNode = lilv_world_get(lv2World.me, portNotifNode,
  2634. lv2World.ui_portIndex.me, nullptr))
  2635. {
  2636. CARLA_SAFE_ASSERT_CONTINUE(lilv_node_is_int(indexNode));
  2637. const int index = lilv_node_as_int(indexNode);
  2638. CARLA_SAFE_ASSERT_CONTINUE(index >= 0);
  2639. rdfPortNotif->Index = static_cast<uint32_t>(index);
  2640. lilv_node_free(indexNode);
  2641. }
  2642. lilv_node_free(protocolNode);
  2643. }
  2644. }
  2645. lilv_nodes_free(const_cast<LilvNodes*>(portNotifNodes.me));
  2646. }
  2647. }
  2648. for (; hasMODGui;)
  2649. {
  2650. CARLA_SAFE_ASSERT_BREAK(numUsed == numUIs-1);
  2651. LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[numUsed++]);
  2652. // -------------------------------------------------------
  2653. // Set UI Type
  2654. rdfUI->Type = LV2_UI_MOD;
  2655. // -------------------------------------------------------
  2656. // Set UI Information
  2657. if (const char* const resDir = lilvPlugin.get_modgui_resources_directory().as_uri())
  2658. rdfUI->URI = carla_strdup_free(lilv_file_uri_parse(resDir, nullptr));
  2659. if (rdfDescriptor->Bundle != nullptr)
  2660. rdfUI->Bundle = carla_strdup(rdfDescriptor->Bundle);
  2661. break;
  2662. }
  2663. rdfDescriptor->UICount = numUsed;
  2664. }
  2665. lilv_nodes_free(const_cast<LilvNodes*>(lilvUIs.me));
  2666. }
  2667. return rdfDescriptor;
  2668. }
  2669. // --------------------------------------------------------------------------------------------------------------------
  2670. // Check if we support a plugin port
  2671. static inline
  2672. bool is_lv2_port_supported(const LV2_Property types) noexcept
  2673. {
  2674. if (LV2_IS_PORT_CONTROL(types))
  2675. return true;
  2676. if (LV2_IS_PORT_AUDIO(types))
  2677. return true;
  2678. if (LV2_IS_PORT_CV(types))
  2679. return true;
  2680. if (LV2_IS_PORT_ATOM_SEQUENCE(types))
  2681. return true;
  2682. if (LV2_IS_PORT_EVENT(types))
  2683. return true;
  2684. if (LV2_IS_PORT_MIDI_LL(types))
  2685. return true;
  2686. return false;
  2687. }
  2688. // --------------------------------------------------------------------------------------------------------------------
  2689. // Check if we support a plugin feature
  2690. static inline
  2691. bool is_lv2_feature_supported(const LV2_URI uri) noexcept
  2692. {
  2693. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', false);
  2694. if (std::strcmp(uri, LV2_BUF_SIZE__boundedBlockLength) == 0)
  2695. return true;
  2696. if (std::strcmp(uri, LV2_BUF_SIZE__fixedBlockLength) == 0)
  2697. return true;
  2698. if (std::strcmp(uri, LV2_BUF_SIZE__powerOf2BlockLength) == 0)
  2699. return true;
  2700. if (std::strcmp(uri, LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI) == 0)
  2701. return true;
  2702. if (std::strcmp(uri, LV2_CORE__hardRTCapable) == 0)
  2703. return true;
  2704. if (std::strcmp(uri, LV2_CORE__inPlaceBroken) == 0)
  2705. return true;
  2706. if (std::strcmp(uri, LV2_CORE__isLive) == 0)
  2707. return true;
  2708. if (std::strcmp(uri, LV2_EVENT_URI) == 0)
  2709. return true;
  2710. if (std::strcmp(uri, LV2_INLINEDISPLAY__queue_draw) == 0)
  2711. return true;
  2712. if (std::strcmp(uri, LV2_LOG__log) == 0)
  2713. return true;
  2714. if (std::strcmp(uri, LV2_OPTIONS__options) == 0)
  2715. return true;
  2716. if (std::strcmp(uri, LV2_PROGRAMS__Host) == 0)
  2717. return true;
  2718. if (std::strcmp(uri, LV2_RESIZE_PORT__resize) == 0)
  2719. return true;
  2720. if (std::strcmp(uri, LV2_RTSAFE_MEMORY_POOL__Pool) == 0)
  2721. return true;
  2722. if (std::strcmp(uri, LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI) == 0)
  2723. return true;
  2724. if (std::strcmp(uri, LV2_STATE__freePath) == 0)
  2725. return true;
  2726. if (std::strcmp(uri, LV2_STATE__loadDefaultState) == 0)
  2727. return true;
  2728. if (std::strcmp(uri, LV2_STATE__makePath) == 0)
  2729. return true;
  2730. if (std::strcmp(uri, LV2_STATE__mapPath) == 0)
  2731. return true;
  2732. if (std::strcmp(uri, LV2_STATE__threadSafeRestore) == 0)
  2733. return true;
  2734. if (std::strcmp(uri, LV2_PORT_PROPS__supportsStrictBounds) == 0)
  2735. return true;
  2736. if (std::strcmp(uri, LV2_URI_MAP_URI) == 0)
  2737. return true;
  2738. if (std::strcmp(uri, LV2_URID__map) == 0)
  2739. return true;
  2740. if (std::strcmp(uri, LV2_URID__unmap) == 0)
  2741. return true;
  2742. if (std::strcmp(uri, LV2_WORKER__schedule) == 0)
  2743. return true;
  2744. return false;
  2745. }
  2746. // --------------------------------------------------------------------------------------------------------------------
  2747. // Check if we support a plugin or UI feature
  2748. static inline
  2749. bool is_lv2_ui_feature_supported(const LV2_URI uri) noexcept
  2750. {
  2751. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', false);
  2752. if (is_lv2_feature_supported(uri))
  2753. return true;
  2754. #ifndef BUILD_BRIDGE_UI
  2755. if (std::strcmp(uri, LV2_DATA_ACCESS_URI) == 0)
  2756. return true;
  2757. if (std::strcmp(uri, LV2_INSTANCE_ACCESS_URI) == 0)
  2758. return true;
  2759. #endif
  2760. if (std::strcmp(uri, LV2_UI__fixedSize) == 0)
  2761. return true;
  2762. if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
  2763. return true;
  2764. if (std::strcmp(uri, LV2_UI__makeResident) == 0)
  2765. return true;
  2766. if (std::strcmp(uri, LV2_UI__makeSONameResident) == 0)
  2767. return true;
  2768. if (std::strcmp(uri, LV2_UI__noUserResize) == 0)
  2769. return true;
  2770. if (std::strcmp(uri, LV2_UI__parent) == 0)
  2771. return true;
  2772. if (std::strcmp(uri, LV2_UI__portMap) == 0)
  2773. return true;
  2774. if (std::strcmp(uri, LV2_UI__portSubscribe) == 0)
  2775. return true;
  2776. if (std::strcmp(uri, LV2_UI__requestValue) == 0)
  2777. return true;
  2778. if (std::strcmp(uri, LV2_UI__resize) == 0)
  2779. return true;
  2780. if (std::strcmp(uri, LV2_UI__touch) == 0)
  2781. return true;
  2782. if (std::strcmp(uri, LV2_EXTERNAL_UI__Widget) == 0)
  2783. return true;
  2784. if (std::strcmp(uri, LV2_EXTERNAL_UI_DEPRECATED_URI) == 0)
  2785. return true;
  2786. return false;
  2787. }
  2788. // --------------------------------------------------------------------------------------------------------------------
  2789. #endif // CARLA_LV2_UTILS_HPP_INCLUDED