Collection of tools useful for audio production
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.

1133 lines
38KB

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