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.

1141 lines
42KB

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