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

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