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.

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