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.

1234 lines
42KB

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