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.

1287 lines
46KB

  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 "CarlaBridgeClient.hpp"
  18. #include "CarlaBase64Utils.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 CarlaBridgeClient
  168. {
  169. public:
  170. CarlaLv2Client(const char* const uiTitle)
  171. : CarlaBridgeClient(uiTitle),
  172. fHandle(nullptr),
  173. fWidget(nullptr),
  174. fDescriptor(nullptr),
  175. fRdfDescriptor(nullptr),
  176. fRdfUiDescriptor(nullptr),
  177. fOptions(),
  178. fIsReady(false),
  179. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  180. fIsResizable(false),
  181. #else
  182. fIsResizable(true),
  183. #endif
  184. fCustomURIDs(),
  185. fExt(),
  186. leakDetector_CarlaLv2Client()
  187. {
  188. carla_fill<LV2_Feature*>(fFeatures, nullptr, kFeatureCount+1);
  189. for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; ++i)
  190. fCustomURIDs.append(nullptr);
  191. // ---------------------------------------------------------------
  192. // initialize options
  193. fOptions.minBufferSize = gBufferSizei;
  194. fOptions.maxBufferSize = gBufferSizei;
  195. fOptions.sampleRate = gSampleRate;
  196. // ---------------------------------------------------------------
  197. // initialize features (part 1)
  198. LV2_Log_Log* const logFt = new LV2_Log_Log;
  199. logFt->handle = this;
  200. logFt->printf = carla_lv2_log_printf;
  201. logFt->vprintf = carla_lv2_log_vprintf;
  202. LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
  203. stateMakePathFt->handle = this;
  204. stateMakePathFt->path = carla_lv2_state_make_path;
  205. LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
  206. stateMapPathFt->handle = this;
  207. stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path;
  208. stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path;
  209. LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
  210. programsFt->handle = this;
  211. programsFt->program_changed = carla_lv2_program_changed;
  212. LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
  213. uriMapFt->callback_data = this;
  214. uriMapFt->uri_to_id = carla_lv2_uri_to_id;
  215. LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
  216. uridMapFt->handle = this;
  217. uridMapFt->map = carla_lv2_urid_map;
  218. LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
  219. uridUnmapFt->handle = this;
  220. uridUnmapFt->unmap = carla_lv2_urid_unmap;
  221. LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
  222. uiPortMapFt->handle = this;
  223. uiPortMapFt->port_index = carla_lv2_ui_port_map;
  224. LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
  225. uiResizeFt->handle = this;
  226. uiResizeFt->ui_resize = carla_lv2_ui_resize;
  227. // ---------------------------------------------------------------
  228. // initialize features (part 2)
  229. for (uint32_t i=0; i < kFeatureCount; ++i)
  230. fFeatures[i] = new LV2_Feature;
  231. fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
  232. fFeatures[kFeatureIdLogs]->data = logFt;
  233. fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
  234. fFeatures[kFeatureIdOptions]->data = fOptions.opts;
  235. fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
  236. fFeatures[kFeatureIdPrograms]->data = programsFt;
  237. fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
  238. fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
  239. fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
  240. fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
  241. fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
  242. fFeatures[kFeatureIdUriMap]->data = uriMapFt;
  243. fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
  244. fFeatures[kFeatureIdUridMap]->data = uridMapFt;
  245. fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
  246. fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
  247. fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
  248. fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
  249. fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
  250. fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
  251. fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
  252. fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
  253. fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
  254. fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
  255. fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
  256. fFeatures[kFeatureIdUiParent]->data = nullptr;
  257. fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
  258. fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
  259. fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
  260. fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
  261. fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
  262. fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
  263. fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
  264. fFeatures[kFeatureIdUiTouch]->data = nullptr;
  265. }
  266. ~CarlaLv2Client() override
  267. {
  268. if (fRdfDescriptor != nullptr)
  269. delete fRdfDescriptor;
  270. delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
  271. delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
  272. delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
  273. delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
  274. delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
  275. delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
  276. delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
  277. delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
  278. delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
  279. for (uint32_t i=0; i < kFeatureCount; ++i)
  280. {
  281. if (fFeatures[i] != nullptr)
  282. {
  283. delete fFeatures[i];
  284. fFeatures[i] = nullptr;
  285. }
  286. }
  287. for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
  288. {
  289. const char* const uri(it.getValue());
  290. if (uri != nullptr)
  291. delete[] uri;
  292. }
  293. fCustomURIDs.clear();
  294. }
  295. // ---------------------------------------------------------------------
  296. // ui initialization
  297. bool uiInit(const char* pluginURI, const char* uiURI, const char* uiBundle) override
  298. {
  299. // -----------------------------------------------------------------
  300. // load bundle
  301. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  302. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, uiBundle));
  303. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(), false);
  304. CarlaString sBundle(bundleNode.as_uri());
  305. if (! sBundle.endsWith("/"))
  306. sBundle += "/";
  307. lv2World.load_bundle(sBundle);
  308. // -----------------------------------------------------------------
  309. // init
  310. CarlaBridgeClient::uiInit(pluginURI, uiURI, uiBundle);
  311. // -----------------------------------------------------------------
  312. // get plugin from lv2_rdf (lilv)
  313. fRdfDescriptor = lv2_rdf_new(pluginURI, true);
  314. if (fRdfDescriptor == nullptr)
  315. return false;
  316. // -----------------------------------------------------------------
  317. // find requested UI
  318. for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
  319. {
  320. if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
  321. {
  322. fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
  323. break;
  324. }
  325. }
  326. if (fRdfUiDescriptor == nullptr)
  327. {
  328. carla_stderr("Failed to find requested UI");
  329. return false;
  330. }
  331. // -----------------------------------------------------------------
  332. // open DLL
  333. if (! uiLibOpen(fRdfUiDescriptor->Binary))
  334. {
  335. carla_stderr("Failed to load UI binary, error was:\n%s", uiLibError());
  336. return false;
  337. }
  338. // -----------------------------------------------------------------
  339. // get DLL main entry
  340. const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)uiLibSymbol("lv2ui_descriptor");
  341. if (ui_descFn == nullptr)
  342. return false;
  343. // -----------------------------------------------------------
  344. // get descriptor that matches URI
  345. uint32_t i = 0;
  346. while ((fDescriptor = ui_descFn(i++)))
  347. {
  348. if (std::strcmp(fDescriptor->URI, uiURI) == 0)
  349. break;
  350. }
  351. if (fDescriptor == nullptr)
  352. {
  353. carla_stderr("Failed to find UI descriptor");
  354. return false;
  355. }
  356. // -----------------------------------------------------------
  357. // initialize UI
  358. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  359. fFeatures[kFeatureIdUiParent]->data = getContainerId();
  360. #endif
  361. fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures);
  362. if (fHandle == nullptr)
  363. {
  364. carla_stderr("Failed to init UI");
  365. return false;
  366. }
  367. // -----------------------------------------------------------
  368. // check if not resizable
  369. for (uint32_t j=0; j < fRdfUiDescriptor->FeatureCount && fIsResizable; ++j)
  370. {
  371. if (std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__fixedSize ) == 0 ||
  372. std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__noUserResize) == 0)
  373. {
  374. fIsResizable = false;
  375. break;
  376. }
  377. }
  378. // -----------------------------------------------------------
  379. // check for known extensions
  380. if (fDescriptor->extension_data != nullptr)
  381. {
  382. fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
  383. fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
  384. fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
  385. // check if invalid
  386. if (fExt.programs != nullptr && fExt.programs->select_program == nullptr)
  387. fExt.programs = nullptr;
  388. if (fExt.idle != nullptr && fExt.idle->idle == nullptr)
  389. fExt.idle = nullptr;
  390. }
  391. return true;
  392. }
  393. void uiIdle() override
  394. {
  395. if (fHandle != nullptr && fExt.idle != nullptr)
  396. fExt.idle->idle(fHandle);
  397. }
  398. void uiClose() override
  399. {
  400. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr)
  401. {
  402. fDescriptor->cleanup(fHandle);
  403. fHandle = nullptr;
  404. }
  405. CarlaBridgeClient::uiClose();
  406. uiLibClose();
  407. }
  408. // ---------------------------------------------------------------------
  409. // ui management
  410. void* getWidget() const override
  411. {
  412. return fWidget;
  413. }
  414. bool isResizable() const override
  415. {
  416. return fIsResizable;
  417. }
  418. // ---------------------------------------------------------------------
  419. // ui processing
  420. void setParameter(const int32_t rindex, const float value) override
  421. {
  422. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  423. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  424. CARLA_SAFE_ASSERT_RETURN(rindex >= 0,)
  425. if (fDescriptor->port_event == nullptr)
  426. return;
  427. fDescriptor->port_event(fHandle, static_cast<uint32_t>(rindex), sizeof(float), 0, &value);
  428. }
  429. void setProgram(const uint32_t) override
  430. {
  431. }
  432. void setMidiProgram(const uint32_t bank, const uint32_t program) override
  433. {
  434. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  435. if (fExt.programs == nullptr)
  436. return;
  437. fExt.programs->select_program(fHandle, bank, program);
  438. }
  439. void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  440. {
  441. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  442. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  443. if (fDescriptor->port_event == nullptr)
  444. return;
  445. LV2_Atom_MidiEvent midiEv;
  446. midiEv.event.time.frames = 0;
  447. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  448. midiEv.event.body.size = 3;
  449. midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
  450. midiEv.data[1] = note;
  451. midiEv.data[2] = velo;
  452. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  453. }
  454. void noteOff(const uint8_t channel, const uint8_t note) override
  455. {
  456. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  457. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  458. if (fDescriptor->port_event == nullptr)
  459. return;
  460. LV2_Atom_MidiEvent midiEv;
  461. midiEv.event.time.frames = 0;
  462. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  463. midiEv.event.body.size = 3;
  464. midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT));
  465. midiEv.data[1] = note;
  466. midiEv.data[2] = 0;
  467. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  468. }
  469. // ---------------------------------------------------------------------
  470. void waitForOscURIs()
  471. {
  472. sendOscUpdate();
  473. for (;;)
  474. {
  475. if (fIsReady || ! oscIdle(true))
  476. return;
  477. }
  478. }
  479. // ---------------------------------------------------------------------
  480. LV2_URID getCustomURID(const char* const uri)
  481. {
  482. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
  483. carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
  484. LV2_URID urid = CARLA_URI_MAP_ID_NULL;
  485. for (uint32_t i=0, count=static_cast<uint32_t>(fCustomURIDs.count()); i<count; ++i)
  486. {
  487. const char* const thisUri(fCustomURIDs.getAt(i, nullptr));
  488. if (thisUri != nullptr && std::strcmp(thisUri, uri) == 0)
  489. {
  490. urid = i;
  491. break;
  492. }
  493. }
  494. if (urid == CARLA_URI_MAP_ID_NULL)
  495. {
  496. urid = static_cast<LV2_URID>(fCustomURIDs.count());
  497. fCustomURIDs.append(carla_strdup(uri));
  498. }
  499. if (isOscControlRegistered())
  500. sendOscLv2UridMap(urid, uri);
  501. return urid;
  502. }
  503. const char* getCustomURIString(const LV2_URID urid) const noexcept
  504. {
  505. CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr);
  506. CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.count(), nullptr);
  507. carla_debug("CarlaLv2Client::getCustomURIString(%i)", urid);
  508. return fCustomURIDs.getAt(urid, nullptr);
  509. }
  510. // ---------------------------------------------------------------------
  511. void handleProgramChanged(const int32_t /*index*/)
  512. {
  513. if (isOscControlRegistered())
  514. sendOscConfigure("reloadprograms", "");
  515. }
  516. uint32_t handleUiPortMap(const char* const symbol)
  517. {
  518. CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
  519. carla_debug("CarlaLv2Client::handleUiPortMap(\"%s\")", symbol);
  520. for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
  521. {
  522. if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
  523. return i;
  524. }
  525. return LV2UI_INVALID_PORT_INDEX;
  526. }
  527. int handleUiResize(const int width, const int height)
  528. {
  529. CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
  530. CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
  531. carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height);
  532. toolkitResize(width, height);
  533. return 0;
  534. }
  535. void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  536. {
  537. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
  538. CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
  539. carla_debug("CarlaLv2Client::handleUiWrite(%i, %i, %i, %p)", portIndex, bufferSize, format, buffer);
  540. if (format == 0)
  541. {
  542. CARLA_ASSERT(buffer != nullptr);
  543. CARLA_ASSERT(bufferSize == sizeof(float));
  544. if (bufferSize != sizeof(float))
  545. return;
  546. if (buffer == nullptr || bufferSize != sizeof(float))
  547. return;
  548. const float value(*(const float*)buffer);
  549. if (isOscControlRegistered())
  550. sendOscControl(static_cast<int32_t>(portIndex), value);
  551. }
  552. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  553. {
  554. CARLA_ASSERT(bufferSize != 0);
  555. CARLA_ASSERT(buffer != nullptr);
  556. if (bufferSize == 0 || buffer == nullptr)
  557. return;
  558. if (isOscControlRegistered())
  559. sendOscLv2AtomTransfer(portIndex, CarlaString::asBase64(buffer, bufferSize).buffer());
  560. }
  561. else
  562. {
  563. carla_stdout("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format", portIndex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
  564. }
  565. }
  566. // ---------------------------------------------------------------------
  567. void handleAtomTransfer(const uint32_t portIndex, const LV2_Atom* const atom)
  568. {
  569. CARLA_ASSERT(atom != nullptr);
  570. carla_debug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
  571. if (atom != nullptr && fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  572. fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  573. }
  574. void handleUridMap(const LV2_URID urid, const char* const uri)
  575. {
  576. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
  577. carla_stdout("CarlaLv2Client::handleUridMap(%i, \"%s\")", urid, uri);
  578. if (urid == CARLA_URI_MAP_ID_NULL)
  579. {
  580. CARLA_SAFE_ASSERT_RETURN(std::strcmp(uri, "Complete") == 0,);
  581. carla_stdout("URID map from host complete");
  582. fIsReady = true;
  583. return;
  584. }
  585. const uint32_t uridCount(static_cast<uint32_t>(fCustomURIDs.count()));
  586. if (urid < uridCount)
  587. {
  588. if (const char* const ourURI = carla_lv2_urid_unmap(this, urid))
  589. {
  590. if (std::strcmp(ourURI, uri) != 0)
  591. carla_stderr2("UI :: wrong URI '%s' vs '%s'", ourURI, uri);
  592. }
  593. else
  594. {
  595. uint32_t i=0;
  596. for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
  597. {
  598. if (i != urid)
  599. continue;
  600. CARLA_SAFE_ASSERT(it.getValue() == nullptr);
  601. it.setValue(carla_strdup(uri));
  602. break;
  603. }
  604. }
  605. }
  606. else if (urid > uridCount)
  607. {
  608. for (uint32_t i=uridCount; i < urid; ++i)
  609. fCustomURIDs.append(nullptr);
  610. fCustomURIDs.append(carla_strdup(uri));
  611. }
  612. else // urid == uridCount
  613. {
  614. fCustomURIDs.append(carla_strdup(uri));
  615. }
  616. }
  617. private:
  618. LV2UI_Handle fHandle;
  619. LV2UI_Widget fWidget;
  620. LV2_Feature* fFeatures[kFeatureCount+1];
  621. const LV2UI_Descriptor* fDescriptor;
  622. const LV2_RDF_Descriptor* fRdfDescriptor;
  623. const LV2_RDF_UI* fRdfUiDescriptor;
  624. Lv2PluginOptions fOptions;
  625. bool fIsReady;
  626. bool fIsResizable;
  627. LinkedList<const char*> fCustomURIDs;
  628. struct Extensions {
  629. const LV2_Options_Interface* options;
  630. const LV2UI_Idle_Interface* idle;
  631. const LV2_Programs_UI_Interface* programs;
  632. Extensions()
  633. : options(nullptr),
  634. idle(nullptr),
  635. programs(nullptr) {}
  636. } fExt;
  637. // -------------------------------------------------------------------
  638. // Logs Feature
  639. static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
  640. {
  641. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  642. CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
  643. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  644. #ifndef DEBUG
  645. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  646. return 0;
  647. #endif
  648. va_list args;
  649. va_start(args, fmt);
  650. const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
  651. va_end(args);
  652. return ret;
  653. }
  654. static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
  655. {
  656. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  657. CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
  658. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  659. #ifndef DEBUG
  660. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  661. return 0;
  662. #endif
  663. int ret = 0;
  664. switch (type)
  665. {
  666. case CARLA_URI_MAP_ID_LOG_ERROR:
  667. std::fprintf(stderr, "\x1b[31m");
  668. ret = std::vfprintf(stderr, fmt, ap);
  669. std::fprintf(stderr, "\x1b[0m");
  670. break;
  671. case CARLA_URI_MAP_ID_LOG_NOTE:
  672. ret = std::vfprintf(stdout, fmt, ap);
  673. break;
  674. case CARLA_URI_MAP_ID_LOG_TRACE:
  675. #ifdef DEBUG
  676. std::fprintf(stdout, "\x1b[30;1m");
  677. ret = std::vfprintf(stdout, fmt, ap);
  678. std::fprintf(stdout, "\x1b[0m");
  679. #endif
  680. break;
  681. case CARLA_URI_MAP_ID_LOG_WARNING:
  682. ret = std::vfprintf(stderr, fmt, ap);
  683. break;
  684. default:
  685. break;
  686. }
  687. return ret;
  688. }
  689. // -------------------------------------------------------------------
  690. // Programs Feature
  691. static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
  692. {
  693. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  694. carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
  695. ((CarlaLv2Client*)handle)->handleProgramChanged(index);
  696. }
  697. // -------------------------------------------------------------------
  698. // State Feature
  699. static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
  700. {
  701. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  702. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
  703. carla_debug("carla_lv2_state_make_path(%p, \"%s\")", handle, path);
  704. File file;
  705. if (File::isAbsolutePath(path))
  706. file = File(path);
  707. else
  708. file = File::getCurrentWorkingDirectory().getChildFile(path);
  709. file.getParentDirectory().createDirectory();
  710. return strdup(file.getFullPathName().toRawUTF8());
  711. }
  712. static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
  713. {
  714. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  715. CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
  716. carla_debug("carla_lv2_state_map_abstract_path(%p, \"%s\")", handle, absolute_path);
  717. // may already be an abstract path
  718. if (! File::isAbsolutePath(absolute_path))
  719. return strdup(absolute_path);
  720. return strdup(File(absolute_path).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
  721. }
  722. static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
  723. {
  724. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  725. CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
  726. carla_debug("carla_lv2_state_map_absolute_path(%p, \"%s\")", handle, abstract_path);
  727. // may already be an absolute path
  728. if (File::isAbsolutePath(abstract_path))
  729. return strdup(abstract_path);
  730. return strdup(File::getCurrentWorkingDirectory().getChildFile(abstract_path).getFullPathName().toRawUTF8());
  731. }
  732. // -------------------------------------------------------------------
  733. // URI-Map Feature
  734. static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
  735. {
  736. carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
  737. return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
  738. // unused
  739. (void)map;
  740. }
  741. // -------------------------------------------------------------------
  742. // URID Feature
  743. static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
  744. {
  745. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, CARLA_URI_MAP_ID_NULL);
  746. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
  747. carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
  748. // Atom types
  749. if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
  750. return CARLA_URI_MAP_ID_ATOM_BLANK;
  751. if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
  752. return CARLA_URI_MAP_ID_ATOM_BOOL;
  753. if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
  754. return CARLA_URI_MAP_ID_ATOM_CHUNK;
  755. if (std::strcmp(uri, LV2_ATOM__Double) == 0)
  756. return CARLA_URI_MAP_ID_ATOM_DOUBLE;
  757. if (std::strcmp(uri, LV2_ATOM__Event) == 0)
  758. return CARLA_URI_MAP_ID_ATOM_EVENT;
  759. if (std::strcmp(uri, LV2_ATOM__Float) == 0)
  760. return CARLA_URI_MAP_ID_ATOM_FLOAT;
  761. if (std::strcmp(uri, LV2_ATOM__Int) == 0)
  762. return CARLA_URI_MAP_ID_ATOM_INT;
  763. if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
  764. return CARLA_URI_MAP_ID_ATOM_LITERAL;
  765. if (std::strcmp(uri, LV2_ATOM__Long) == 0)
  766. return CARLA_URI_MAP_ID_ATOM_LONG;
  767. if (std::strcmp(uri, LV2_ATOM__Number) == 0)
  768. return CARLA_URI_MAP_ID_ATOM_NUMBER;
  769. if (std::strcmp(uri, LV2_ATOM__Object) == 0)
  770. return CARLA_URI_MAP_ID_ATOM_OBJECT;
  771. if (std::strcmp(uri, LV2_ATOM__Path) == 0)
  772. return CARLA_URI_MAP_ID_ATOM_PATH;
  773. if (std::strcmp(uri, LV2_ATOM__Property) == 0)
  774. return CARLA_URI_MAP_ID_ATOM_PROPERTY;
  775. if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
  776. return CARLA_URI_MAP_ID_ATOM_RESOURCE;
  777. if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
  778. return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
  779. if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
  780. return CARLA_URI_MAP_ID_ATOM_SOUND;
  781. if (std::strcmp(uri, LV2_ATOM__String) == 0)
  782. return CARLA_URI_MAP_ID_ATOM_STRING;
  783. if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
  784. return CARLA_URI_MAP_ID_ATOM_TUPLE;
  785. if (std::strcmp(uri, LV2_ATOM__URI) == 0)
  786. return CARLA_URI_MAP_ID_ATOM_URI;
  787. if (std::strcmp(uri, LV2_ATOM__URID) == 0)
  788. return CARLA_URI_MAP_ID_ATOM_URID;
  789. if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
  790. return CARLA_URI_MAP_ID_ATOM_VECTOR;
  791. if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  792. return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
  793. if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  794. return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
  795. // BufSize types
  796. if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
  797. return CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  798. if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
  799. return CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  800. if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
  801. return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  802. // Log types
  803. if (std::strcmp(uri, LV2_LOG__Error) == 0)
  804. return CARLA_URI_MAP_ID_LOG_ERROR;
  805. if (std::strcmp(uri, LV2_LOG__Note) == 0)
  806. return CARLA_URI_MAP_ID_LOG_NOTE;
  807. if (std::strcmp(uri, LV2_LOG__Trace) == 0)
  808. return CARLA_URI_MAP_ID_LOG_TRACE;
  809. if (std::strcmp(uri, LV2_LOG__Warning) == 0)
  810. return CARLA_URI_MAP_ID_LOG_WARNING;
  811. // Time types
  812. if (std::strcmp(uri, LV2_TIME__Position) == 0)
  813. return CARLA_URI_MAP_ID_TIME_POSITION;
  814. if (std::strcmp(uri, LV2_TIME__bar) == 0)
  815. return CARLA_URI_MAP_ID_TIME_BAR;
  816. if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
  817. return CARLA_URI_MAP_ID_TIME_BAR_BEAT;
  818. if (std::strcmp(uri, LV2_TIME__beat) == 0)
  819. return CARLA_URI_MAP_ID_TIME_BEAT;
  820. if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
  821. return CARLA_URI_MAP_ID_TIME_BEAT_UNIT;
  822. if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
  823. return CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR;
  824. if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
  825. return CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE;
  826. if (std::strcmp(uri, LV2_TIME__frame) == 0)
  827. return CARLA_URI_MAP_ID_TIME_FRAME;
  828. if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
  829. return CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND;
  830. if (std::strcmp(uri, LV2_TIME__speed) == 0)
  831. return CARLA_URI_MAP_ID_TIME_SPEED;
  832. // Others
  833. if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  834. return CARLA_URI_MAP_ID_MIDI_EVENT;
  835. if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
  836. return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  837. // Custom
  838. if (std::strcmp(uri, URI_CARLA_FRONTEND_WIN_ID) == 0)
  839. return CARLA_URI_MAP_ID_FRONTEND_WIN_ID;
  840. if (std::strcmp(uri, URI_CARLA_WORKER) == 0)
  841. return CARLA_URI_MAP_ID_ATOM_WORKER;
  842. // Custom types
  843. return ((CarlaLv2Client*)handle)->getCustomURID(uri);
  844. }
  845. static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  846. {
  847. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  848. CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr);
  849. carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
  850. // Atom types
  851. if (urid == CARLA_URI_MAP_ID_ATOM_BLANK)
  852. return LV2_ATOM__Blank;
  853. if (urid == CARLA_URI_MAP_ID_ATOM_BOOL)
  854. return LV2_ATOM__Bool;
  855. if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
  856. return LV2_ATOM__Chunk;
  857. if (urid == CARLA_URI_MAP_ID_ATOM_DOUBLE)
  858. return LV2_ATOM__Double;
  859. if (urid == CARLA_URI_MAP_ID_ATOM_EVENT)
  860. return LV2_ATOM__Event;
  861. if (urid == CARLA_URI_MAP_ID_ATOM_FLOAT)
  862. return LV2_ATOM__Float;
  863. if (urid == CARLA_URI_MAP_ID_ATOM_INT)
  864. return LV2_ATOM__Int;
  865. if (urid == CARLA_URI_MAP_ID_ATOM_LITERAL)
  866. return LV2_ATOM__Literal;
  867. if (urid == CARLA_URI_MAP_ID_ATOM_LONG)
  868. return LV2_ATOM__Long;
  869. if (urid == CARLA_URI_MAP_ID_ATOM_NUMBER)
  870. return LV2_ATOM__Number;
  871. if (urid == CARLA_URI_MAP_ID_ATOM_OBJECT)
  872. return LV2_ATOM__Object;
  873. if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
  874. return LV2_ATOM__Path;
  875. if (urid == CARLA_URI_MAP_ID_ATOM_PROPERTY)
  876. return LV2_ATOM__Property;
  877. if (urid == CARLA_URI_MAP_ID_ATOM_RESOURCE)
  878. return LV2_ATOM__Resource;
  879. if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
  880. return LV2_ATOM__Sequence;
  881. if (urid == CARLA_URI_MAP_ID_ATOM_SOUND)
  882. return LV2_ATOM__Sound;
  883. if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
  884. return LV2_ATOM__String;
  885. if (urid == CARLA_URI_MAP_ID_ATOM_TUPLE)
  886. return LV2_ATOM__Tuple;
  887. if (urid == CARLA_URI_MAP_ID_ATOM_URI)
  888. return LV2_ATOM__URI;
  889. if (urid == CARLA_URI_MAP_ID_ATOM_URID)
  890. return LV2_ATOM__URID;
  891. if (urid == CARLA_URI_MAP_ID_ATOM_VECTOR)
  892. return LV2_ATOM__Vector;
  893. if (urid == CARLA_URI_MAP_ID_ATOM_WORKER)
  894. return URI_CARLA_WORKER; // custom
  895. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  896. return LV2_ATOM__atomTransfer;
  897. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  898. return LV2_ATOM__eventTransfer;
  899. // BufSize types
  900. if (urid == CARLA_URI_MAP_ID_BUF_MAX_LENGTH)
  901. return LV2_BUF_SIZE__maxBlockLength;
  902. if (urid == CARLA_URI_MAP_ID_BUF_MIN_LENGTH)
  903. return LV2_BUF_SIZE__minBlockLength;
  904. if (urid == CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE)
  905. return LV2_BUF_SIZE__sequenceSize;
  906. // Log types
  907. if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
  908. return LV2_LOG__Error;
  909. if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
  910. return LV2_LOG__Note;
  911. if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
  912. return LV2_LOG__Trace;
  913. if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
  914. return LV2_LOG__Warning;
  915. // Time types
  916. if (urid == CARLA_URI_MAP_ID_TIME_POSITION)
  917. return LV2_TIME__Position;
  918. if (urid == CARLA_URI_MAP_ID_TIME_BAR)
  919. return LV2_TIME__bar;
  920. if (urid == CARLA_URI_MAP_ID_TIME_BAR_BEAT)
  921. return LV2_TIME__barBeat;
  922. if (urid == CARLA_URI_MAP_ID_TIME_BEAT)
  923. return LV2_TIME__beat;
  924. if (urid == CARLA_URI_MAP_ID_TIME_BEAT_UNIT)
  925. return LV2_TIME__beatUnit;
  926. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR)
  927. return LV2_TIME__beatsPerBar;
  928. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE)
  929. return LV2_TIME__beatsPerMinute;
  930. if (urid == CARLA_URI_MAP_ID_TIME_FRAME)
  931. return LV2_TIME__frame;
  932. if (urid == CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND)
  933. return LV2_TIME__framesPerSecond;
  934. if (urid == CARLA_URI_MAP_ID_TIME_SPEED)
  935. return LV2_TIME__speed;
  936. // Others
  937. if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
  938. return LV2_MIDI__MidiEvent;
  939. if (urid == CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE)
  940. return LV2_PARAMETERS__sampleRate;
  941. if (urid == CARLA_URI_MAP_ID_FRONTEND_WIN_ID)
  942. return URI_CARLA_FRONTEND_WIN_ID;
  943. // Custom types
  944. return ((CarlaLv2Client*)handle)->getCustomURIString(urid);
  945. }
  946. // -------------------------------------------------------------------
  947. // UI Port-Map Feature
  948. static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
  949. {
  950. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
  951. carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
  952. return ((CarlaLv2Client*)handle)->handleUiPortMap(symbol);
  953. }
  954. // -------------------------------------------------------------------
  955. // UI Resize Feature
  956. static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
  957. {
  958. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
  959. carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  960. return ((CarlaLv2Client*)handle)->handleUiResize(width, height);
  961. }
  962. // -------------------------------------------------------------------
  963. // UI Extension
  964. static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
  965. {
  966. CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
  967. carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  968. ((CarlaLv2Client*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
  969. }
  970. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client)
  971. };
  972. #define lv2ClientPtr ((CarlaLv2Client*)kClient)
  973. int CarlaBridgeOsc::handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  974. {
  975. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  976. carla_debug("CarlaBridgeOsc::handleMsgLv2AtomTransfer()");
  977. if (kClient == nullptr)
  978. return 1;
  979. const int32_t portIndex = argv[0]->i;
  980. const char* const atomBuf = (const char*)&argv[1]->s;
  981. if (portIndex < 0)
  982. return 0;
  983. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(atomBuf));
  984. CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, 0);
  985. const LV2_Atom* const atom((const LV2_Atom*)chunk.data());
  986. lv2ClientPtr->handleAtomTransfer(static_cast<uint32_t>(portIndex), atom);
  987. return 0;
  988. }
  989. int CarlaBridgeOsc::handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  990. {
  991. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  992. carla_debug("CarlaBridgeOsc::handleMsgLv2UridMap()");
  993. if (kClient == nullptr)
  994. return 1;
  995. const int32_t urid = argv[0]->i;
  996. const char* const uri = (const char*)&argv[1]->s;
  997. if (urid < 0)
  998. return 0;
  999. lv2ClientPtr->handleUridMap(static_cast<LV2_URID>(urid), uri);
  1000. return 0;
  1001. }
  1002. #undef lv2ClientPtr
  1003. CARLA_BRIDGE_END_NAMESPACE
  1004. int main(int argc, char* argv[])
  1005. {
  1006. CARLA_BRIDGE_USE_NAMESPACE
  1007. if (argc != 6)
  1008. {
  1009. carla_stderr("usage: %s <osc-url|\"null\"> <plugin-bundle> <plugin-uri> <ui-uri> <ui-title>", argv[0]);
  1010. return 1;
  1011. }
  1012. const char* oscUrl = argv[1];
  1013. const char* pluginURI = argv[2];
  1014. const char* uiURI = argv[3];
  1015. const char* uiBundle = argv[4];
  1016. const char* uiTitle = argv[5];
  1017. const bool useOsc(std::strcmp(oscUrl, "null") != 0);
  1018. // try to get sampleRate value
  1019. if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE"))
  1020. gSampleRate = std::atof(sampleRateStr);
  1021. // Init LV2 client
  1022. CarlaLv2Client client(uiTitle);
  1023. // Init OSC
  1024. if (useOsc)
  1025. {
  1026. client.oscInit(oscUrl);
  1027. client.waitForOscURIs();
  1028. }
  1029. // Load UI
  1030. int ret;
  1031. if (client.uiInit(pluginURI, uiURI, uiBundle))
  1032. {
  1033. client.toolkitExec(!useOsc);
  1034. ret = 0;
  1035. }
  1036. else
  1037. {
  1038. ret = 1;
  1039. }
  1040. // Close OSC
  1041. if (useOsc)
  1042. client.oscClose();
  1043. // Close LV2 client
  1044. client.uiClose();
  1045. return ret;
  1046. }