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.

904 lines
29KB

  1. /*
  2. * Carla UI bridge code
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.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. #include "carla_bridge_client.h"
  18. #include "carla_lv2.h"
  19. #include "carla_midi.h"
  20. #include <vector>
  21. #include <QtCore/QDir>
  22. #ifdef BRIDGE_LV2_X11
  23. #include <QtGui/QDialog>
  24. #endif
  25. //CARLA_BRIDGE_START_NAMESPACE;
  26. namespace CarlaBridge {
  27. // -------------------------------------------------------------------------
  28. // feature ids
  29. const uint32_t lv2_feature_id_event = 0;
  30. const uint32_t lv2_feature_id_logs = 1;
  31. const uint32_t lv2_feature_id_programs = 2;
  32. const uint32_t lv2_feature_id_state_make_path = 3;
  33. const uint32_t lv2_feature_id_state_map_path = 4;
  34. const uint32_t lv2_feature_id_strict_bounds = 5;
  35. const uint32_t lv2_feature_id_uri_map = 6;
  36. const uint32_t lv2_feature_id_urid_map = 7;
  37. const uint32_t lv2_feature_id_urid_unmap = 8;
  38. const uint32_t lv2_feature_id_ui_parent = 9;
  39. const uint32_t lv2_feature_id_ui_port_map = 10;
  40. const uint32_t lv2_feature_id_ui_resize = 11;
  41. const uint32_t lv2_feature_count = 12;
  42. // pre-set uri[d] map ids
  43. const uint32_t CARLA_URI_MAP_ID_NULL = 0;
  44. const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1;
  45. const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 2;
  46. const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 3;
  47. const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 4;
  48. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 5;
  49. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 6;
  50. const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 7;
  51. const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 8;
  52. const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 9;
  53. const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 10;
  54. const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 11;
  55. const uint32_t CARLA_URI_MAP_ID_COUNT = 12;
  56. // -------------------------------------------------------------------------
  57. class CarlaBridgeLv2Client : public CarlaBridgeClient
  58. {
  59. public:
  60. CarlaBridgeLv2Client(CarlaBridgeToolkit* const toolkit) : CarlaBridgeClient(toolkit)
  61. {
  62. handle = nullptr;
  63. widget = nullptr;
  64. descriptor = nullptr;
  65. rdf_descriptor = nullptr;
  66. rdf_ui_descriptor = nullptr;
  67. programs = nullptr;
  68. #ifdef BRIDGE_LV2_X11
  69. m_resizable = false;
  70. x11_widget = new QDialog;
  71. #else
  72. m_resizable = true;
  73. #endif
  74. for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; i++)
  75. customURIDs.push_back(nullptr);
  76. for (uint32_t i=0; i < lv2_feature_count+1; i++)
  77. features[i] = nullptr;
  78. // -----------------------------------------------------------------
  79. // initialize features
  80. LV2_Event_Feature* Event_Feature = new LV2_Event_Feature;
  81. Event_Feature->callback_data = this;
  82. Event_Feature->lv2_event_ref = carla_lv2_event_ref;
  83. Event_Feature->lv2_event_unref = carla_lv2_event_unref;
  84. LV2_Log_Log* Log_Feature = new LV2_Log_Log;
  85. Log_Feature->handle = this;
  86. Log_Feature->printf = carla_lv2_log_printf;
  87. Log_Feature->vprintf = carla_lv2_log_vprintf;
  88. LV2_Programs_Host* Programs_Feature = new LV2_Programs_Host;
  89. Programs_Feature->handle = this;
  90. Programs_Feature->program_changed = carla_lv2_program_changed;
  91. LV2_State_Make_Path* State_MakePath_Feature = new LV2_State_Make_Path;
  92. State_MakePath_Feature->handle = this;
  93. State_MakePath_Feature->path = carla_lv2_state_make_path;
  94. LV2_State_Map_Path* State_MapPath_Feature = new LV2_State_Map_Path;
  95. State_MapPath_Feature->handle = this;
  96. State_MapPath_Feature->abstract_path = carla_lv2_state_map_abstract_path;
  97. State_MapPath_Feature->absolute_path = carla_lv2_state_map_absolute_path;
  98. LV2_URI_Map_Feature* URI_Map_Feature = new LV2_URI_Map_Feature;
  99. URI_Map_Feature->callback_data = this;
  100. URI_Map_Feature->uri_to_id = carla_lv2_uri_to_id;
  101. LV2_URID_Map* URID_Map_Feature = new LV2_URID_Map;
  102. URID_Map_Feature->handle = this;
  103. URID_Map_Feature->map = carla_lv2_urid_map;
  104. LV2_URID_Unmap* URID_Unmap_Feature = new LV2_URID_Unmap;
  105. URID_Unmap_Feature->handle = this;
  106. URID_Unmap_Feature->unmap = carla_lv2_urid_unmap;
  107. LV2UI_Port_Map* UI_PortMap_Feature = new LV2UI_Port_Map;
  108. UI_PortMap_Feature->handle = this;
  109. UI_PortMap_Feature->port_index = carla_lv2_ui_port_map;
  110. LV2UI_Resize* UI_Resize_Feature = new LV2UI_Resize;
  111. UI_Resize_Feature->handle = this;
  112. UI_Resize_Feature->ui_resize = carla_lv2_ui_resize;
  113. features[lv2_feature_id_event] = new LV2_Feature;
  114. features[lv2_feature_id_event]->URI = LV2_EVENT_URI;
  115. features[lv2_feature_id_event]->data = Event_Feature;
  116. features[lv2_feature_id_logs] = new LV2_Feature;
  117. features[lv2_feature_id_logs]->URI = LV2_LOG__log;
  118. features[lv2_feature_id_logs]->data = Log_Feature;
  119. features[lv2_feature_id_programs] = new LV2_Feature;
  120. features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host;
  121. features[lv2_feature_id_programs]->data = Programs_Feature;
  122. features[lv2_feature_id_state_make_path] = new LV2_Feature;
  123. features[lv2_feature_id_state_make_path]->URI = LV2_STATE__makePath;
  124. features[lv2_feature_id_state_make_path]->data = State_MakePath_Feature;
  125. features[lv2_feature_id_state_map_path] = new LV2_Feature;
  126. features[lv2_feature_id_state_map_path]->URI = LV2_STATE__mapPath;
  127. features[lv2_feature_id_state_map_path]->data = State_MapPath_Feature;
  128. features[lv2_feature_id_strict_bounds] = new LV2_Feature;
  129. features[lv2_feature_id_strict_bounds]->URI = LV2_PORT_PROPS__supportsStrictBounds;
  130. features[lv2_feature_id_strict_bounds]->data = nullptr;
  131. features[lv2_feature_id_uri_map] = new LV2_Feature;
  132. features[lv2_feature_id_uri_map]->URI = LV2_URI_MAP_URI;
  133. features[lv2_feature_id_uri_map]->data = URI_Map_Feature;
  134. features[lv2_feature_id_urid_map] = new LV2_Feature;
  135. features[lv2_feature_id_urid_map]->URI = LV2_URID__map;
  136. features[lv2_feature_id_urid_map]->data = URID_Map_Feature;
  137. features[lv2_feature_id_urid_unmap] = new LV2_Feature;
  138. features[lv2_feature_id_urid_unmap]->URI = LV2_URID__unmap;
  139. features[lv2_feature_id_urid_unmap]->data = URID_Unmap_Feature;
  140. features[lv2_feature_id_ui_parent] = new LV2_Feature;
  141. features[lv2_feature_id_ui_parent]->URI = LV2_UI__parent;
  142. #ifdef BRIDGE_LV2_X11
  143. features[lv2_feature_id_ui_parent]->data = (void*)x11_widget->winId();
  144. #else
  145. features[lv2_feature_id_ui_parent]->data = nullptr;
  146. #endif
  147. features[lv2_feature_id_ui_port_map] = new LV2_Feature;
  148. features[lv2_feature_id_ui_port_map]->URI = LV2_UI__portMap;
  149. features[lv2_feature_id_ui_port_map]->data = UI_PortMap_Feature;
  150. features[lv2_feature_id_ui_resize] = new LV2_Feature;
  151. features[lv2_feature_id_ui_resize]->URI = LV2_UI__resize;
  152. features[lv2_feature_id_ui_resize]->data = UI_Resize_Feature;
  153. }
  154. ~CarlaBridgeLv2Client()
  155. {
  156. if (rdf_descriptor)
  157. lv2_rdf_free(rdf_descriptor);
  158. delete (LV2_Event_Feature*)features[lv2_feature_id_event]->data;
  159. delete (LV2_Log_Log*)features[lv2_feature_id_logs]->data;
  160. delete (LV2_Programs_Host*)features[lv2_feature_id_programs]->data;
  161. delete (LV2_State_Make_Path*)features[lv2_feature_id_state_make_path]->data;
  162. delete (LV2_State_Map_Path*)features[lv2_feature_id_state_map_path]->data;
  163. delete (LV2_URI_Map_Feature*)features[lv2_feature_id_uri_map]->data;
  164. delete (LV2_URID_Map*)features[lv2_feature_id_urid_map]->data;
  165. delete (LV2_URID_Unmap*)features[lv2_feature_id_urid_unmap]->data;
  166. delete (LV2UI_Port_Map*)features[lv2_feature_id_ui_port_map]->data;
  167. delete (LV2UI_Resize*)features[lv2_feature_id_ui_resize]->data;
  168. for (uint32_t i=0; i < lv2_feature_count; i++)
  169. {
  170. if (features[i])
  171. delete features[i];
  172. }
  173. for (size_t i=0; i < customURIDs.size(); i++)
  174. {
  175. if (customURIDs[i])
  176. free((void*)customURIDs[i]);
  177. }
  178. customURIDs.clear();
  179. }
  180. // ---------------------------------------------------------------------
  181. // initialization
  182. bool init(const char* plugin_uri, const char* ui_uri)
  183. {
  184. // -----------------------------------------------------------------
  185. // get plugin from lv2_rdf (lilv)
  186. Lv2World.init();
  187. rdf_descriptor = lv2_rdf_new(plugin_uri);
  188. if (! rdf_descriptor)
  189. return false;
  190. // -----------------------------------------------------------------
  191. // find requested UI
  192. for (uint32_t i=0; i < rdf_descriptor->UICount; i++)
  193. {
  194. if (strcmp(rdf_descriptor->UIs[i].URI, ui_uri) == 0)
  195. {
  196. rdf_ui_descriptor = &rdf_descriptor->UIs[i];
  197. break;
  198. }
  199. }
  200. if (! rdf_ui_descriptor)
  201. return false;
  202. // -----------------------------------------------------------------
  203. // open DLL
  204. if (! libOpen(rdf_ui_descriptor->Binary))
  205. return false;
  206. // -----------------------------------------------------------------
  207. // get DLL main entry
  208. LV2UI_DescriptorFunction const ui_descfn = (LV2UI_DescriptorFunction)libSymbol("lv2ui_descriptor");
  209. if (! ui_descfn)
  210. return false;
  211. // -----------------------------------------------------------
  212. // get descriptor that matches URI
  213. uint32_t i = 0;
  214. while ((descriptor = ui_descfn(i++)))
  215. {
  216. if (strcmp(descriptor->URI, ui_uri) == 0)
  217. break;
  218. }
  219. if (! descriptor)
  220. return false;
  221. // -----------------------------------------------------------
  222. // initialize UI
  223. handle = descriptor->instantiate(descriptor, plugin_uri, rdf_ui_descriptor->Bundle, carla_lv2_ui_write_function, this, &widget, features);
  224. if (! handle)
  225. return false;
  226. // -----------------------------------------------------------
  227. // check if not resizable
  228. #ifndef BRIDGE_LV2_X11
  229. for (uint32_t i=0; i < rdf_ui_descriptor->FeatureCount; i++)
  230. {
  231. if (strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__fixedSize) == 0 || strcmp(rdf_ui_descriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
  232. {
  233. m_resizable = false;
  234. break;
  235. }
  236. }
  237. #endif
  238. // -----------------------------------------------------------
  239. // check for known extensions
  240. for (uint32_t i=0; descriptor->extension_data && i < rdf_ui_descriptor->ExtensionCount; i++)
  241. {
  242. if (strcmp(rdf_ui_descriptor->Extensions[i], LV2_PROGRAMS__UIInterface) == 0)
  243. {
  244. programs = (LV2_Programs_UI_Interface*)descriptor->extension_data(LV2_PROGRAMS__UIInterface);
  245. break;
  246. }
  247. }
  248. return true;
  249. }
  250. void close()
  251. {
  252. if (handle && descriptor && descriptor->cleanup)
  253. descriptor->cleanup(handle);
  254. libClose();
  255. }
  256. // ---------------------------------------------------------------------
  257. // processing
  258. void setParameter(int32_t rindex, double value)
  259. {
  260. assert(handle && descriptor);
  261. if (handle && descriptor && descriptor->port_event)
  262. {
  263. float fvalue = value;
  264. descriptor->port_event(handle, rindex, sizeof(float), 0, &fvalue);
  265. }
  266. }
  267. void setProgram(uint32_t)
  268. {
  269. }
  270. void setMidiProgram(uint32_t bank, uint32_t program)
  271. {
  272. assert(handle);
  273. if (handle && programs)
  274. programs->select_program(handle, bank, program);
  275. }
  276. void noteOn(uint8_t note, uint8_t velo)
  277. {
  278. assert(handle && descriptor);
  279. // FIXME
  280. if (handle && descriptor && descriptor->port_event)
  281. {
  282. uint8_t buf[3] = { 0x90, note, velo };
  283. descriptor->port_event(handle, 0, 3, CARLA_URI_MAP_ID_MIDI_EVENT, buf);
  284. }
  285. }
  286. void noteOff(uint8_t note)
  287. {
  288. assert(handle && descriptor);
  289. // FIXME
  290. if (handle && descriptor && descriptor->port_event)
  291. {
  292. uint8_t buf[3] = { 0x80, note, 0 };
  293. descriptor->port_event(handle, 0, 3, CARLA_URI_MAP_ID_MIDI_EVENT, buf);
  294. }
  295. }
  296. // ---------------------------------------------------------------------
  297. // gui
  298. void* getWidget() const
  299. {
  300. #ifdef BRIDGE_LV2_X11
  301. return x11_widget;
  302. #else
  303. return widget;
  304. #endif
  305. }
  306. bool isResizable() const
  307. {
  308. return m_resizable;
  309. }
  310. bool needsReparent() const
  311. {
  312. #ifdef BRIDGE_LV2_X11
  313. return true;
  314. #else
  315. return false;
  316. #endif
  317. }
  318. // ---------------------------------------------------------------------
  319. uint32_t getCustomURID(const char* const uri)
  320. {
  321. qDebug("CarlaBridgeLv2Client::getCustomURID(%s)", uri);
  322. assert(uri);
  323. for (size_t i=0; i < customURIDs.size(); i++)
  324. {
  325. if (customURIDs[i] && strcmp(customURIDs[i], uri) == 0)
  326. return i;
  327. }
  328. customURIDs.push_back(strdup(uri));
  329. return customURIDs.size()-1;
  330. }
  331. const char* getCustomURIString(LV2_URID urid)
  332. {
  333. qDebug("CarlaBridgeLv2Client::getCustomURIString(%i)", urid);
  334. assert(urid != 0);
  335. if (urid < customURIDs.size())
  336. return customURIDs[urid];
  337. return nullptr;
  338. }
  339. void handleTransferAtom(const char* const type, const char* const value)
  340. {
  341. qDebug("CarlaBridgeLv2Client::handleTransferEvent(%s, %s)", type, value);
  342. Q_ASSERT(type);
  343. Q_ASSERT(value);
  344. }
  345. void handleTransferEvent(const char* const type, const char* const value)
  346. {
  347. qDebug("CarlaBridgeLv2Client::handleTransferEvent(%s, %s)", type, value);
  348. Q_ASSERT(type);
  349. Q_ASSERT(value);
  350. if (handle && descriptor && descriptor->port_event)
  351. {
  352. LV2_URID_Map* const URID_Map = (LV2_URID_Map*)features[lv2_feature_id_urid_map]->data;
  353. const LV2_URID uridPatchSet = getCustomURID(LV2_PATCH__Set);
  354. const LV2_URID uridPatchBody = getCustomURID(LV2_PATCH__body);
  355. Sratom* sratom = sratom_new(URID_Map);
  356. SerdChunk chunk = { nullptr, 0 };
  357. LV2_Atom_Forge forge;
  358. lv2_atom_forge_init(&forge, URID_Map);
  359. lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &chunk);
  360. LV2_Atom_Forge_Frame refFrame, bodyFrame;
  361. LV2_Atom_Forge_Ref ref = lv2_atom_forge_blank(&forge, &refFrame, 1, uridPatchSet);
  362. lv2_atom_forge_property_head(&forge, uridPatchBody, CARLA_URI_MAP_ID_NULL);
  363. lv2_atom_forge_blank(&forge, &bodyFrame, 2, CARLA_URI_MAP_ID_NULL);
  364. //lv2_atom_forge_property_head(&forge, getCustomURID(key), CARLA_URI_MAP_ID_NULL);
  365. if (strcmp(type, "string") == 0)
  366. lv2_atom_forge_string(&forge, value, strlen(value));
  367. else if (strcmp(type, "path") == 0)
  368. lv2_atom_forge_path(&forge, value, strlen(value));
  369. else if (strcmp(type, "chunk") == 0)
  370. lv2_atom_forge_literal(&forge, value, strlen(value), CARLA_URI_MAP_ID_ATOM_CHUNK, CARLA_URI_MAP_ID_NULL);
  371. //else
  372. // lv2_atom_forge_literal(&forge, value, strlen(value), getCustomURID(key), CARLA_URI_MAP_ID_NULL);
  373. lv2_atom_forge_pop(&forge, &bodyFrame);
  374. lv2_atom_forge_pop(&forge, &refFrame);
  375. const LV2_Atom* const atom = lv2_atom_forge_deref(&forge, ref);
  376. descriptor->port_event(handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  377. free((void*)chunk.buf);
  378. sratom_free(sratom);
  379. }
  380. }
  381. void handleProgramChanged(int32_t /*index*/)
  382. {
  383. sendOscConfigure("reloadprograms", "");
  384. }
  385. uint32_t handleUiPortMap(const char* const symbol)
  386. {
  387. assert(symbol);
  388. for (uint32_t i=0; i < rdf_descriptor->PortCount; i++)
  389. {
  390. if (strcmp(rdf_descriptor->Ports[i].Symbol, symbol) == 0)
  391. return i;
  392. }
  393. return LV2UI_INVALID_PORT_INDEX;
  394. }
  395. int handleUiResize(int width, int height)
  396. {
  397. assert(width > 0);
  398. assert(height > 0);
  399. quequeMessage(MESSAGE_RESIZE_GUI, width, height, 0.0);
  400. return 0;
  401. }
  402. void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  403. {
  404. if (format == 0)
  405. {
  406. assert(bufferSize == sizeof(float));
  407. if (bufferSize == sizeof(float))
  408. {
  409. float value = *(float*)buffer;
  410. sendOscControl(portIndex, value);
  411. }
  412. }
  413. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  414. {
  415. const LV2_Atom* const atom = (const LV2_Atom*)buffer;
  416. QByteArray chunk((const char*)buffer, bufferSize);
  417. sendOscLv2TransferAtom(getCustomURIString(atom->type), chunk.toBase64().constData());
  418. if (descriptor && descriptor->port_event)
  419. descriptor->port_event(handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, atom);
  420. }
  421. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  422. {
  423. const LV2_Atom* const atom = (const LV2_Atom*)buffer;
  424. QByteArray chunk((const char*)buffer, bufferSize);
  425. sendOscLv2TransferEvent(getCustomURIString(atom->type), chunk.toBase64().constData());
  426. if (descriptor && descriptor->port_event)
  427. descriptor->port_event(handle, 0, atom->size, CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  428. }
  429. }
  430. // ----------------- Event Feature ---------------------------------------------------
  431. static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
  432. {
  433. qDebug("CarlaBridgeLv2Client::carla_lv2_event_ref(%p, %p)", callback_data, event);
  434. assert(callback_data);
  435. assert(event);
  436. return 0;
  437. }
  438. static uint32_t carla_lv2_event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
  439. {
  440. qDebug("CarlaBridgeLv2Client::carla_lv2_event_unref(%p, %p)", callback_data, event);
  441. assert(callback_data);
  442. assert(event);
  443. return 0;
  444. }
  445. // ----------------- Logs Feature ----------------------------------------------------
  446. static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
  447. {
  448. qDebug("CarlaBridgeLv2Client::carla_lv2_log_printf(%p, %i, %s, ...)", handle, type, fmt);
  449. assert(handle);
  450. assert(type > 0);
  451. #ifndef DEBUG
  452. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  453. return 0;
  454. #endif
  455. va_list args;
  456. va_start(args, fmt);
  457. const int ret = carla_lv2_log_vprintf(handle, type, fmt, args);
  458. va_end(args);
  459. return ret;
  460. }
  461. static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
  462. {
  463. qDebug("CarlaBridgeLv2Client::carla_lv2_log_vprintf(%p, %i, %s, ...)", handle, type, fmt);
  464. assert(handle);
  465. assert(type > 0);
  466. #ifndef DEBUG
  467. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  468. return 0;
  469. #endif
  470. char buf[8196];
  471. vsprintf(buf, fmt, ap);
  472. if (*buf == 0)
  473. return 0;
  474. switch (type)
  475. {
  476. case CARLA_URI_MAP_ID_LOG_ERROR:
  477. qCritical("%s", buf);
  478. break;
  479. case CARLA_URI_MAP_ID_LOG_NOTE:
  480. printf("%s\n", buf);
  481. break;
  482. case CARLA_URI_MAP_ID_LOG_TRACE:
  483. qDebug("%s", buf);
  484. break;
  485. case CARLA_URI_MAP_ID_LOG_WARNING:
  486. qWarning("%s", buf);
  487. break;
  488. default:
  489. break;
  490. }
  491. return strlen(buf);
  492. }
  493. // ----------------- Programs Feature ------------------------------------------------
  494. static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
  495. {
  496. qDebug("CarlaBridgeLv2Client::carla_lv2_program_changed(%p, %i)", handle, index);
  497. assert(handle);
  498. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)handle;
  499. client->handleProgramChanged(index);
  500. }
  501. // ----------------- State Feature ---------------------------------------------------
  502. static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
  503. {
  504. qDebug("CarlaBridgeLv2Client::carla_lv2_state_make_path(%p, %p)", handle, path);
  505. assert(handle);
  506. assert(path);
  507. QDir dir;
  508. dir.mkpath(path);
  509. return strdup(path);
  510. }
  511. static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
  512. {
  513. qDebug("CarlaBridgeLv2Client::carla_lv2_state_map_abstract_path(%p, %p)", handle, absolute_path);
  514. assert(handle);
  515. assert(absolute_path);
  516. QDir dir(absolute_path);
  517. return strdup(dir.canonicalPath().toUtf8().constData());
  518. }
  519. static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
  520. {
  521. qDebug("CarlaBridgeLv2Client::carla_lv2_state_map_absolute_path(%p, %p)", handle, abstract_path);
  522. assert(handle);
  523. assert(abstract_path);
  524. QDir dir(abstract_path);
  525. return strdup(dir.absolutePath().toUtf8().constData());
  526. }
  527. // ----------------- URI-Map Feature ---------------------------------------
  528. static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
  529. {
  530. qDebug("CarlaBridgeLv2Client::carla_lv2_uri_to_id(%p, %s, %s)", data, map, uri);
  531. return carla_lv2_urid_map(data, uri);
  532. }
  533. // ----------------- URID Feature ------------------------------------------
  534. static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
  535. {
  536. qDebug("CarlaBridgeLv2Client::carla_lv2_urid_map(%p, %s)", handle, uri);
  537. assert(handle);
  538. assert(uri);
  539. // Atom types
  540. if (strcmp(uri, LV2_ATOM__Chunk) == 0)
  541. return CARLA_URI_MAP_ID_ATOM_CHUNK;
  542. if (strcmp(uri, LV2_ATOM__Path) == 0)
  543. return CARLA_URI_MAP_ID_ATOM_PATH;
  544. if (strcmp(uri, LV2_ATOM__Sequence) == 0)
  545. return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
  546. if (strcmp(uri, LV2_ATOM__String) == 0)
  547. return CARLA_URI_MAP_ID_ATOM_STRING;
  548. if (strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  549. return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
  550. if (strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  551. return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
  552. // Log types
  553. if (strcmp(uri, LV2_LOG__Error) == 0)
  554. return CARLA_URI_MAP_ID_LOG_ERROR;
  555. if (strcmp(uri, LV2_LOG__Note) == 0)
  556. return CARLA_URI_MAP_ID_LOG_NOTE;
  557. if (strcmp(uri, LV2_LOG__Trace) == 0)
  558. return CARLA_URI_MAP_ID_LOG_TRACE;
  559. if (strcmp(uri, LV2_LOG__Warning) == 0)
  560. return CARLA_URI_MAP_ID_LOG_WARNING;
  561. // Others
  562. if (strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  563. return CARLA_URI_MAP_ID_MIDI_EVENT;
  564. // Custom types
  565. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)handle;
  566. return client->getCustomURID(uri);
  567. }
  568. static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  569. {
  570. qDebug("CarlaBridgeLv2Client::carla_lv2_urid_unmap(%p, %i)", handle, urid);
  571. assert(handle);
  572. assert(urid > 0);
  573. // Atom types
  574. if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
  575. return LV2_ATOM__Chunk;
  576. if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
  577. return LV2_ATOM__Path;
  578. if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
  579. return LV2_ATOM__Sequence;
  580. if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
  581. return LV2_ATOM__String;
  582. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  583. return LV2_ATOM__atomTransfer;
  584. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  585. return LV2_ATOM__eventTransfer;
  586. // Log types
  587. if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
  588. return LV2_LOG__Error;
  589. if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
  590. return LV2_LOG__Note;
  591. if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
  592. return LV2_LOG__Trace;
  593. if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
  594. return LV2_LOG__Warning;
  595. // Others
  596. if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
  597. return LV2_MIDI__MidiEvent;
  598. // Custom types
  599. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)handle;
  600. return client->getCustomURIString(urid);
  601. }
  602. // ----------------- UI Port-Map Feature ---------------------------------------------
  603. static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
  604. {
  605. qDebug("CarlaBridgeLv2Client::carla_lv2_ui_port_map(%p, %s)", handle, symbol);
  606. assert(handle);
  607. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)handle;
  608. return client->handleUiPortMap(symbol);
  609. }
  610. // ----------------- UI Resize Feature -------------------------------------
  611. static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
  612. {
  613. qDebug("CarlaBridgeLv2Client::carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  614. assert(handle);
  615. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)handle;
  616. return client->handleUiResize(width, height);
  617. }
  618. // ----------------- UI Extension ------------------------------------------
  619. static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
  620. {
  621. qDebug("CarlaBridgeLv2Client::carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  622. assert(controller);
  623. CarlaBridgeLv2Client* const client = (CarlaBridgeLv2Client*)controller;
  624. client->handleUiWrite(port_index, buffer_size, format, buffer);
  625. }
  626. private:
  627. LV2UI_Handle handle;
  628. LV2UI_Widget widget;
  629. const LV2UI_Descriptor* descriptor;
  630. LV2_Feature* features[lv2_feature_count+1];
  631. const LV2_RDF_Descriptor* rdf_descriptor;
  632. const LV2_RDF_UI* rdf_ui_descriptor;
  633. const LV2_Programs_UI_Interface* programs;
  634. #ifdef BRIDGE_LV2_X11
  635. QDialog* x11_widget;
  636. #endif
  637. bool m_resizable;
  638. std::vector<const char*> customURIDs;
  639. };
  640. int CarlaBridgeOsc::handle_lv2_transfer_atom(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  641. {
  642. qDebug("CarlaBridgeOsc::handle_lv2_atom_transfer()");
  643. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ss");
  644. if (! client)
  645. return 1;
  646. const char* type = (const char*)&argv[0]->s;
  647. const char* value = (const char*)&argv[2]->s;
  648. CarlaBridgeLv2Client* const lv2client = (CarlaBridgeLv2Client*)client;
  649. lv2client->handleTransferAtom(type, value);
  650. return 0;
  651. }
  652. int CarlaBridgeOsc::handle_lv2_transfer_event(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  653. {
  654. qDebug("CarlaBridgeOsc::handle_lv2_event_transfer()");
  655. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ss");
  656. if (! client)
  657. return 1;
  658. const char* type = (const char*)&argv[0]->s;
  659. const char* value = (const char*)&argv[2]->s;
  660. CarlaBridgeLv2Client* lv2client = (CarlaBridgeLv2Client*)client;
  661. lv2client->handleTransferEvent(type, value);
  662. return 0;
  663. }
  664. CARLA_BRIDGE_END_NAMESPACE
  665. int main(int argc, char* argv[])
  666. {
  667. if (argc != 5)
  668. {
  669. qCritical("%s: bad arguments", argv[0]);
  670. return 1;
  671. }
  672. const char* osc_url = argv[1];
  673. const char* plugin_uri = argv[2];
  674. const char* ui_uri = argv[3];
  675. const char* ui_title = argv[4];
  676. using namespace CarlaBridge;
  677. // Init toolkit
  678. CarlaBridgeToolkit* const toolkit = CarlaBridgeToolkit::createNew(ui_title);
  679. toolkit->init();
  680. // Init LV2-UI
  681. CarlaBridgeLv2Client client(toolkit);
  682. // Init OSC
  683. if (! client.oscInit(osc_url))
  684. {
  685. toolkit->quit();
  686. delete toolkit;
  687. return -1;
  688. }
  689. // Load UI
  690. int ret;
  691. if (client.init(plugin_uri, ui_uri))
  692. {
  693. toolkit->exec(&client);
  694. ret = 0;
  695. }
  696. else
  697. {
  698. qCritical("Failed to load LV2 UI");
  699. ret = 1;
  700. }
  701. // Close OSC
  702. client.sendOscExiting();
  703. client.oscClose();
  704. // Close LV2-UI
  705. client.close();
  706. // Close toolkit
  707. toolkit->quit();
  708. delete toolkit;
  709. return ret;
  710. }