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.

CarlaBridgeUI-LV2.cpp 44KB

11 years ago
11 years ago
11 years ago
11 years ago
10 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
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
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
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. /*
  2. * Carla Bridge UI, LV2 version
  3. * Copyright (C) 2011-2014 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. #include "CarlaBridgeClient.hpp"
  18. #include "CarlaBase64Utils.hpp"
  19. #include "CarlaLv2Utils.hpp"
  20. #include "CarlaMIDI.h"
  21. #include "LinkedList.hpp"
  22. #include "juce_core.h"
  23. #define URI_CARLA_FRONTEND_WIN_ID "http://kxstudio.sf.net/ns/carla/frontendWinId"
  24. #define URI_CARLA_WORKER "http://kxstudio.sf.net/ns/carla/worker"
  25. using juce::File;
  26. CARLA_BRIDGE_START_NAMESPACE
  27. // -----------------------------------------------------
  28. static uint32_t gBufferSize = 1024;
  29. static double gSampleRate = 44100.0;
  30. // Maximum default buffer size
  31. const unsigned int MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000
  32. // LV2 URI Map Ids
  33. const uint32_t CARLA_URI_MAP_ID_NULL = 0;
  34. const uint32_t CARLA_URI_MAP_ID_ATOM_BLANK = 1;
  35. const uint32_t CARLA_URI_MAP_ID_ATOM_BOOL = 2;
  36. const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 3;
  37. const uint32_t CARLA_URI_MAP_ID_ATOM_DOUBLE = 4;
  38. const uint32_t CARLA_URI_MAP_ID_ATOM_EVENT = 5;
  39. const uint32_t CARLA_URI_MAP_ID_ATOM_FLOAT = 6;
  40. const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 7;
  41. const uint32_t CARLA_URI_MAP_ID_ATOM_LITERAL = 8;
  42. const uint32_t CARLA_URI_MAP_ID_ATOM_LONG = 9;
  43. const uint32_t CARLA_URI_MAP_ID_ATOM_NUMBER = 10;
  44. const uint32_t CARLA_URI_MAP_ID_ATOM_OBJECT = 11;
  45. const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 12;
  46. const uint32_t CARLA_URI_MAP_ID_ATOM_PROPERTY = 13;
  47. const uint32_t CARLA_URI_MAP_ID_ATOM_RESOURCE = 14;
  48. const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 15;
  49. const uint32_t CARLA_URI_MAP_ID_ATOM_SOUND = 16;
  50. const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 17;
  51. const uint32_t CARLA_URI_MAP_ID_ATOM_TUPLE = 18;
  52. const uint32_t CARLA_URI_MAP_ID_ATOM_URI = 19;
  53. const uint32_t CARLA_URI_MAP_ID_ATOM_URID = 20;
  54. const uint32_t CARLA_URI_MAP_ID_ATOM_VECTOR = 21;
  55. const uint32_t CARLA_URI_MAP_ID_ATOM_WORKER = 22; // custom
  56. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 23;
  57. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 24;
  58. const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 25;
  59. const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 26;
  60. const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 27;
  61. const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 28;
  62. const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 29;
  63. const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 30;
  64. const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 31;
  65. const uint32_t CARLA_URI_MAP_ID_TIME_POSITION = 32; // base type
  66. const uint32_t CARLA_URI_MAP_ID_TIME_BAR = 33; // values
  67. const uint32_t CARLA_URI_MAP_ID_TIME_BAR_BEAT = 34;
  68. const uint32_t CARLA_URI_MAP_ID_TIME_BEAT = 35;
  69. const uint32_t CARLA_URI_MAP_ID_TIME_BEAT_UNIT = 36;
  70. const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR = 37;
  71. const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE = 38;
  72. const uint32_t CARLA_URI_MAP_ID_TIME_FRAME = 39;
  73. const uint32_t CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND = 40;
  74. const uint32_t CARLA_URI_MAP_ID_TIME_SPEED = 41;
  75. const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 42;
  76. const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 43;
  77. const uint32_t CARLA_URI_MAP_ID_FRONTEND_WIN_ID = 44;
  78. const uint32_t CARLA_URI_MAP_ID_COUNT = 45;
  79. // LV2 Feature Ids
  80. const uint32_t kFeatureIdLogs = 0;
  81. const uint32_t kFeatureIdOptions = 1;
  82. const uint32_t kFeatureIdPrograms = 2;
  83. const uint32_t kFeatureIdStateMakePath = 3;
  84. const uint32_t kFeatureIdStateMapPath = 4;
  85. const uint32_t kFeatureIdUriMap = 5;
  86. const uint32_t kFeatureIdUridMap = 6;
  87. const uint32_t kFeatureIdUridUnmap = 7;
  88. const uint32_t kFeatureIdUiIdleInterface = 8;
  89. const uint32_t kFeatureIdUiFixedSize = 9;
  90. const uint32_t kFeatureIdUiMakeResident = 10;
  91. const uint32_t kFeatureIdUiNoUserResize = 11;
  92. const uint32_t kFeatureIdUiParent = 12;
  93. const uint32_t kFeatureIdUiPortMap = 13;
  94. const uint32_t kFeatureIdUiPortSubscribe = 14;
  95. const uint32_t kFeatureIdUiResize = 15;
  96. const uint32_t kFeatureIdUiTouch = 16;
  97. const uint32_t kFeatureCount = 17;
  98. // -------------------------------------------------------------------------
  99. struct Lv2PluginOptions {
  100. enum OptIndex {
  101. MaxBlockLenth = 0,
  102. MinBlockLenth,
  103. SequenceSize,
  104. SampleRate,
  105. FrontendWinId,
  106. Null
  107. };
  108. int maxBufferSize;
  109. int minBufferSize;
  110. int sequenceSize;
  111. double sampleRate;
  112. int64_t frontendWinId;
  113. LV2_Options_Option opts[6];
  114. Lv2PluginOptions()
  115. : maxBufferSize(0),
  116. minBufferSize(0),
  117. sequenceSize(MAX_DEFAULT_BUFFER_SIZE),
  118. sampleRate(0.0),
  119. frontendWinId(0)
  120. {
  121. LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]);
  122. optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE;
  123. optMaxBlockLenth.subject = 0;
  124. optMaxBlockLenth.key = CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  125. optMaxBlockLenth.size = sizeof(int);
  126. optMaxBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  127. optMaxBlockLenth.value = &maxBufferSize;
  128. LV2_Options_Option& optMinBlockLenth(opts[MinBlockLenth]);
  129. optMinBlockLenth.context = LV2_OPTIONS_INSTANCE;
  130. optMinBlockLenth.subject = 0;
  131. optMinBlockLenth.key = CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  132. optMinBlockLenth.size = sizeof(int);
  133. optMinBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  134. optMinBlockLenth.value = &minBufferSize;
  135. LV2_Options_Option& optSequenceSize(opts[SequenceSize]);
  136. optSequenceSize.context = LV2_OPTIONS_INSTANCE;
  137. optSequenceSize.subject = 0;
  138. optSequenceSize.key = CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  139. optSequenceSize.size = sizeof(int);
  140. optSequenceSize.type = CARLA_URI_MAP_ID_ATOM_INT;
  141. optSequenceSize.value = &sequenceSize;
  142. LV2_Options_Option& optSampleRate(opts[SampleRate]);
  143. optSampleRate.context = LV2_OPTIONS_INSTANCE;
  144. optSampleRate.subject = 0;
  145. optSampleRate.key = CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  146. optSampleRate.size = sizeof(double);
  147. optSampleRate.type = CARLA_URI_MAP_ID_ATOM_DOUBLE;
  148. optSampleRate.value = &sampleRate;
  149. LV2_Options_Option& optFrontendWinId(opts[FrontendWinId]);
  150. optFrontendWinId.context = LV2_OPTIONS_INSTANCE;
  151. optFrontendWinId.subject = 0;
  152. optFrontendWinId.key = CARLA_URI_MAP_ID_FRONTEND_WIN_ID;
  153. optFrontendWinId.size = sizeof(int64_t);
  154. optFrontendWinId.type = CARLA_URI_MAP_ID_ATOM_LONG;
  155. optFrontendWinId.value = &frontendWinId;
  156. LV2_Options_Option& optNull(opts[Null]);
  157. optNull.context = LV2_OPTIONS_INSTANCE;
  158. optNull.subject = 0;
  159. optNull.key = CARLA_URI_MAP_ID_NULL;
  160. optNull.size = 0;
  161. optNull.type = CARLA_URI_MAP_ID_NULL;
  162. optNull.value = nullptr;
  163. }
  164. };
  165. // -------------------------------------------------------------------------
  166. class CarlaLv2Client : public CarlaBridgeClient
  167. {
  168. public:
  169. CarlaLv2Client(const char* const uiTitle)
  170. : CarlaBridgeClient(uiTitle),
  171. fHandle(nullptr),
  172. fWidget(nullptr),
  173. fDescriptor(nullptr),
  174. fRdfDescriptor(nullptr),
  175. fRdfUiDescriptor(nullptr),
  176. fIsReady(false),
  177. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  178. fIsResizable(false)
  179. #else
  180. fIsResizable(true)
  181. #endif
  182. {
  183. carla_fill<LV2_Feature*>(fFeatures, nullptr, kFeatureCount+1);
  184. for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; ++i)
  185. fCustomURIDs.append(nullptr);
  186. // ---------------------------------------------------------------
  187. // initialize options
  188. fOptions.minBufferSize = gBufferSize;
  189. fOptions.maxBufferSize = gBufferSize;
  190. fOptions.sampleRate = gSampleRate;
  191. // ---------------------------------------------------------------
  192. // initialize features (part 1)
  193. LV2_Log_Log* const logFt = new LV2_Log_Log;
  194. logFt->handle = this;
  195. logFt->printf = carla_lv2_log_printf;
  196. logFt->vprintf = carla_lv2_log_vprintf;
  197. LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
  198. stateMakePathFt->handle = this;
  199. stateMakePathFt->path = carla_lv2_state_make_path;
  200. LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
  201. stateMapPathFt->handle = this;
  202. stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path;
  203. stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path;
  204. LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
  205. programsFt->handle = this;
  206. programsFt->program_changed = carla_lv2_program_changed;
  207. LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
  208. uriMapFt->callback_data = this;
  209. uriMapFt->uri_to_id = carla_lv2_uri_to_id;
  210. LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
  211. uridMapFt->handle = this;
  212. uridMapFt->map = carla_lv2_urid_map;
  213. LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
  214. uridUnmapFt->handle = this;
  215. uridUnmapFt->unmap = carla_lv2_urid_unmap;
  216. LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
  217. uiPortMapFt->handle = this;
  218. uiPortMapFt->port_index = carla_lv2_ui_port_map;
  219. LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
  220. uiResizeFt->handle = this;
  221. uiResizeFt->ui_resize = carla_lv2_ui_resize;
  222. // ---------------------------------------------------------------
  223. // initialize features (part 2)
  224. for (uint32_t i=0; i < kFeatureCount; ++i)
  225. fFeatures[i] = new LV2_Feature;
  226. fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
  227. fFeatures[kFeatureIdLogs]->data = logFt;
  228. fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
  229. fFeatures[kFeatureIdOptions]->data = fOptions.opts;
  230. fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
  231. fFeatures[kFeatureIdPrograms]->data = programsFt;
  232. fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
  233. fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
  234. fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
  235. fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
  236. fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
  237. fFeatures[kFeatureIdUriMap]->data = uriMapFt;
  238. fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
  239. fFeatures[kFeatureIdUridMap]->data = uridMapFt;
  240. fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
  241. fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
  242. fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
  243. fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
  244. fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
  245. fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
  246. fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
  247. fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
  248. fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
  249. fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
  250. fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
  251. fFeatures[kFeatureIdUiParent]->data = nullptr;
  252. fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
  253. fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
  254. fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
  255. fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
  256. fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
  257. fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
  258. fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
  259. fFeatures[kFeatureIdUiTouch]->data = nullptr;
  260. }
  261. ~CarlaLv2Client() override
  262. {
  263. if (fRdfDescriptor != nullptr)
  264. delete fRdfDescriptor;
  265. delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
  266. delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
  267. delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
  268. delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
  269. delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
  270. delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
  271. delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
  272. delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
  273. delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
  274. for (uint32_t i=0; i < kFeatureCount; ++i)
  275. {
  276. if (fFeatures[i] != nullptr)
  277. {
  278. delete fFeatures[i];
  279. fFeatures[i] = nullptr;
  280. }
  281. }
  282. for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
  283. {
  284. const char* const uri(it.getValue());
  285. if (uri != nullptr)
  286. delete[] uri;
  287. }
  288. fCustomURIDs.clear();
  289. }
  290. // ---------------------------------------------------------------------
  291. // ui initialization
  292. bool uiInit(const char* pluginURI, const char* uiURI) override
  293. {
  294. // -----------------------------------------------------------------
  295. // init
  296. CarlaBridgeClient::uiInit(pluginURI, uiURI);
  297. // -----------------------------------------------------------------
  298. // get plugin from lv2_rdf (lilv)
  299. fRdfDescriptor = lv2_rdf_new(pluginURI, true);
  300. if (fRdfDescriptor == nullptr)
  301. return false;
  302. // -----------------------------------------------------------------
  303. // find requested UI
  304. for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
  305. {
  306. if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
  307. {
  308. fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
  309. break;
  310. }
  311. }
  312. if (fRdfUiDescriptor == nullptr)
  313. {
  314. carla_stderr("Failed to find requested UI");
  315. return false;
  316. }
  317. // -----------------------------------------------------------------
  318. // open DLL
  319. if (! uiLibOpen(fRdfUiDescriptor->Binary))
  320. {
  321. carla_stderr("Failed to load UI binary, error was:\n%s", uiLibError());
  322. return false;
  323. }
  324. // -----------------------------------------------------------------
  325. // get DLL main entry
  326. const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)uiLibSymbol("lv2ui_descriptor");
  327. if (ui_descFn == nullptr)
  328. return false;
  329. // -----------------------------------------------------------
  330. // get descriptor that matches URI
  331. uint32_t i = 0;
  332. while ((fDescriptor = ui_descFn(i++)))
  333. {
  334. if (std::strcmp(fDescriptor->URI, uiURI) == 0)
  335. break;
  336. }
  337. if (fDescriptor == nullptr)
  338. {
  339. carla_stderr("Failed to find UI descriptor");
  340. return false;
  341. }
  342. // -----------------------------------------------------------
  343. // initialize UI
  344. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  345. fFeatures[kFeatureIdUiParent]->data = getContainerId();
  346. #endif
  347. fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures);
  348. if (fHandle == nullptr)
  349. {
  350. carla_stderr("Failed to init UI");
  351. return false;
  352. }
  353. // -----------------------------------------------------------
  354. // check if not resizable
  355. for (uint32_t i=0; i < fRdfUiDescriptor->FeatureCount && fIsResizable; ++i)
  356. {
  357. if (std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__fixedSize) == 0 || std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
  358. {
  359. fIsResizable = false;
  360. break;
  361. }
  362. }
  363. // -----------------------------------------------------------
  364. // check for known extensions
  365. if (fDescriptor->extension_data != nullptr)
  366. {
  367. fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
  368. fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
  369. fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
  370. // check if invalid
  371. if (fExt.programs != nullptr && fExt.programs->select_program == nullptr)
  372. fExt.programs = nullptr;
  373. if (fExt.idle != nullptr && fExt.idle->idle == nullptr)
  374. fExt.idle = nullptr;
  375. }
  376. return true;
  377. }
  378. void uiIdle() override
  379. {
  380. if (fHandle != nullptr && fExt.idle != nullptr)
  381. fExt.idle->idle(fHandle);
  382. }
  383. void uiClose() override
  384. {
  385. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr)
  386. {
  387. fDescriptor->cleanup(fHandle);
  388. fHandle = nullptr;
  389. }
  390. CarlaBridgeClient::uiClose();
  391. uiLibClose();
  392. }
  393. // ---------------------------------------------------------------------
  394. // ui management
  395. void* getWidget() const override
  396. {
  397. return fWidget;
  398. }
  399. bool isResizable() const override
  400. {
  401. return fIsResizable;
  402. }
  403. // ---------------------------------------------------------------------
  404. // ui processing
  405. void setParameter(const int32_t rindex, const float value) override
  406. {
  407. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  408. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  409. if (fDescriptor->port_event == nullptr)
  410. return;
  411. fDescriptor->port_event(fHandle, rindex, sizeof(float), 0, &value);
  412. }
  413. void setProgram(const uint32_t) override
  414. {
  415. }
  416. void setMidiProgram(const uint32_t bank, const uint32_t program) override
  417. {
  418. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  419. if (fExt.programs == nullptr)
  420. return;
  421. fExt.programs->select_program(fHandle, bank, program);
  422. }
  423. void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  424. {
  425. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  426. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  427. if (fDescriptor->port_event == nullptr)
  428. return;
  429. LV2_Atom_MidiEvent midiEv;
  430. midiEv.event.time.frames = 0;
  431. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  432. midiEv.event.body.size = 3;
  433. midiEv.data[0] = MIDI_STATUS_NOTE_ON + channel;
  434. midiEv.data[1] = note;
  435. midiEv.data[2] = velo;
  436. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  437. }
  438. void noteOff(const uint8_t channel, const uint8_t note) override
  439. {
  440. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  441. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  442. if (fDescriptor->port_event == nullptr)
  443. return;
  444. LV2_Atom_MidiEvent midiEv;
  445. midiEv.event.time.frames = 0;
  446. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  447. midiEv.event.body.size = 3;
  448. midiEv.data[0] = MIDI_STATUS_NOTE_OFF + channel;
  449. midiEv.data[1] = note;
  450. midiEv.data[2] = 0;
  451. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  452. }
  453. // ---------------------------------------------------------------------
  454. void waitForOscURIs()
  455. {
  456. sendOscUpdate();
  457. for (;;)
  458. {
  459. if (fIsReady || ! oscIdle())
  460. return;
  461. }
  462. }
  463. // ---------------------------------------------------------------------
  464. LV2_URID getCustomURID(const char* const uri)
  465. {
  466. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
  467. carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
  468. LV2_URID urid = CARLA_URI_MAP_ID_NULL;
  469. for (size_t i=0; i < fCustomURIDs.count(); ++i)
  470. {
  471. const char* const thisUri(fCustomURIDs.getAt(i, nullptr));
  472. if (thisUri != nullptr && std::strcmp(thisUri, uri) == 0)
  473. {
  474. urid = i;
  475. break;
  476. }
  477. }
  478. if (urid == CARLA_URI_MAP_ID_NULL)
  479. {
  480. urid = fCustomURIDs.count();
  481. fCustomURIDs.append(carla_strdup(uri));
  482. }
  483. if (isOscControlRegistered())
  484. sendOscLv2UridMap(urid, uri);
  485. return urid;
  486. }
  487. const char* getCustomURIString(const LV2_URID urid) const noexcept
  488. {
  489. CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr);
  490. CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.count(), nullptr);
  491. carla_debug("CarlaLv2Client::getCustomURIString(%i)", urid);
  492. return fCustomURIDs.getAt(urid, nullptr);
  493. }
  494. // ---------------------------------------------------------------------
  495. void handleProgramChanged(const int32_t /*index*/)
  496. {
  497. if (isOscControlRegistered())
  498. sendOscConfigure("reloadprograms", "");
  499. }
  500. uint32_t handleUiPortMap(const char* const symbol)
  501. {
  502. CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
  503. carla_debug("CarlaLv2Client::handleUiPortMap(\"%s\")", symbol);
  504. for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
  505. {
  506. if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
  507. return i;
  508. }
  509. return LV2UI_INVALID_PORT_INDEX;
  510. }
  511. int handleUiResize(const int width, const int height)
  512. {
  513. CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
  514. CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
  515. carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height);
  516. toolkitResize(width, height);
  517. return 0;
  518. }
  519. void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  520. {
  521. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
  522. CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
  523. carla_debug("CarlaLv2Client::handleUiWrite(%i, %i, %i, %p)", portIndex, bufferSize, format, buffer);
  524. if (format == 0)
  525. {
  526. CARLA_ASSERT(buffer != nullptr);
  527. CARLA_ASSERT(bufferSize == sizeof(float));
  528. if (bufferSize != sizeof(float))
  529. return;
  530. if (buffer == nullptr || bufferSize != sizeof(float))
  531. return;
  532. const float value(*(const float*)buffer);
  533. if (isOscControlRegistered())
  534. sendOscControl(portIndex, value);
  535. }
  536. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  537. {
  538. CARLA_ASSERT(bufferSize != 0);
  539. CARLA_ASSERT(buffer != nullptr);
  540. if (bufferSize == 0 || buffer == nullptr)
  541. return;
  542. if (isOscControlRegistered())
  543. sendOscLv2AtomTransfer(portIndex, CarlaString::asBase64(buffer, bufferSize).buffer());
  544. }
  545. else
  546. {
  547. carla_stdout("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format", portIndex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
  548. }
  549. }
  550. // ---------------------------------------------------------------------
  551. void handleAtomTransfer(const uint32_t portIndex, const LV2_Atom* const atom)
  552. {
  553. CARLA_ASSERT(atom != nullptr);
  554. carla_debug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
  555. if (atom != nullptr && fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  556. fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  557. }
  558. void handleUridMap(const LV2_URID urid, const char* const uri)
  559. {
  560. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
  561. carla_stdout("CarlaLv2Client::handleUridMap(%i, \"%s\")", urid, uri);
  562. if (urid == CARLA_URI_MAP_ID_NULL)
  563. {
  564. CARLA_SAFE_ASSERT_RETURN(std::strcmp(uri, "Complete") == 0,);
  565. carla_stdout("URID map from host complete");
  566. fIsReady = true;
  567. return;
  568. }
  569. const uint32_t uridCount(fCustomURIDs.count());
  570. if (urid < uridCount)
  571. {
  572. if (const char* const ourURI = carla_lv2_urid_unmap(this, urid))
  573. {
  574. if (std::strcmp(ourURI, uri) != 0)
  575. carla_stderr2("UI :: wrong URI '%s' vs '%s'", ourURI, uri);
  576. }
  577. else
  578. {
  579. uint32_t i=0;
  580. for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
  581. {
  582. if (i != urid)
  583. continue;
  584. CARLA_SAFE_ASSERT(it.getValue() == nullptr);
  585. it.setValue(carla_strdup(uri));
  586. break;
  587. }
  588. }
  589. }
  590. else if (urid > uridCount)
  591. {
  592. for (uint32_t i=uridCount; i < urid; ++i)
  593. fCustomURIDs.append(nullptr);
  594. }
  595. else
  596. {
  597. fCustomURIDs.append(carla_strdup(uri));
  598. }
  599. }
  600. private:
  601. LV2UI_Handle fHandle;
  602. LV2UI_Widget fWidget;
  603. LV2_Feature* fFeatures[kFeatureCount+1];
  604. const LV2UI_Descriptor* fDescriptor;
  605. const LV2_RDF_Descriptor* fRdfDescriptor;
  606. const LV2_RDF_UI* fRdfUiDescriptor;
  607. Lv2PluginOptions fOptions;
  608. bool fIsReady;
  609. bool fIsResizable;
  610. LinkedList<const char*> fCustomURIDs;
  611. struct Extensions {
  612. const LV2_Options_Interface* options;
  613. const LV2UI_Idle_Interface* idle;
  614. const LV2_Programs_UI_Interface* programs;
  615. Extensions()
  616. : options(nullptr),
  617. idle(nullptr),
  618. programs(nullptr) {}
  619. } fExt;
  620. // -------------------------------------------------------------------
  621. // Logs Feature
  622. static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
  623. {
  624. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  625. CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
  626. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  627. #ifndef DEBUG
  628. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  629. return 0;
  630. #endif
  631. va_list args;
  632. va_start(args, fmt);
  633. const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
  634. va_end(args);
  635. return ret;
  636. }
  637. static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
  638. {
  639. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  640. CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
  641. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  642. #ifndef DEBUG
  643. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  644. return 0;
  645. #endif
  646. int ret = 0;
  647. switch (type)
  648. {
  649. case CARLA_URI_MAP_ID_LOG_ERROR:
  650. std::fprintf(stderr, "\x1b[31m");
  651. ret = std::vfprintf(stderr, fmt, ap);
  652. std::fprintf(stderr, "\x1b[0m");
  653. break;
  654. case CARLA_URI_MAP_ID_LOG_NOTE:
  655. ret = std::vfprintf(stdout, fmt, ap);
  656. break;
  657. case CARLA_URI_MAP_ID_LOG_TRACE:
  658. #ifdef DEBUG
  659. std::fprintf(stdout, "\x1b[30;1m");
  660. ret = std::vfprintf(stdout, fmt, ap);
  661. std::fprintf(stdout, "\x1b[0m");
  662. #endif
  663. break;
  664. case CARLA_URI_MAP_ID_LOG_WARNING:
  665. ret = std::vfprintf(stderr, fmt, ap);
  666. break;
  667. default:
  668. break;
  669. }
  670. return ret;
  671. }
  672. // -------------------------------------------------------------------
  673. // Programs Feature
  674. static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
  675. {
  676. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  677. carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
  678. ((CarlaLv2Client*)handle)->handleProgramChanged(index);
  679. }
  680. // -------------------------------------------------------------------
  681. // State Feature
  682. static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
  683. {
  684. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  685. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
  686. carla_debug("carla_lv2_state_make_path(%p, \"%s\")", handle, path);
  687. File(path).createDirectory();
  688. return strdup(path);
  689. }
  690. static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
  691. {
  692. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  693. CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
  694. carla_debug("carla_lv2_state_map_abstract_path(%p, \"%s\")", handle, absolute_path);
  695. return strdup(File(absolute_path).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
  696. }
  697. static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
  698. {
  699. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  700. CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
  701. carla_debug("carla_lv2_state_map_absolute_path(%p, \"%s\")", handle, abstract_path);
  702. return strdup(File(abstract_path).getFullPathName().toRawUTF8());
  703. }
  704. // -------------------------------------------------------------------
  705. // URI-Map Feature
  706. static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
  707. {
  708. carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
  709. return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
  710. // unused
  711. (void)map;
  712. }
  713. // -------------------------------------------------------------------
  714. // URID Feature
  715. static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
  716. {
  717. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, CARLA_URI_MAP_ID_NULL);
  718. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
  719. carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
  720. // Atom types
  721. if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
  722. return CARLA_URI_MAP_ID_ATOM_BLANK;
  723. if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
  724. return CARLA_URI_MAP_ID_ATOM_BOOL;
  725. if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
  726. return CARLA_URI_MAP_ID_ATOM_CHUNK;
  727. if (std::strcmp(uri, LV2_ATOM__Double) == 0)
  728. return CARLA_URI_MAP_ID_ATOM_DOUBLE;
  729. if (std::strcmp(uri, LV2_ATOM__Event) == 0)
  730. return CARLA_URI_MAP_ID_ATOM_EVENT;
  731. if (std::strcmp(uri, LV2_ATOM__Float) == 0)
  732. return CARLA_URI_MAP_ID_ATOM_FLOAT;
  733. if (std::strcmp(uri, LV2_ATOM__Int) == 0)
  734. return CARLA_URI_MAP_ID_ATOM_INT;
  735. if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
  736. return CARLA_URI_MAP_ID_ATOM_LITERAL;
  737. if (std::strcmp(uri, LV2_ATOM__Long) == 0)
  738. return CARLA_URI_MAP_ID_ATOM_LONG;
  739. if (std::strcmp(uri, LV2_ATOM__Number) == 0)
  740. return CARLA_URI_MAP_ID_ATOM_NUMBER;
  741. if (std::strcmp(uri, LV2_ATOM__Object) == 0)
  742. return CARLA_URI_MAP_ID_ATOM_OBJECT;
  743. if (std::strcmp(uri, LV2_ATOM__Path) == 0)
  744. return CARLA_URI_MAP_ID_ATOM_PATH;
  745. if (std::strcmp(uri, LV2_ATOM__Property) == 0)
  746. return CARLA_URI_MAP_ID_ATOM_PROPERTY;
  747. if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
  748. return CARLA_URI_MAP_ID_ATOM_RESOURCE;
  749. if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
  750. return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
  751. if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
  752. return CARLA_URI_MAP_ID_ATOM_SOUND;
  753. if (std::strcmp(uri, LV2_ATOM__String) == 0)
  754. return CARLA_URI_MAP_ID_ATOM_STRING;
  755. if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
  756. return CARLA_URI_MAP_ID_ATOM_TUPLE;
  757. if (std::strcmp(uri, LV2_ATOM__URI) == 0)
  758. return CARLA_URI_MAP_ID_ATOM_URI;
  759. if (std::strcmp(uri, LV2_ATOM__URID) == 0)
  760. return CARLA_URI_MAP_ID_ATOM_URID;
  761. if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
  762. return CARLA_URI_MAP_ID_ATOM_VECTOR;
  763. if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  764. return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
  765. if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  766. return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
  767. // BufSize types
  768. if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
  769. return CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  770. if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
  771. return CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  772. if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
  773. return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  774. // Log types
  775. if (std::strcmp(uri, LV2_LOG__Error) == 0)
  776. return CARLA_URI_MAP_ID_LOG_ERROR;
  777. if (std::strcmp(uri, LV2_LOG__Note) == 0)
  778. return CARLA_URI_MAP_ID_LOG_NOTE;
  779. if (std::strcmp(uri, LV2_LOG__Trace) == 0)
  780. return CARLA_URI_MAP_ID_LOG_TRACE;
  781. if (std::strcmp(uri, LV2_LOG__Warning) == 0)
  782. return CARLA_URI_MAP_ID_LOG_WARNING;
  783. // Time types
  784. if (std::strcmp(uri, LV2_TIME__Position) == 0)
  785. return CARLA_URI_MAP_ID_TIME_POSITION;
  786. if (std::strcmp(uri, LV2_TIME__bar) == 0)
  787. return CARLA_URI_MAP_ID_TIME_BAR;
  788. if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
  789. return CARLA_URI_MAP_ID_TIME_BAR_BEAT;
  790. if (std::strcmp(uri, LV2_TIME__beat) == 0)
  791. return CARLA_URI_MAP_ID_TIME_BEAT;
  792. if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
  793. return CARLA_URI_MAP_ID_TIME_BEAT_UNIT;
  794. if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
  795. return CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR;
  796. if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
  797. return CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE;
  798. if (std::strcmp(uri, LV2_TIME__frame) == 0)
  799. return CARLA_URI_MAP_ID_TIME_FRAME;
  800. if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
  801. return CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND;
  802. if (std::strcmp(uri, LV2_TIME__speed) == 0)
  803. return CARLA_URI_MAP_ID_TIME_SPEED;
  804. // Others
  805. if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  806. return CARLA_URI_MAP_ID_MIDI_EVENT;
  807. if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
  808. return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  809. // Custom
  810. if (std::strcmp(uri, URI_CARLA_FRONTEND_WIN_ID) == 0)
  811. return CARLA_URI_MAP_ID_FRONTEND_WIN_ID;
  812. if (std::strcmp(uri, URI_CARLA_WORKER) == 0)
  813. return CARLA_URI_MAP_ID_ATOM_WORKER;
  814. // Custom types
  815. return ((CarlaLv2Client*)handle)->getCustomURID(uri);
  816. }
  817. static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  818. {
  819. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  820. CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr);
  821. carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
  822. // Atom types
  823. if (urid == CARLA_URI_MAP_ID_ATOM_BLANK)
  824. return LV2_ATOM__Blank;
  825. if (urid == CARLA_URI_MAP_ID_ATOM_BOOL)
  826. return LV2_ATOM__Bool;
  827. if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
  828. return LV2_ATOM__Chunk;
  829. if (urid == CARLA_URI_MAP_ID_ATOM_DOUBLE)
  830. return LV2_ATOM__Double;
  831. if (urid == CARLA_URI_MAP_ID_ATOM_EVENT)
  832. return LV2_ATOM__Event;
  833. if (urid == CARLA_URI_MAP_ID_ATOM_FLOAT)
  834. return LV2_ATOM__Float;
  835. if (urid == CARLA_URI_MAP_ID_ATOM_INT)
  836. return LV2_ATOM__Int;
  837. if (urid == CARLA_URI_MAP_ID_ATOM_LITERAL)
  838. return LV2_ATOM__Literal;
  839. if (urid == CARLA_URI_MAP_ID_ATOM_LONG)
  840. return LV2_ATOM__Long;
  841. if (urid == CARLA_URI_MAP_ID_ATOM_NUMBER)
  842. return LV2_ATOM__Number;
  843. if (urid == CARLA_URI_MAP_ID_ATOM_OBJECT)
  844. return LV2_ATOM__Object;
  845. if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
  846. return LV2_ATOM__Path;
  847. if (urid == CARLA_URI_MAP_ID_ATOM_PROPERTY)
  848. return LV2_ATOM__Property;
  849. if (urid == CARLA_URI_MAP_ID_ATOM_RESOURCE)
  850. return LV2_ATOM__Resource;
  851. if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
  852. return LV2_ATOM__Sequence;
  853. if (urid == CARLA_URI_MAP_ID_ATOM_SOUND)
  854. return LV2_ATOM__Sound;
  855. if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
  856. return LV2_ATOM__String;
  857. if (urid == CARLA_URI_MAP_ID_ATOM_TUPLE)
  858. return LV2_ATOM__Tuple;
  859. if (urid == CARLA_URI_MAP_ID_ATOM_URI)
  860. return LV2_ATOM__URI;
  861. if (urid == CARLA_URI_MAP_ID_ATOM_URID)
  862. return LV2_ATOM__URID;
  863. if (urid == CARLA_URI_MAP_ID_ATOM_VECTOR)
  864. return LV2_ATOM__Vector;
  865. if (urid == CARLA_URI_MAP_ID_ATOM_WORKER)
  866. return URI_CARLA_WORKER; // custom
  867. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  868. return LV2_ATOM__atomTransfer;
  869. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  870. return LV2_ATOM__eventTransfer;
  871. // BufSize types
  872. if (urid == CARLA_URI_MAP_ID_BUF_MAX_LENGTH)
  873. return LV2_BUF_SIZE__maxBlockLength;
  874. if (urid == CARLA_URI_MAP_ID_BUF_MIN_LENGTH)
  875. return LV2_BUF_SIZE__minBlockLength;
  876. if (urid == CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE)
  877. return LV2_BUF_SIZE__sequenceSize;
  878. // Log types
  879. if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
  880. return LV2_LOG__Error;
  881. if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
  882. return LV2_LOG__Note;
  883. if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
  884. return LV2_LOG__Trace;
  885. if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
  886. return LV2_LOG__Warning;
  887. // Time types
  888. if (urid == CARLA_URI_MAP_ID_TIME_POSITION)
  889. return LV2_TIME__Position;
  890. if (urid == CARLA_URI_MAP_ID_TIME_BAR)
  891. return LV2_TIME__bar;
  892. if (urid == CARLA_URI_MAP_ID_TIME_BAR_BEAT)
  893. return LV2_TIME__barBeat;
  894. if (urid == CARLA_URI_MAP_ID_TIME_BEAT)
  895. return LV2_TIME__beat;
  896. if (urid == CARLA_URI_MAP_ID_TIME_BEAT_UNIT)
  897. return LV2_TIME__beatUnit;
  898. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR)
  899. return LV2_TIME__beatsPerBar;
  900. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE)
  901. return LV2_TIME__beatsPerMinute;
  902. if (urid == CARLA_URI_MAP_ID_TIME_FRAME)
  903. return LV2_TIME__frame;
  904. if (urid == CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND)
  905. return LV2_TIME__framesPerSecond;
  906. if (urid == CARLA_URI_MAP_ID_TIME_SPEED)
  907. return LV2_TIME__speed;
  908. // Others
  909. if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
  910. return LV2_MIDI__MidiEvent;
  911. if (urid == CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE)
  912. return LV2_PARAMETERS__sampleRate;
  913. if (urid == CARLA_URI_MAP_ID_FRONTEND_WIN_ID)
  914. return URI_CARLA_FRONTEND_WIN_ID;
  915. // Custom types
  916. return ((CarlaLv2Client*)handle)->getCustomURIString(urid);
  917. }
  918. // -------------------------------------------------------------------
  919. // UI Port-Map Feature
  920. static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
  921. {
  922. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
  923. carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
  924. return ((CarlaLv2Client*)handle)->handleUiPortMap(symbol);
  925. }
  926. // -------------------------------------------------------------------
  927. // UI Resize Feature
  928. static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
  929. {
  930. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
  931. carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  932. return ((CarlaLv2Client*)handle)->handleUiResize(width, height);
  933. }
  934. // -------------------------------------------------------------------
  935. // UI Extension
  936. static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
  937. {
  938. CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
  939. carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  940. ((CarlaLv2Client*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
  941. }
  942. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client)
  943. };
  944. #define lv2ClientPtr ((CarlaLv2Client*)kClient)
  945. int CarlaBridgeOsc::handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  946. {
  947. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  948. carla_debug("CarlaBridgeOsc::handleMsgLv2AtomTransfer()");
  949. if (kClient == nullptr)
  950. return 1;
  951. const int32_t portIndex = argv[0]->i;
  952. const char* const atomBuf = (const char*)&argv[1]->s;
  953. if (portIndex < 0)
  954. return 0;
  955. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(atomBuf));
  956. CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, 0);
  957. const LV2_Atom* const atom((const LV2_Atom*)chunk.data());
  958. lv2ClientPtr->handleAtomTransfer(portIndex, atom);
  959. return 0;
  960. }
  961. int CarlaBridgeOsc::handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  962. {
  963. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  964. carla_debug("CarlaBridgeOsc::handleMsgLv2UridMap()");
  965. if (kClient == nullptr)
  966. return 1;
  967. const int32_t urid = argv[0]->i;
  968. const char* const uri = (const char*)&argv[1]->s;
  969. if (urid < 0)
  970. return 0;
  971. lv2ClientPtr->handleUridMap(urid, uri);
  972. return 0;
  973. }
  974. #undef lv2ClientPtr
  975. CARLA_BRIDGE_END_NAMESPACE
  976. int main(int argc, char* argv[])
  977. {
  978. CARLA_BRIDGE_USE_NAMESPACE
  979. if (argc != 5)
  980. {
  981. carla_stderr("usage: %s <osc-url|\"null\"> <plugin-uri> <ui-uri> <ui-title>", argv[0]);
  982. return 1;
  983. }
  984. const char* oscUrl = argv[1];
  985. const char* pluginURI = argv[2];
  986. const char* uiURI = argv[3];
  987. const char* uiTitle = argv[4];
  988. const bool useOsc(std::strcmp(oscUrl, "null") != 0);
  989. // try to get sampleRate value
  990. if (const char* const sampleRateStr = getenv("CARLA_SAMPLE_RATE"))
  991. gSampleRate = atof(sampleRateStr);
  992. // Init LV2 client
  993. CarlaLv2Client client(uiTitle);
  994. // Init OSC
  995. if (useOsc)
  996. {
  997. client.oscInit(oscUrl);
  998. client.waitForOscURIs();
  999. }
  1000. // Load UI
  1001. int ret;
  1002. if (client.uiInit(pluginURI, uiURI))
  1003. {
  1004. client.toolkitExec(!useOsc);
  1005. ret = 0;
  1006. }
  1007. else
  1008. {
  1009. ret = 1;
  1010. }
  1011. // Close OSC
  1012. if (useOsc)
  1013. client.oscClose();
  1014. // Close LV2 client
  1015. client.uiClose();
  1016. return ret;
  1017. }