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.

1204 lines
41KB

  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__idleInterface;
  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. }