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

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  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. #ifdef BRIDGE_LV2
  18. #include "CarlaBridgeClient.hpp"
  19. #include "CarlaLv2Utils.hpp"
  20. #include "CarlaMIDI.h"
  21. extern "C" {
  22. #include "rtmempool/rtmempool-lv2.h"
  23. }
  24. #include <vector>
  25. #include <QtCore/QDir>
  26. Lv2WorldClass lv2World;
  27. CARLA_BRIDGE_START_NAMESPACE
  28. // -------------------------------------------------------------------------
  29. // fake values
  30. uint32_t bufferSize = 512;
  31. double sampleRate = 44100.0;
  32. // static max values
  33. const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000
  34. // feature ids
  35. const uint32_t lv2_feature_id_bufsize_bounded = 0;
  36. const uint32_t lv2_feature_id_bufsize_fixed = 1;
  37. const uint32_t lv2_feature_id_bufsize_powerof2 = 2;
  38. const uint32_t lv2_feature_id_event = 3;
  39. const uint32_t lv2_feature_id_logs = 4;
  40. const uint32_t lv2_feature_id_options = 5;
  41. const uint32_t lv2_feature_id_programs = 6;
  42. const uint32_t lv2_feature_id_rtmempool = 7;
  43. const uint32_t lv2_feature_id_state_make_path = 8;
  44. const uint32_t lv2_feature_id_state_map_path = 9;
  45. const uint32_t lv2_feature_id_strict_bounds = 10;
  46. const uint32_t lv2_feature_id_uri_map = 11;
  47. const uint32_t lv2_feature_id_urid_map = 12;
  48. const uint32_t lv2_feature_id_urid_unmap = 13;
  49. const uint32_t lv2_feature_id_ui_parent = 14;
  50. const uint32_t lv2_feature_id_ui_port_map = 15;
  51. const uint32_t lv2_feature_id_ui_resize = 16;
  52. const uint32_t lv2_feature_count = 17;
  53. // pre-set uri[d] map ids
  54. const uint32_t CARLA_URI_MAP_ID_NULL = 0;
  55. const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1;
  56. const uint32_t CARLA_URI_MAP_ID_ATOM_DOUBLE = 2;
  57. const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 3;
  58. const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 4;
  59. const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 5;
  60. const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 6;
  61. const uint32_t CARLA_URI_MAP_ID_ATOM_WORKER = 7;
  62. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 8;
  63. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 9;
  64. const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 10;
  65. const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 11;
  66. const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 12;
  67. const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 13;
  68. const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 14;
  69. const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 15;
  70. const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 16;
  71. const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 17;
  72. const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 18;
  73. const uint32_t CARLA_URI_MAP_ID_COUNT = 19;
  74. // -------------------------------------------------------------------------
  75. struct Lv2PluginOptions {
  76. uint32_t eventSize;
  77. uint32_t bufferSize;
  78. double sampleRate;
  79. LV2_Options_Option oNull;
  80. LV2_Options_Option oMaxBlockLenth;
  81. LV2_Options_Option oMinBlockLenth;
  82. LV2_Options_Option oSequenceSize;
  83. LV2_Options_Option oSampleRate;
  84. Lv2PluginOptions()
  85. : eventSize(MAX_EVENT_BUFFER),
  86. bufferSize(0),
  87. sampleRate(0.0) {}
  88. };
  89. Lv2PluginOptions lv2Options;
  90. class CarlaLv2Client : public CarlaBridgeClient
  91. {
  92. public:
  93. CarlaLv2Client(const char* const uiTitle)
  94. : CarlaBridgeClient(uiTitle)
  95. {
  96. handle = nullptr;
  97. widget = nullptr;
  98. descriptor = nullptr;
  99. rdf_descriptor = nullptr;
  100. rdf_ui_descriptor = nullptr;
  101. programs = nullptr;
  102. #ifdef BRIDGE_LV2_X11
  103. m_resizable = false;
  104. #else
  105. m_resizable = true;
  106. #endif
  107. for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; i++)
  108. customURIDs.push_back(nullptr);
  109. for (uint32_t i=0; i < lv2_feature_count+1; i++)
  110. features[i] = nullptr;
  111. // -----------------------------------------------------------------
  112. // initialize options
  113. lv2Options.bufferSize = bufferSize;
  114. lv2Options.sampleRate = sampleRate;
  115. lv2Options.oNull.key = CARLA_URI_MAP_ID_NULL;
  116. lv2Options.oNull.size = 0;
  117. lv2Options.oNull.type = CARLA_URI_MAP_ID_NULL;
  118. lv2Options.oNull.value = nullptr;
  119. lv2Options.oMaxBlockLenth.key = CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  120. lv2Options.oMaxBlockLenth.size = sizeof(uint32_t);
  121. lv2Options.oMaxBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  122. lv2Options.oMaxBlockLenth.value = &lv2Options.bufferSize;
  123. lv2Options.oMinBlockLenth.key = CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  124. lv2Options.oMinBlockLenth.size = sizeof(uint32_t);
  125. lv2Options.oMinBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  126. lv2Options.oMinBlockLenth.value = &lv2Options.bufferSize;
  127. lv2Options.oSequenceSize.key = CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  128. lv2Options.oSequenceSize.size = sizeof(uint32_t);
  129. lv2Options.oSequenceSize.type = CARLA_URI_MAP_ID_ATOM_INT;
  130. lv2Options.oSequenceSize.value = &lv2Options.eventSize;
  131. lv2Options.oSampleRate.key = CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  132. lv2Options.oSampleRate.size = sizeof(double);
  133. lv2Options.oSampleRate.type = CARLA_URI_MAP_ID_ATOM_DOUBLE;
  134. lv2Options.oSampleRate.value = &lv2Options.sampleRate;
  135. // -----------------------------------------------------------------
  136. // initialize features
  137. LV2_Event_Feature* const eventFt = new LV2_Event_Feature;
  138. eventFt->callback_data = this;
  139. eventFt->lv2_event_ref = carla_lv2_event_ref;
  140. eventFt->lv2_event_unref = carla_lv2_event_unref;
  141. LV2_Log_Log* const logFt = new LV2_Log_Log;
  142. logFt->handle = this;
  143. logFt->printf = carla_lv2_log_printf;
  144. logFt->vprintf = carla_lv2_log_vprintf;
  145. LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
  146. programsFt->handle = this;
  147. programsFt->program_changed = carla_lv2_program_changed;
  148. LV2_RtMemPool_Pool* const rtMemPoolFt = new LV2_RtMemPool_Pool;
  149. lv2_rtmempool_init(rtMemPoolFt);
  150. LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
  151. stateMakePathFt->handle = this;
  152. stateMakePathFt->path = carla_lv2_state_make_path;
  153. LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
  154. stateMapPathFt->handle = this;
  155. stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path;
  156. stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path;
  157. LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
  158. uriMapFt->callback_data = this;
  159. uriMapFt->uri_to_id = carla_lv2_uri_to_id;
  160. LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
  161. uridMapFt->handle = this;
  162. uridMapFt->map = carla_lv2_urid_map;
  163. LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
  164. uridUnmapFt->handle = this;
  165. uridUnmapFt->unmap = carla_lv2_urid_unmap;
  166. LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
  167. uiPortMapFt->handle = this;
  168. uiPortMapFt->port_index = carla_lv2_ui_port_map;
  169. LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
  170. uiResizeFt->handle = this;
  171. uiResizeFt->ui_resize = carla_lv2_ui_resize;
  172. LV2_Options_Option* const optionsFt = new LV2_Options_Option [5];
  173. optionsFt[0] = lv2Options.oMaxBlockLenth;
  174. optionsFt[1] = lv2Options.oMinBlockLenth;
  175. optionsFt[2] = lv2Options.oSequenceSize;
  176. optionsFt[3] = lv2Options.oSampleRate;
  177. optionsFt[4] = lv2Options.oNull;
  178. features[lv2_feature_id_bufsize_bounded] = new LV2_Feature;
  179. features[lv2_feature_id_bufsize_bounded]->URI = LV2_BUF_SIZE__boundedBlockLength;
  180. features[lv2_feature_id_bufsize_bounded]->data = nullptr;
  181. features[lv2_feature_id_bufsize_fixed] = new LV2_Feature;
  182. features[lv2_feature_id_bufsize_fixed]->URI = LV2_BUF_SIZE__fixedBlockLength;
  183. features[lv2_feature_id_bufsize_fixed]->data = nullptr;
  184. features[lv2_feature_id_bufsize_powerof2] = new LV2_Feature;
  185. features[lv2_feature_id_bufsize_powerof2]->URI = LV2_BUF_SIZE__powerOf2BlockLength;
  186. features[lv2_feature_id_bufsize_powerof2]->data = nullptr;
  187. features[lv2_feature_id_event] = new LV2_Feature;
  188. features[lv2_feature_id_event]->URI = LV2_EVENT_URI;
  189. features[lv2_feature_id_event]->data = eventFt;
  190. features[lv2_feature_id_logs] = new LV2_Feature;
  191. features[lv2_feature_id_logs]->URI = LV2_LOG__log;
  192. features[lv2_feature_id_logs]->data = logFt;
  193. features[lv2_feature_id_options] = new LV2_Feature;
  194. features[lv2_feature_id_options]->URI = LV2_OPTIONS__options;
  195. features[lv2_feature_id_options]->data = optionsFt;
  196. features[lv2_feature_id_programs] = new LV2_Feature;
  197. features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host;
  198. features[lv2_feature_id_programs]->data = programsFt;
  199. features[lv2_feature_id_rtmempool] = new LV2_Feature;
  200. features[lv2_feature_id_rtmempool]->URI = LV2_RTSAFE_MEMORY_POOL__Pool;
  201. features[lv2_feature_id_rtmempool]->data = rtMemPoolFt;
  202. features[lv2_feature_id_state_make_path] = new LV2_Feature;
  203. features[lv2_feature_id_state_make_path]->URI = LV2_STATE__makePath;
  204. features[lv2_feature_id_state_make_path]->data = stateMakePathFt;
  205. features[lv2_feature_id_state_map_path] = new LV2_Feature;
  206. features[lv2_feature_id_state_map_path]->URI = LV2_STATE__mapPath;
  207. features[lv2_feature_id_state_map_path]->data = stateMapPathFt;
  208. features[lv2_feature_id_strict_bounds] = new LV2_Feature;
  209. features[lv2_feature_id_strict_bounds]->URI = LV2_PORT_PROPS__supportsStrictBounds;
  210. features[lv2_feature_id_strict_bounds]->data = nullptr;
  211. features[lv2_feature_id_uri_map] = new LV2_Feature;
  212. features[lv2_feature_id_uri_map]->URI = LV2_URI_MAP_URI;
  213. features[lv2_feature_id_uri_map]->data = uriMapFt;
  214. features[lv2_feature_id_urid_map] = new LV2_Feature;
  215. features[lv2_feature_id_urid_map]->URI = LV2_URID__map;
  216. features[lv2_feature_id_urid_map]->data = uridMapFt;
  217. features[lv2_feature_id_urid_unmap] = new LV2_Feature;
  218. features[lv2_feature_id_urid_unmap]->URI = LV2_URID__unmap;
  219. features[lv2_feature_id_urid_unmap]->data = uridUnmapFt;
  220. features[lv2_feature_id_ui_parent] = new LV2_Feature;
  221. features[lv2_feature_id_ui_parent]->URI = LV2_UI__parent;
  222. #ifdef BRIDGE_LV2_X11
  223. features[lv2_feature_id_ui_parent]->data = getContainerId();
  224. #else
  225. features[lv2_feature_id_ui_parent]->data = nullptr;
  226. #endif
  227. features[lv2_feature_id_ui_port_map] = new LV2_Feature;
  228. features[lv2_feature_id_ui_port_map]->URI = LV2_UI__portMap;
  229. features[lv2_feature_id_ui_port_map]->data = uiPortMapFt;
  230. features[lv2_feature_id_ui_resize] = new LV2_Feature;
  231. features[lv2_feature_id_ui_resize]->URI = LV2_UI__resize;
  232. features[lv2_feature_id_ui_resize]->data = uiResizeFt;
  233. }
  234. ~CarlaLv2Client()
  235. {
  236. if (rdf_descriptor)
  237. delete rdf_descriptor;
  238. const LV2_Options_Option* const options = (const LV2_Options_Option*)features[lv2_feature_id_options]->data;
  239. delete[] options;
  240. delete (LV2_Event_Feature*)features[lv2_feature_id_event]->data;
  241. delete (LV2_Log_Log*)features[lv2_feature_id_logs]->data;
  242. delete (LV2_Programs_Host*)features[lv2_feature_id_programs]->data;
  243. delete (LV2_RtMemPool_Pool*)features[lv2_feature_id_rtmempool]->data;
  244. delete (LV2_State_Make_Path*)features[lv2_feature_id_state_make_path]->data;
  245. delete (LV2_State_Map_Path*)features[lv2_feature_id_state_map_path]->data;
  246. delete (LV2_URI_Map_Feature*)features[lv2_feature_id_uri_map]->data;
  247. delete (LV2_URID_Map*)features[lv2_feature_id_urid_map]->data;
  248. delete (LV2_URID_Unmap*)features[lv2_feature_id_urid_unmap]->data;
  249. delete (LV2UI_Port_Map*)features[lv2_feature_id_ui_port_map]->data;
  250. delete (LV2UI_Resize*)features[lv2_feature_id_ui_resize]->data;
  251. for (uint32_t i=0; i < lv2_feature_count; i++)
  252. {
  253. if (features[i])
  254. delete features[i];
  255. }
  256. for (size_t i=0; i < customURIDs.size(); i++)
  257. {
  258. if (customURIDs[i])
  259. free((void*)customURIDs[i]);
  260. }
  261. customURIDs.clear();
  262. }
  263. // ---------------------------------------------------------------------
  264. // ui initialization
  265. bool uiInit(const char* pluginURI, const char* uiURI)
  266. {
  267. // -----------------------------------------------------------------
  268. // init
  269. CarlaBridgeClient::uiInit(pluginURI, uiURI);
  270. // -----------------------------------------------------------------
  271. // get plugin from lv2_rdf (lilv)
  272. lv2World.init();
  273. rdf_descriptor = lv2_rdf_new(pluginURI);
  274. if (! rdf_descriptor)
  275. return false;
  276. // -----------------------------------------------------------------
  277. // find requested UI
  278. for (uint32_t i=0; i < rdf_descriptor->UICount; i++)
  279. {
  280. if (std::strcmp(rdf_descriptor->UIs[i].URI, uiURI) == 0)
  281. {
  282. rdf_ui_descriptor = &rdf_descriptor->UIs[i];
  283. break;
  284. }
  285. }
  286. if (! rdf_ui_descriptor)
  287. return false;
  288. // -----------------------------------------------------------------
  289. // open DLL
  290. if (! uiLibOpen(rdf_ui_descriptor->Binary))
  291. return false;
  292. // -----------------------------------------------------------------
  293. // get DLL main entry
  294. const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)uiLibSymbol("lv2ui_descriptor");
  295. if (! ui_descFn)
  296. return false;
  297. // -----------------------------------------------------------
  298. // get descriptor that matches URI
  299. uint32_t i = 0;
  300. while ((descriptor = ui_descFn(i++)))
  301. {
  302. if (std::strcmp(descriptor->URI, uiURI) == 0)
  303. break;
  304. }
  305. if (! descriptor)
  306. return false;
  307. // -----------------------------------------------------------
  308. // initialize UI
  309. handle = descriptor->instantiate(descriptor, pluginURI, rdf_ui_descriptor->Bundle, carla_lv2_ui_write_function, this, &widget, features);
  310. if (! handle)
  311. return false;
  312. // -----------------------------------------------------------
  313. // check if not resizable
  314. #ifndef BRIDGE_LV2_X11
  315. for (uint32_t i=0; i < rdf_ui_descriptor->FeatureCount; i++)
  316. {
  317. if (std::strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__fixedSize) == 0 || std::strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
  318. {
  319. m_resizable = false;
  320. break;
  321. }
  322. }
  323. #endif
  324. // -----------------------------------------------------------
  325. // check for known extensions
  326. for (uint32_t i=0; descriptor->extension_data && i < rdf_ui_descriptor->ExtensionCount; i++)
  327. {
  328. if (std::strcmp(rdf_ui_descriptor->Extensions[i], LV2_PROGRAMS__UIInterface) == 0)
  329. {
  330. programs = (LV2_Programs_UI_Interface*)descriptor->extension_data(LV2_PROGRAMS__UIInterface);
  331. if (programs && ! programs->select_program)
  332. // invalid
  333. programs = nullptr;
  334. break;
  335. }
  336. }
  337. return true;
  338. }
  339. void uiClose()
  340. {
  341. CarlaBridgeClient::uiClose();
  342. if (handle && descriptor && descriptor->cleanup)
  343. descriptor->cleanup(handle);
  344. uiLibClose();
  345. }
  346. // ---------------------------------------------------------------------
  347. // ui management
  348. void* getWidget() const
  349. {
  350. return widget;
  351. }
  352. bool isResizable() const
  353. {
  354. return m_resizable;
  355. }
  356. bool needsReparent() const
  357. {
  358. #ifdef BRIDGE_LV2_X11
  359. return true;
  360. #else
  361. return false;
  362. #endif
  363. }
  364. // ---------------------------------------------------------------------
  365. // processing
  366. void setParameter(const int32_t rindex, const float value)
  367. {
  368. CARLA_ASSERT(handle && descriptor);
  369. if (handle && descriptor && descriptor->port_event)
  370. {
  371. float fvalue = value;
  372. descriptor->port_event(handle, rindex, sizeof(float), 0, &fvalue);
  373. }
  374. }
  375. void setProgram(const uint32_t)
  376. {
  377. }
  378. void setMidiProgram(const uint32_t bank, const uint32_t program)
  379. {
  380. CARLA_ASSERT(handle);
  381. if (handle && programs)
  382. programs->select_program(handle, bank, program);
  383. }
  384. void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  385. {
  386. CARLA_ASSERT(handle && descriptor);
  387. if (handle && descriptor && descriptor->port_event)
  388. {
  389. LV2_Atom_MidiEvent midiEv;
  390. midiEv.event.time.frames = 0;
  391. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  392. midiEv.event.body.size = 3;
  393. midiEv.data[0] = MIDI_STATUS_NOTE_ON + channel;
  394. midiEv.data[1] = note;
  395. midiEv.data[2] = velo;
  396. descriptor->port_event(handle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  397. }
  398. }
  399. void noteOff(const uint8_t channel, const uint8_t note)
  400. {
  401. CARLA_ASSERT(handle && descriptor);
  402. if (handle && descriptor && descriptor->port_event)
  403. {
  404. LV2_Atom_MidiEvent midiEv;
  405. midiEv.event.time.frames = 0;
  406. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  407. midiEv.event.body.size = 3;
  408. midiEv.data[0] = MIDI_STATUS_NOTE_OFF + channel;
  409. midiEv.data[1] = note;
  410. midiEv.data[2] = 0;
  411. descriptor->port_event(handle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  412. }
  413. }
  414. // ---------------------------------------------------------------------
  415. uint32_t getCustomURID(const char* const uri)
  416. {
  417. qDebug("CarlaLv2Client::getCustomURID(%s)", uri);
  418. CARLA_ASSERT(uri);
  419. if (! uri)
  420. return CARLA_URI_MAP_ID_NULL;
  421. for (size_t i=0; i < customURIDs.size(); i++)
  422. {
  423. if (customURIDs[i] && std::strcmp(customURIDs[i], uri) == 0)
  424. return i;
  425. }
  426. customURIDs.push_back(strdup(uri));
  427. return customURIDs.size()-1;
  428. }
  429. const char* getCustomURIString(const LV2_URID urid) const
  430. {
  431. qDebug("CarlaLv2Client::getCustomURIString(%i)", urid);
  432. CARLA_ASSERT(urid > CARLA_URI_MAP_ID_NULL);
  433. if (urid == CARLA_URI_MAP_ID_NULL)
  434. return nullptr;
  435. if (urid < customURIDs.size())
  436. return customURIDs[urid];
  437. return nullptr;
  438. }
  439. // ---------------------------------------------------------------------
  440. void handleTransferAtom(const int32_t portIndex, const LV2_Atom* const atom)
  441. {
  442. qDebug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
  443. CARLA_ASSERT(portIndex >= 0);
  444. CARLA_ASSERT(atom);
  445. if (atom && handle && descriptor && descriptor->port_event)
  446. descriptor->port_event(handle, portIndex, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, atom);
  447. }
  448. void handleTransferEvent(const int32_t portIndex, const LV2_Atom* const atom)
  449. {
  450. qDebug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
  451. CARLA_ASSERT(portIndex >= 0);
  452. CARLA_ASSERT(atom);
  453. if (atom && handle && descriptor && descriptor->port_event)
  454. descriptor->port_event(handle, portIndex, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  455. #if 0
  456. if (handle && descriptor && descriptor->port_event)
  457. {
  458. LV2_URID_Map* const URID_Map = (LV2_URID_Map*)features[lv2_feature_id_urid_map]->data;
  459. const LV2_URID uridPatchSet = getCustomURID(LV2_PATCH__Set);
  460. const LV2_URID uridPatchBody = getCustomURID(LV2_PATCH__body);
  461. Sratom* sratom = sratom_new(URID_Map);
  462. SerdChunk chunk = { nullptr, 0 };
  463. LV2_Atom_Forge forge;
  464. lv2_atom_forge_init(&forge, URID_Map);
  465. lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &chunk);
  466. LV2_Atom_Forge_Frame refFrame, bodyFrame;
  467. LV2_Atom_Forge_Ref ref = lv2_atom_forge_blank(&forge, &refFrame, 1, uridPatchSet);
  468. lv2_atom_forge_property_head(&forge, uridPatchBody, CARLA_URI_MAP_ID_NULL);
  469. lv2_atom_forge_blank(&forge, &bodyFrame, 2, CARLA_URI_MAP_ID_NULL);
  470. //lv2_atom_forge_property_head(&forge, getCustomURID(key), CARLA_URI_MAP_ID_NULL);
  471. if (std::strcmp(type, "string") == 0)
  472. lv2_atom_forge_string(&forge, value, std::strlen(value));
  473. else if (std::strcmp(type, "path") == 0)
  474. lv2_atom_forge_path(&forge, value, std::strlen(value));
  475. else if (std::strcmp(type, "chunk") == 0)
  476. lv2_atom_forge_literal(&forge, value, std::strlen(value), CARLA_URI_MAP_ID_ATOM_CHUNK, CARLA_URI_MAP_ID_NULL);
  477. //else
  478. // lv2_atom_forge_literal(&forge, value, std::strlen(value), getCustomURID(key), CARLA_URI_MAP_ID_NULL);
  479. lv2_atom_forge_pop(&forge, &bodyFrame);
  480. lv2_atom_forge_pop(&forge, &refFrame);
  481. const LV2_Atom* const atom = lv2_atom_forge_deref(&forge, ref);
  482. descriptor->port_event(handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  483. free((void*)chunk.buf);
  484. sratom_free(sratom);
  485. }
  486. #endif
  487. }
  488. // ---------------------------------------------------------------------
  489. void handleProgramChanged(int32_t /*index*/)
  490. {
  491. if (isOscControlRegistered())
  492. sendOscConfigure("reloadprograms", "");
  493. }
  494. uint32_t handleUiPortMap(const char* const symbol)
  495. {
  496. CARLA_ASSERT(symbol);
  497. if (! symbol)
  498. return LV2UI_INVALID_PORT_INDEX;
  499. for (uint32_t i=0; i < rdf_descriptor->PortCount; i++)
  500. {
  501. if (std::strcmp(rdf_descriptor->Ports[i].Symbol, symbol) == 0)
  502. return i;
  503. }
  504. return LV2UI_INVALID_PORT_INDEX;
  505. }
  506. int handleUiResize(int width, int height)
  507. {
  508. CARLA_ASSERT(width > 0);
  509. CARLA_ASSERT(height > 0);
  510. if (width <= 0 || height <= 0)
  511. return 1;
  512. toolkitResize(width, height);
  513. return 0;
  514. }
  515. void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  516. {
  517. if (! (buffer && isOscControlRegistered()))
  518. return;
  519. if (format == 0)
  520. {
  521. CARLA_ASSERT(buffer);
  522. CARLA_ASSERT(bufferSize == sizeof(float));
  523. if (bufferSize != sizeof(float))
  524. return;
  525. float value = *(float*)buffer;
  526. sendOscControl(portIndex, value);
  527. }
  528. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  529. {
  530. CARLA_ASSERT(buffer);
  531. const LV2_Atom* const atom = (const LV2_Atom*)buffer;
  532. QByteArray chunk((const char*)buffer, bufferSize);
  533. sendOscLv2TransferAtom(portIndex, getCustomURIString(atom->type), chunk.toBase64().constData());
  534. }
  535. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  536. {
  537. CARLA_ASSERT(buffer);
  538. const LV2_Atom* const atom = (const LV2_Atom*)buffer;
  539. QByteArray chunk((const char*)buffer, bufferSize);
  540. sendOscLv2TransferEvent(portIndex, getCustomURIString(atom->type), chunk.toBase64().constData());
  541. }
  542. }
  543. // ----------------- Event Feature ---------------------------------------------------
  544. static uint32_t carla_lv2_event_ref(const LV2_Event_Callback_Data callback_data, LV2_Event* const event)
  545. {
  546. qDebug("CarlaLv2Client::carla_lv2_event_ref(%p, %p)", callback_data, event);
  547. CARLA_ASSERT(callback_data);
  548. CARLA_ASSERT(event);
  549. return 0;
  550. }
  551. static uint32_t carla_lv2_event_unref(const LV2_Event_Callback_Data callback_data, LV2_Event* const event)
  552. {
  553. qDebug("CarlaLv2Client::carla_lv2_event_unref(%p, %p)", callback_data, event);
  554. CARLA_ASSERT(callback_data);
  555. CARLA_ASSERT(event);
  556. return 0;
  557. }
  558. // ----------------- Logs Feature ----------------------------------------------------
  559. static int carla_lv2_log_printf(const LV2_Log_Handle handle, const LV2_URID type, const char* const fmt, ...)
  560. {
  561. qDebug("CarlaLv2Client::carla_lv2_log_printf(%p, %i, %s, ...)", handle, type, fmt);
  562. CARLA_ASSERT(handle);
  563. CARLA_ASSERT(type > 0);
  564. #ifndef DEBUG
  565. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  566. return 0;
  567. #endif
  568. va_list args;
  569. va_start(args, fmt);
  570. const int ret = carla_lv2_log_vprintf(handle, type, fmt, args);
  571. va_end(args);
  572. return ret;
  573. }
  574. static int carla_lv2_log_vprintf(const LV2_Log_Handle handle, const LV2_URID type, const char* const fmt, va_list ap)
  575. {
  576. qDebug("CarlaLv2Client::carla_lv2_log_vprintf(%p, %i, %s, ...)", handle, type, fmt);
  577. CARLA_ASSERT(handle);
  578. CARLA_ASSERT(type > 0);
  579. #ifndef DEBUG
  580. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  581. return 0;
  582. #endif
  583. char buf[8196];
  584. vsprintf(buf, fmt, ap);
  585. if (*buf == 0)
  586. return 0;
  587. switch (type)
  588. {
  589. case CARLA_URI_MAP_ID_LOG_ERROR:
  590. qCritical("%s", buf);
  591. break;
  592. case CARLA_URI_MAP_ID_LOG_NOTE:
  593. printf("%s\n", buf);
  594. break;
  595. case CARLA_URI_MAP_ID_LOG_TRACE:
  596. qDebug("%s", buf);
  597. break;
  598. case CARLA_URI_MAP_ID_LOG_WARNING:
  599. qWarning("%s", buf);
  600. break;
  601. default:
  602. break;
  603. }
  604. return std::strlen(buf);
  605. }
  606. // ----------------- Programs Feature ------------------------------------------------
  607. static void carla_lv2_program_changed(const LV2_Programs_Handle handle, const int32_t index)
  608. {
  609. qDebug("CarlaLv2Client::carla_lv2_program_changed(%p, %i)", handle, index);
  610. CARLA_ASSERT(handle);
  611. if (! handle)
  612. return;
  613. CarlaLv2Client* const client = (CarlaLv2Client*)handle;
  614. client->handleProgramChanged(index);
  615. }
  616. // ----------------- State Feature ---------------------------------------------------
  617. static char* carla_lv2_state_make_path(const LV2_State_Make_Path_Handle handle, const char* const path)
  618. {
  619. qDebug("CarlaLv2Client::carla_lv2_state_make_path(%p, %p)", handle, path);
  620. CARLA_ASSERT(handle);
  621. CARLA_ASSERT(path);
  622. if (! path)
  623. return nullptr;
  624. QDir dir;
  625. dir.mkpath(path);
  626. return strdup(path);
  627. }
  628. static char* carla_lv2_state_map_abstract_path(const LV2_State_Map_Path_Handle handle, const char* const absolute_path)
  629. {
  630. qDebug("CarlaLv2Client::carla_lv2_state_map_abstract_path(%p, %p)", handle, absolute_path);
  631. CARLA_ASSERT(handle);
  632. CARLA_ASSERT(absolute_path);
  633. if (! absolute_path)
  634. return nullptr;
  635. QDir dir(absolute_path);
  636. return strdup(dir.canonicalPath().toUtf8().constData());
  637. }
  638. static char* carla_lv2_state_map_absolute_path(const LV2_State_Map_Path_Handle handle, const char* const abstract_path)
  639. {
  640. qDebug("CarlaLv2Client::carla_lv2_state_map_absolute_path(%p, %p)", handle, abstract_path);
  641. CARLA_ASSERT(handle);
  642. CARLA_ASSERT(abstract_path);
  643. if (! abstract_path)
  644. return nullptr;
  645. QDir dir(abstract_path);
  646. return strdup(dir.absolutePath().toUtf8().constData());
  647. }
  648. // ----------------- URI-Map Feature ---------------------------------------
  649. static uint32_t carla_lv2_uri_to_id(const LV2_URI_Map_Callback_Data data, const char* const map, const char* const uri)
  650. {
  651. qDebug("CarlaLv2Client::carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);
  652. return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
  653. }
  654. // ----------------- URID Feature ------------------------------------------
  655. static LV2_URID carla_lv2_urid_map(const LV2_URID_Map_Handle handle, const char* const uri)
  656. {
  657. qDebug("CarlaLv2Client::carla_lv2_urid_map(%p, %s)", handle, uri);
  658. CARLA_ASSERT(handle);
  659. CARLA_ASSERT(uri);
  660. if (! uri)
  661. return CARLA_URI_MAP_ID_NULL;
  662. // Atom types
  663. if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
  664. return CARLA_URI_MAP_ID_ATOM_CHUNK;
  665. if (std::strcmp(uri, LV2_ATOM__Double) == 0)
  666. return CARLA_URI_MAP_ID_ATOM_DOUBLE;
  667. if (std::strcmp(uri, LV2_ATOM__Int) == 0)
  668. return CARLA_URI_MAP_ID_ATOM_INT;
  669. if (std::strcmp(uri, LV2_ATOM__Path) == 0)
  670. return CARLA_URI_MAP_ID_ATOM_PATH;
  671. if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
  672. return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
  673. if (std::strcmp(uri, LV2_ATOM__String) == 0)
  674. return CARLA_URI_MAP_ID_ATOM_STRING;
  675. if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  676. return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
  677. if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  678. return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
  679. // BufSize types
  680. if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
  681. return CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  682. if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
  683. return CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  684. if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
  685. return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  686. // Log types
  687. if (std::strcmp(uri, LV2_LOG__Error) == 0)
  688. return CARLA_URI_MAP_ID_LOG_ERROR;
  689. if (std::strcmp(uri, LV2_LOG__Note) == 0)
  690. return CARLA_URI_MAP_ID_LOG_NOTE;
  691. if (std::strcmp(uri, LV2_LOG__Trace) == 0)
  692. return CARLA_URI_MAP_ID_LOG_TRACE;
  693. if (std::strcmp(uri, LV2_LOG__Warning) == 0)
  694. return CARLA_URI_MAP_ID_LOG_WARNING;
  695. // Others
  696. if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  697. return CARLA_URI_MAP_ID_MIDI_EVENT;
  698. if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
  699. return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  700. if (! handle)
  701. return CARLA_URI_MAP_ID_NULL;
  702. // Custom types
  703. CarlaLv2Client* const client = (CarlaLv2Client*)handle;
  704. return client->getCustomURID(uri);
  705. }
  706. static const char* carla_lv2_urid_unmap(const LV2_URID_Map_Handle handle, const LV2_URID urid)
  707. {
  708. qDebug("CarlaLv2Client::carla_lv2_urid_unmap(%p, %i)", handle, urid);
  709. CARLA_ASSERT(handle);
  710. CARLA_ASSERT(urid > CARLA_URI_MAP_ID_NULL);
  711. if (urid == CARLA_URI_MAP_ID_NULL)
  712. return nullptr;
  713. // Atom types
  714. if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
  715. return LV2_ATOM__Chunk;
  716. if (urid == CARLA_URI_MAP_ID_ATOM_DOUBLE)
  717. return LV2_ATOM__Double;
  718. if (urid == CARLA_URI_MAP_ID_ATOM_INT)
  719. return LV2_ATOM__Int;
  720. if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
  721. return LV2_ATOM__Path;
  722. if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
  723. return LV2_ATOM__Sequence;
  724. if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
  725. return LV2_ATOM__String;
  726. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  727. return LV2_ATOM__atomTransfer;
  728. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  729. return LV2_ATOM__eventTransfer;
  730. // BufSize types
  731. if (urid == CARLA_URI_MAP_ID_BUF_MAX_LENGTH)
  732. return LV2_BUF_SIZE__maxBlockLength;
  733. if (urid == CARLA_URI_MAP_ID_BUF_MIN_LENGTH)
  734. return LV2_BUF_SIZE__minBlockLength;
  735. if (urid == CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE)
  736. return LV2_BUF_SIZE__sequenceSize;
  737. // Log types
  738. if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
  739. return LV2_LOG__Error;
  740. if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
  741. return LV2_LOG__Note;
  742. if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
  743. return LV2_LOG__Trace;
  744. if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
  745. return LV2_LOG__Warning;
  746. // Others
  747. if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
  748. return LV2_MIDI__MidiEvent;
  749. if (urid == CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE)
  750. return LV2_PARAMETERS__sampleRate;
  751. if (! handle)
  752. return nullptr;
  753. // Custom types
  754. CarlaLv2Client* const client = (CarlaLv2Client*)handle;
  755. return client->getCustomURIString(urid);
  756. }
  757. // ----------------- UI Port-Map Feature ---------------------------------------------
  758. static uint32_t carla_lv2_ui_port_map(const LV2UI_Feature_Handle handle, const char* const symbol)
  759. {
  760. qDebug("CarlaLv2Client::carla_lv2_ui_port_map(%p, %s)", handle, symbol);
  761. CARLA_ASSERT(handle);
  762. if (! handle)
  763. return LV2UI_INVALID_PORT_INDEX;
  764. CarlaLv2Client* const client = (CarlaLv2Client*)handle;
  765. return client->handleUiPortMap(symbol);
  766. }
  767. // ----------------- UI Resize Feature -------------------------------------
  768. static int carla_lv2_ui_resize(const LV2UI_Feature_Handle handle, const int width, const int height)
  769. {
  770. qDebug("CarlaLv2Client::carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  771. CARLA_ASSERT(handle);
  772. if (! handle)
  773. return 1;
  774. CarlaLv2Client* const client = (CarlaLv2Client*)handle;
  775. return client->handleUiResize(width, height);
  776. }
  777. // ----------------- UI Extension ------------------------------------------
  778. static void carla_lv2_ui_write_function(const LV2UI_Controller controller, const uint32_t port_index, const uint32_t buffer_size, const uint32_t format, const void* const buffer)
  779. {
  780. qDebug("CarlaLv2Client::carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  781. CARLA_ASSERT(controller);
  782. if (! controller)
  783. return;
  784. CarlaLv2Client* const client = (CarlaLv2Client*)controller;
  785. client->handleUiWrite(port_index, buffer_size, format, buffer);
  786. }
  787. private:
  788. LV2UI_Handle handle;
  789. LV2UI_Widget widget;
  790. const LV2UI_Descriptor* descriptor;
  791. LV2_Feature* features[lv2_feature_count+1];
  792. const LV2_RDF_Descriptor* rdf_descriptor;
  793. const LV2_RDF_UI* rdf_ui_descriptor;
  794. const LV2_Programs_UI_Interface* programs;
  795. bool m_resizable;
  796. std::vector<const char*> customURIDs;
  797. };
  798. int CarlaBridgeOsc::handleMsgLv2TransferAtom(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  799. {
  800. qDebug("CarlaBridgeOsc::handleMsgLv2TransferAtom()");
  801. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(3, "iss");
  802. if (! kClient)
  803. return 1;
  804. const int32_t portIndex = argv[0]->i;
  805. const char* const typeStr = (const char*)&argv[1]->s;
  806. const char* const atomBuf = (const char*)&argv[2]->s;
  807. QByteArray chunk;
  808. chunk = QByteArray::fromBase64(atomBuf);
  809. LV2_Atom* const atom = (LV2_Atom*)chunk.constData();
  810. CarlaLv2Client* const lv2Client = (CarlaLv2Client*)kClient;
  811. atom->type = lv2Client->getCustomURID(typeStr);
  812. lv2Client->handleTransferAtom(portIndex, atom);
  813. return 0;
  814. }
  815. int CarlaBridgeOsc::handleMsgLv2TransferEvent(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  816. {
  817. qDebug("CarlaBridgeOsc::handleMsgLv2TransferEvent()");
  818. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(3, "iss");
  819. if (! kClient)
  820. return 1;
  821. const int32_t portIndex = argv[0]->i;
  822. const char* const typeStr = (const char*)&argv[1]->s;
  823. const char* const atomBuf = (const char*)&argv[2]->s;
  824. QByteArray chunk;
  825. chunk = QByteArray::fromBase64(atomBuf);
  826. LV2_Atom* const atom = (LV2_Atom*)chunk.constData();
  827. CarlaLv2Client* const lv2Client = (CarlaLv2Client*)kClient;
  828. atom->type = lv2Client->getCustomURID(typeStr);
  829. lv2Client->handleTransferEvent(portIndex, atom);
  830. return 0;
  831. }
  832. CARLA_BRIDGE_END_NAMESPACE
  833. int main(int argc, char* argv[])
  834. {
  835. CARLA_BRIDGE_USE_NAMESPACE
  836. if (argc != 5)
  837. {
  838. qWarning("usage: %s <osc-url|\"null\"> <plugin-uri> <ui-uri> <ui-title>", argv[0]);
  839. return 1;
  840. }
  841. const char* oscUrl = argv[1];
  842. const char* pluginURI = argv[2];
  843. const char* uiURI = argv[3];
  844. const char* uiTitle = argv[4];
  845. const bool useOsc = std::strcmp(oscUrl, "null");
  846. // try to get sampleRate value
  847. const char* const sampleRateStr = getenv("CARLA_SAMPLE_RATE");
  848. if (sampleRateStr)
  849. sampleRate = atof(sampleRateStr);
  850. // Init LV2 client
  851. CarlaLv2Client client(uiTitle);
  852. // Init OSC
  853. if (useOsc)
  854. client.oscInit(oscUrl);
  855. // Load UI
  856. int ret;
  857. if (client.uiInit(pluginURI, uiURI))
  858. {
  859. client.toolkitExec(!useOsc);
  860. ret = 0;
  861. }
  862. else
  863. {
  864. qCritical("Failed to load LV2 UI");
  865. ret = 1;
  866. }
  867. // Close OSC
  868. if (useOsc)
  869. client.oscClose();
  870. // Close LV2 client
  871. client.uiClose();
  872. return ret;
  873. }
  874. #endif // BRIDGE_LV2