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.

1564 lines
55KB

  1. /*
  2. * Carla Bridge UI
  3. * Copyright (C) 2011-2019 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 "CarlaBridgeFormat.hpp"
  18. #include "CarlaBridgeToolkit.hpp"
  19. #include "CarlaLibUtils.hpp"
  20. #include "CarlaLv2Utils.hpp"
  21. #include "CarlaMIDI.h"
  22. #include "LinkedList.hpp"
  23. #include "water/files/File.h"
  24. #ifdef CARLA_OS_MAC
  25. # include "CarlaMacUtils.hpp"
  26. #endif
  27. #include <string>
  28. #include <vector>
  29. #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn"
  30. #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp"
  31. #define URI_CARLA_PARAMETER_CHANGE "http://kxstudio.sf.net/ns/carla/parameterChange"
  32. using water::File;
  33. CARLA_BRIDGE_UI_START_NAMESPACE
  34. // --------------------------------------------------------------------------------------------------------------------
  35. static double gInitialSampleRate = 44100.0;
  36. static const char* const kNullWindowTitle = "TestUI";
  37. static const uint32_t kNullWindowTitleSize = 6;
  38. static const char* const kUnmapFallback = "urn:null";
  39. // LV2 URI Map Ids
  40. enum CarlaLv2URIDs {
  41. kUridNull = 0,
  42. kUridAtomBlank,
  43. kUridAtomBool,
  44. kUridAtomChunk,
  45. kUridAtomDouble,
  46. kUridAtomEvent,
  47. kUridAtomFloat,
  48. kUridAtomInt,
  49. kUridAtomLiteral,
  50. kUridAtomLong,
  51. kUridAtomNumber,
  52. kUridAtomObject,
  53. kUridAtomPath,
  54. kUridAtomProperty,
  55. kUridAtomResource,
  56. kUridAtomSequence,
  57. kUridAtomSound,
  58. kUridAtomString,
  59. kUridAtomTuple,
  60. kUridAtomURI,
  61. kUridAtomURID,
  62. kUridAtomVector,
  63. kUridAtomTransferAtom,
  64. kUridAtomTransferEvent,
  65. kUridBufMaxLength,
  66. kUridBufMinLength,
  67. kUridBufNominalLength,
  68. kUridBufSequenceSize,
  69. kUridLogError,
  70. kUridLogNote,
  71. kUridLogTrace,
  72. kUridLogWarning,
  73. kUridPatchSet,
  74. kUridPatchProperty,
  75. kUridPatchSubject,
  76. kUridPatchValue,
  77. // time base type
  78. kUridTimePosition,
  79. // time values
  80. kUridTimeBar,
  81. kUridTimeBarBeat,
  82. kUridTimeBeat,
  83. kUridTimeBeatUnit,
  84. kUridTimeBeatsPerBar,
  85. kUridTimeBeatsPerMinute,
  86. kUridTimeFrame,
  87. kUridTimeFramesPerSecond,
  88. kUridTimeSpeed,
  89. kUridTimeTicksPerBeat,
  90. kUridMidiEvent,
  91. kUridParamSampleRate,
  92. // ui stuff
  93. kUridBackgroundColor,
  94. kUridForegroundColor,
  95. kUridScaleFactor,
  96. kUridWindowTitle,
  97. // custom carla props
  98. kUridCarlaAtomWorkerIn,
  99. kUridCarlaAtomWorkerResp,
  100. kUridCarlaParameterChange,
  101. kUridCarlaTransientWindowId,
  102. // count
  103. kUridCount
  104. };
  105. // LV2 Feature Ids
  106. enum CarlaLv2Features {
  107. // DSP features
  108. kFeatureIdLogs = 0,
  109. kFeatureIdOptions,
  110. kFeatureIdPrograms,
  111. kFeatureIdStateFreePath,
  112. kFeatureIdStateMakePath,
  113. kFeatureIdStateMapPath,
  114. kFeatureIdUriMap,
  115. kFeatureIdUridMap,
  116. kFeatureIdUridUnmap,
  117. kFeatureIdUiIdleInterface,
  118. kFeatureIdUiFixedSize,
  119. kFeatureIdUiMakeResident,
  120. kFeatureIdUiMakeResident2,
  121. kFeatureIdUiNoUserResize,
  122. kFeatureIdUiParent,
  123. kFeatureIdUiPortMap,
  124. kFeatureIdUiPortSubscribe,
  125. kFeatureIdUiRequestValue,
  126. kFeatureIdUiResize,
  127. kFeatureIdUiTouch,
  128. kFeatureCount
  129. };
  130. // --------------------------------------------------------------------------------------------------------------------
  131. struct Lv2PluginOptions {
  132. enum OptIndex {
  133. SampleRate,
  134. TransientWinId,
  135. BackgroundColor,
  136. ForegroundColor,
  137. ScaleFactor,
  138. WindowTitle,
  139. Null,
  140. Count
  141. };
  142. float sampleRate;
  143. int64_t transientWinId;
  144. uint32_t bgColor;
  145. uint32_t fgColor;
  146. float uiScale;
  147. LV2_Options_Option opts[Count];
  148. Lv2PluginOptions() noexcept
  149. : sampleRate(static_cast<float>(gInitialSampleRate)),
  150. transientWinId(0),
  151. bgColor(0x000000ff),
  152. fgColor(0xffffffff),
  153. uiScale(1.0f)
  154. {
  155. LV2_Options_Option& optSampleRate(opts[SampleRate]);
  156. optSampleRate.context = LV2_OPTIONS_INSTANCE;
  157. optSampleRate.subject = 0;
  158. optSampleRate.key = kUridParamSampleRate;
  159. optSampleRate.size = sizeof(float);
  160. optSampleRate.type = kUridAtomFloat;
  161. optSampleRate.value = &sampleRate;
  162. LV2_Options_Option& optBackgroundColor(opts[BackgroundColor]);
  163. optBackgroundColor.context = LV2_OPTIONS_INSTANCE;
  164. optBackgroundColor.subject = 0;
  165. optBackgroundColor.key = kUridBackgroundColor;
  166. optBackgroundColor.size = sizeof(int32_t);
  167. optBackgroundColor.type = kUridAtomInt;
  168. optBackgroundColor.value = &bgColor;
  169. LV2_Options_Option& optForegroundColor(opts[ForegroundColor]);
  170. optForegroundColor.context = LV2_OPTIONS_INSTANCE;
  171. optForegroundColor.subject = 0;
  172. optForegroundColor.key = kUridForegroundColor;
  173. optForegroundColor.size = sizeof(int32_t);
  174. optForegroundColor.type = kUridAtomInt;
  175. optForegroundColor.value = &fgColor;
  176. LV2_Options_Option& optScaleFactor(opts[ScaleFactor]);
  177. optScaleFactor.context = LV2_OPTIONS_INSTANCE;
  178. optScaleFactor.subject = 0;
  179. optScaleFactor.key = kUridScaleFactor;
  180. optScaleFactor.size = sizeof(float);
  181. optScaleFactor.type = kUridAtomFloat;
  182. optScaleFactor.value = &uiScale;
  183. LV2_Options_Option& optTransientWinId(opts[TransientWinId]);
  184. optTransientWinId.context = LV2_OPTIONS_INSTANCE;
  185. optTransientWinId.subject = 0;
  186. optTransientWinId.key = kUridCarlaTransientWindowId;
  187. optTransientWinId.size = sizeof(int64_t);
  188. optTransientWinId.type = kUridAtomLong;
  189. optTransientWinId.value = &transientWinId;
  190. LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
  191. optWindowTitle.context = LV2_OPTIONS_INSTANCE;
  192. optWindowTitle.subject = 0;
  193. optWindowTitle.key = kUridWindowTitle;
  194. optWindowTitle.size = kNullWindowTitleSize;
  195. optWindowTitle.type = kUridAtomString;
  196. optWindowTitle.value = kNullWindowTitle;
  197. LV2_Options_Option& optNull(opts[Null]);
  198. optNull.context = LV2_OPTIONS_INSTANCE;
  199. optNull.subject = 0;
  200. optNull.key = kUridNull;
  201. optNull.size = 0;
  202. optNull.type = kUridNull;
  203. optNull.value = nullptr;
  204. }
  205. };
  206. // -------------------------------------------------------------------------------------------------------------------
  207. static void initAtomForge(LV2_Atom_Forge& atomForge) noexcept
  208. {
  209. carla_zeroStruct(atomForge);
  210. atomForge.Bool = kUridAtomBool;
  211. atomForge.Chunk = kUridAtomChunk;
  212. atomForge.Double = kUridAtomDouble;
  213. atomForge.Float = kUridAtomFloat;
  214. atomForge.Int = kUridAtomInt;
  215. atomForge.Literal = kUridAtomLiteral;
  216. atomForge.Long = kUridAtomLong;
  217. atomForge.Object = kUridAtomObject;
  218. atomForge.Path = kUridAtomPath;
  219. atomForge.Property = kUridAtomProperty;
  220. atomForge.Sequence = kUridAtomSequence;
  221. atomForge.String = kUridAtomString;
  222. atomForge.Tuple = kUridAtomTuple;
  223. atomForge.URI = kUridAtomURI;
  224. atomForge.URID = kUridAtomURID;
  225. atomForge.Vector = kUridAtomVector;
  226. #if defined(__clang__)
  227. # pragma clang diagnostic push
  228. # pragma clang diagnostic ignored "-Wdeprecated-declarations"
  229. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  230. # pragma GCC diagnostic push
  231. # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  232. #endif
  233. atomForge.Blank = kUridAtomBlank;
  234. atomForge.Resource = kUridAtomResource;
  235. #if defined(__clang__)
  236. # pragma clang diagnostic pop
  237. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  238. # pragma GCC diagnostic pop
  239. #endif
  240. }
  241. // --------------------------------------------------------------------------------------------------------------------
  242. class CarlaLv2Client : public CarlaBridgeFormat
  243. {
  244. public:
  245. CarlaLv2Client()
  246. : CarlaBridgeFormat(),
  247. fHandle(nullptr),
  248. fWidget(nullptr),
  249. fDescriptor(nullptr),
  250. fRdfDescriptor(nullptr),
  251. fRdfUiDescriptor(nullptr),
  252. fControlDesignatedPort(0),
  253. fLv2Options(),
  254. fUiOptions(),
  255. fCustomURIDs(kUridCount, std::string("urn:null")),
  256. fExt()
  257. {
  258. CARLA_SAFE_ASSERT(fCustomURIDs.size() == kUridCount);
  259. carla_zeroPointers(fFeatures, kFeatureCount+1);
  260. // ------------------------------------------------------------------------------------------------------------
  261. // initialize features (part 1)
  262. LV2_Log_Log* const logFt = new LV2_Log_Log;
  263. logFt->handle = this;
  264. logFt->printf = carla_lv2_log_printf;
  265. logFt->vprintf = carla_lv2_log_vprintf;
  266. LV2_State_Free_Path* const stateFreePathFt = new LV2_State_Free_Path;
  267. stateFreePathFt->handle = this;
  268. stateFreePathFt->free_path = carla_lv2_state_free_path;
  269. LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
  270. stateMakePathFt->handle = this;
  271. stateMakePathFt->path = carla_lv2_state_make_path_tmp;
  272. LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
  273. stateMapPathFt->handle = this;
  274. stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path_tmp;
  275. stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path_tmp;
  276. LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
  277. programsFt->handle = this;
  278. programsFt->program_changed = carla_lv2_program_changed;
  279. LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
  280. uriMapFt->callback_data = this;
  281. uriMapFt->uri_to_id = carla_lv2_uri_to_id;
  282. LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
  283. uridMapFt->handle = this;
  284. uridMapFt->map = carla_lv2_urid_map;
  285. LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
  286. uridUnmapFt->handle = this;
  287. uridUnmapFt->unmap = carla_lv2_urid_unmap;
  288. LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
  289. uiPortMapFt->handle = this;
  290. uiPortMapFt->port_index = carla_lv2_ui_port_map;
  291. LV2UI_Request_Value* const uiRequestValueFt = new LV2UI_Request_Value;
  292. uiRequestValueFt->handle = this;
  293. uiRequestValueFt->request = carla_lv2_ui_request_value;
  294. LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
  295. uiResizeFt->handle = this;
  296. uiResizeFt->ui_resize = carla_lv2_ui_resize;
  297. // ------------------------------------------------------------------------------------------------------------
  298. // initialize features (part 2)
  299. for (uint32_t i=0; i < kFeatureCount; ++i)
  300. fFeatures[i] = new LV2_Feature;
  301. fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
  302. fFeatures[kFeatureIdLogs]->data = logFt;
  303. fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
  304. fFeatures[kFeatureIdOptions]->data = fLv2Options.opts;
  305. fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
  306. fFeatures[kFeatureIdPrograms]->data = programsFt;
  307. fFeatures[kFeatureIdStateFreePath]->URI = LV2_STATE__freePath;
  308. fFeatures[kFeatureIdStateFreePath]->data = stateFreePathFt;
  309. fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
  310. fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
  311. fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
  312. fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
  313. fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
  314. fFeatures[kFeatureIdUriMap]->data = uriMapFt;
  315. fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
  316. fFeatures[kFeatureIdUridMap]->data = uridMapFt;
  317. fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
  318. fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
  319. fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
  320. fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
  321. fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
  322. fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
  323. fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
  324. fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
  325. fFeatures[kFeatureIdUiMakeResident2]->URI = LV2_UI__makeSONameResident;
  326. fFeatures[kFeatureIdUiMakeResident2]->data = nullptr;
  327. fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
  328. fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
  329. fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
  330. fFeatures[kFeatureIdUiParent]->data = nullptr;
  331. fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
  332. fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
  333. fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
  334. fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
  335. fFeatures[kFeatureIdUiRequestValue]->URI = LV2_UI__requestValue;
  336. fFeatures[kFeatureIdUiRequestValue]->data = uiRequestValueFt;
  337. fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
  338. fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
  339. fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
  340. fFeatures[kFeatureIdUiTouch]->data = nullptr;
  341. }
  342. ~CarlaLv2Client() override
  343. {
  344. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr)
  345. {
  346. fDescriptor->cleanup(fHandle);
  347. fHandle = nullptr;
  348. }
  349. if (fRdfDescriptor != nullptr)
  350. {
  351. delete fRdfDescriptor;
  352. fRdfDescriptor = nullptr;
  353. }
  354. fRdfUiDescriptor = nullptr;
  355. delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
  356. delete (LV2_State_Free_Path*)fFeatures[kFeatureIdStateFreePath]->data;
  357. delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
  358. delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
  359. delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
  360. delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
  361. delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
  362. delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
  363. delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
  364. delete (LV2UI_Request_Value*)fFeatures[kFeatureIdUiRequestValue]->data;
  365. delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
  366. for (uint32_t i=0; i < kFeatureCount; ++i)
  367. {
  368. if (fFeatures[i] != nullptr)
  369. {
  370. delete fFeatures[i];
  371. fFeatures[i] = nullptr;
  372. }
  373. }
  374. }
  375. // ----------------------------------------------------------------------------------------------------------------
  376. // UI initialization
  377. bool init(const int argc, const char* argv[]) override
  378. {
  379. const char* pluginURI = argv[1];
  380. const char* uiURI = argc > 2 ? argv[2] : nullptr;
  381. // ------------------------------------------------------------------------------------------------------------
  382. // load plugin
  383. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  384. lv2World.initIfNeeded(std::getenv("LV2_PATH"));
  385. #if 0
  386. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, uiBundle));
  387. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(), false);
  388. CarlaString sBundle(bundleNode.as_uri());
  389. if (! sBundle.endsWith("/"))
  390. sBundle += "/";
  391. lv2World.load_bundle(sBundle);
  392. #endif
  393. // ------------------------------------------------------------------------------------------------------------
  394. // get plugin from lv2_rdf (lilv)
  395. fRdfDescriptor = lv2_rdf_new(pluginURI, false);
  396. CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
  397. // ------------------------------------------------------------------------------------------------------------
  398. // find requested UI
  399. if (uiURI == nullptr)
  400. {
  401. CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor->UICount > 0, false);
  402. fRdfUiDescriptor = &fRdfDescriptor->UIs[0];
  403. uiURI = fRdfUiDescriptor->URI;
  404. }
  405. else
  406. {
  407. for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
  408. {
  409. if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
  410. {
  411. fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
  412. break;
  413. }
  414. }
  415. }
  416. CARLA_SAFE_ASSERT_RETURN(fRdfUiDescriptor != nullptr, false);
  417. // ------------------------------------------------------------------------------------------------------------
  418. // check if not resizable
  419. for (uint32_t i=0; i < fRdfUiDescriptor->FeatureCount; ++i)
  420. {
  421. if (std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__fixedSize ) == 0 ||
  422. std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
  423. {
  424. fUiOptions.isResizable = false;
  425. break;
  426. }
  427. }
  428. // ------------------------------------------------------------------------------------------------------------
  429. // init UI
  430. if (! CarlaBridgeFormat::init(argc, argv))
  431. return false;
  432. // ------------------------------------------------------------------------------------------------------------
  433. // open DLL
  434. #ifdef CARLA_OS_MAC
  435. // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
  436. CarlaBackend::removeFileFromQuarantine(fRdfUiDescriptor->Binary);
  437. #endif
  438. if (! libOpen(fRdfUiDescriptor->Binary))
  439. {
  440. carla_stderr("Failed to load UI binary, error was:\n%s", libError());
  441. return false;
  442. }
  443. // ------------------------------------------------------------------------------------------------------------
  444. // get DLL main entry
  445. const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)libSymbol("lv2ui_descriptor");
  446. if (ui_descFn == nullptr)
  447. return false;
  448. // ------------------------------------------------------------------------------------------------------------
  449. // get descriptor that matches URI
  450. for (uint32_t i=0; (fDescriptor = ui_descFn(i++)) != nullptr;)
  451. {
  452. if (std::strcmp(fDescriptor->URI, uiURI) == 0)
  453. break;
  454. }
  455. if (fDescriptor == nullptr)
  456. {
  457. carla_stderr("Failed to find UI descriptor");
  458. return false;
  459. }
  460. // ------------------------------------------------------------------------------------------------------------
  461. // initialize UI
  462. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  463. fFeatures[kFeatureIdUiParent]->data = fToolkit->getContainerId();
  464. #endif
  465. fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle,
  466. carla_lv2_ui_write_function, this, &fWidget, fFeatures);
  467. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
  468. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  469. if (fWidget != nullptr)
  470. fToolkit->setChildWindow(fWidget);
  471. #endif
  472. // ------------------------------------------------------------------------------------------------------------
  473. // check for known extensions
  474. if (fDescriptor->extension_data != nullptr)
  475. {
  476. fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
  477. fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
  478. fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
  479. fExt.resize = (const LV2UI_Resize*)fDescriptor->extension_data(LV2_UI__resize);
  480. // check if invalid
  481. if (fExt.programs != nullptr && fExt.programs->select_program == nullptr)
  482. fExt.programs = nullptr;
  483. if (fExt.idle != nullptr && fExt.idle->idle == nullptr)
  484. fExt.idle = nullptr;
  485. if (fExt.resize != nullptr && fExt.resize->ui_resize == nullptr)
  486. fExt.resize = nullptr;
  487. }
  488. for (uint32_t i=0; i<fRdfDescriptor->PortCount; ++i)
  489. {
  490. if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
  491. {
  492. fControlDesignatedPort = i;
  493. break;
  494. }
  495. }
  496. return true;
  497. }
  498. void idleUI() override
  499. {
  500. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  501. if (fHandle != nullptr && fExt.idle != nullptr && fExt.idle->idle(fHandle) != 0)
  502. {
  503. if (isPipeRunning() && ! fQuitReceived)
  504. writeExitingMessageAndWait();
  505. }
  506. #endif
  507. }
  508. // ----------------------------------------------------------------------------------------------------------------
  509. // UI management
  510. void* getWidget() const noexcept override
  511. {
  512. return fWidget;
  513. }
  514. const Options& getOptions() const noexcept override
  515. {
  516. return fUiOptions;
  517. }
  518. // ----------------------------------------------------------------------------------------------------------------
  519. // DSP Callbacks
  520. void dspParameterChanged(const uint32_t index, const float value) override
  521. {
  522. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  523. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  524. if (fDescriptor->port_event == nullptr)
  525. return;
  526. fDescriptor->port_event(fHandle, index, sizeof(float), kUridNull, &value);
  527. }
  528. void dspParameterChanged(const char* const uri, const float value) override
  529. {
  530. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  531. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  532. if (fDescriptor->port_event == nullptr)
  533. return;
  534. uint32_t parameterId = UINT32_MAX;
  535. for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
  536. {
  537. const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
  538. if (std::strcmp(rdfParam.URI, uri) == 0)
  539. {
  540. parameterId = i;
  541. break;
  542. }
  543. }
  544. if (parameterId == UINT32_MAX)
  545. return;
  546. uint8_t atomBuf[256];
  547. LV2_Atom_Forge atomForge;
  548. initAtomForge(atomForge);
  549. lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
  550. LV2_Atom_Forge_Frame forgeFrame;
  551. lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
  552. lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
  553. lv2_atom_forge_bool(&atomForge, true);
  554. lv2_atom_forge_key(&atomForge, kUridPatchProperty);
  555. lv2_atom_forge_urid(&atomForge, getCustomURID(uri));
  556. lv2_atom_forge_key(&atomForge, kUridPatchValue);
  557. switch (fRdfDescriptor->Parameters[parameterId].Type)
  558. {
  559. case LV2_PARAMETER_TYPE_BOOL:
  560. lv2_atom_forge_bool(&atomForge, value > 0.5f);
  561. break;
  562. case LV2_PARAMETER_TYPE_INT:
  563. lv2_atom_forge_int(&atomForge, static_cast<int32_t>(value + 0.5f));
  564. break;
  565. case LV2_PARAMETER_TYPE_LONG:
  566. lv2_atom_forge_long(&atomForge, static_cast<int64_t>(value + 0.5f));
  567. break;
  568. case LV2_PARAMETER_TYPE_FLOAT:
  569. lv2_atom_forge_float(&atomForge, value);
  570. break;
  571. case LV2_PARAMETER_TYPE_DOUBLE:
  572. lv2_atom_forge_double(&atomForge, value);
  573. break;
  574. default:
  575. carla_stderr2("dspParameterChanged called for invalid parameter, abort!");
  576. return;
  577. }
  578. lv2_atom_forge_pop(&atomForge, &forgeFrame);
  579. LV2_Atom* const atom((LV2_Atom*)atomBuf);
  580. CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
  581. fDescriptor->port_event(fHandle,
  582. fControlDesignatedPort,
  583. lv2_atom_total_size(atom),
  584. kUridAtomTransferEvent,
  585. atom);
  586. }
  587. void dspProgramChanged(const uint32_t index) override
  588. {
  589. carla_stderr2("dspProgramChanged(%i) - not handled", index);
  590. }
  591. void dspMidiProgramChanged(const uint32_t bank, const uint32_t program) override
  592. {
  593. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  594. if (fExt.programs == nullptr)
  595. return;
  596. fExt.programs->select_program(fHandle, bank, program);
  597. }
  598. void dspStateChanged(const char* const, const char* const) override
  599. {
  600. }
  601. void dspNoteReceived(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) override
  602. {
  603. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
  604. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  605. if (fDescriptor->port_event == nullptr)
  606. return;
  607. LV2_Atom_MidiEvent midiEv;
  608. midiEv.atom.type = kUridMidiEvent;
  609. midiEv.atom.size = 3;
  610. midiEv.data[0] = uint8_t((onOff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (channel & MIDI_CHANNEL_BIT));
  611. midiEv.data[1] = note;
  612. midiEv.data[2] = velocity;
  613. fDescriptor->port_event(fHandle, fControlDesignatedPort, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
  614. }
  615. void dspAtomReceived(const uint32_t portIndex, const LV2_Atom* const atom) override
  616. {
  617. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  618. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  619. CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
  620. if (fDescriptor->port_event == nullptr)
  621. return;
  622. fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
  623. }
  624. void dspURIDReceived(const LV2_URID urid, const char* const uri) override
  625. {
  626. CARLA_SAFE_ASSERT_RETURN(urid == fCustomURIDs.size(),);
  627. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
  628. fCustomURIDs.push_back(uri);
  629. }
  630. void uiOptionsChanged(const BridgeFormatOptions& opts) override
  631. {
  632. carla_debug("CarlaLv2Client::uiOptionsChanged()");
  633. // ------------------------------------------------------------------------------------------------------------
  634. // sample rate
  635. const float sampleRatef = static_cast<float>(opts.sampleRate);
  636. if (carla_isNotEqual(fLv2Options.sampleRate, sampleRatef))
  637. {
  638. fLv2Options.sampleRate = sampleRatef;
  639. if (fExt.options != nullptr && fExt.options->set != nullptr)
  640. {
  641. LV2_Options_Option options[2];
  642. carla_zeroStructs(options, 2);
  643. LV2_Options_Option& optSampleRate(options[0]);
  644. optSampleRate.context = LV2_OPTIONS_INSTANCE;
  645. optSampleRate.subject = 0;
  646. optSampleRate.key = kUridParamSampleRate;
  647. optSampleRate.size = sizeof(float);
  648. optSampleRate.type = kUridAtomFloat;
  649. optSampleRate.value = &fLv2Options.sampleRate;
  650. fExt.options->set(fHandle, options);
  651. }
  652. }
  653. // ------------------------------------------------------------------------------------------------------------
  654. // ui colors and scale
  655. fLv2Options.bgColor = opts.bgColor;
  656. fLv2Options.fgColor = opts.fgColor;
  657. fLv2Options.uiScale = opts.uiScale;
  658. // ------------------------------------------------------------------------------------------------------------
  659. // window title
  660. if (opts.windowTitle != nullptr)
  661. fUiOptions.windowTitle = opts.windowTitle;
  662. else
  663. fUiOptions.windowTitle.clear();
  664. fLv2Options.opts[Lv2PluginOptions::WindowTitle].size = static_cast<uint32_t>(fUiOptions.windowTitle.length());
  665. fLv2Options.opts[Lv2PluginOptions::WindowTitle].value = fUiOptions.windowTitle.buffer();
  666. // ------------------------------------------------------------------------------------------------------------
  667. // transient win id
  668. fLv2Options.transientWinId = static_cast<int64_t>(opts.transientWindowId);
  669. fUiOptions.transientWindowId = opts.transientWindowId;
  670. // ------------------------------------------------------------------------------------------------------------
  671. // other
  672. fUiOptions.useTheme = opts.useTheme;
  673. fUiOptions.useThemeColors = opts.useThemeColors;
  674. }
  675. void uiResized(const uint width, const uint height) override
  676. {
  677. if (fHandle != nullptr && fExt.resize != nullptr)
  678. fExt.resize->ui_resize(fHandle, static_cast<int>(width), static_cast<int>(height));
  679. }
  680. // ----------------------------------------------------------------------------------------------------------------
  681. LV2_URID getCustomURID(const char* const uri)
  682. {
  683. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
  684. carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
  685. const std::string s_uri(uri);
  686. const std::ptrdiff_t s_pos(std::find(fCustomURIDs.begin(), fCustomURIDs.end(), s_uri) - fCustomURIDs.begin());
  687. if (s_pos <= 0 || s_pos >= INT32_MAX)
  688. return kUridNull;
  689. const LV2_URID urid = static_cast<LV2_URID>(s_pos);
  690. const LV2_URID uriCount = static_cast<LV2_URID>(fCustomURIDs.size());
  691. if (urid < uriCount)
  692. return urid;
  693. CARLA_SAFE_ASSERT(urid == uriCount);
  694. fCustomURIDs.push_back(uri);
  695. if (isPipeRunning())
  696. writeLv2UridMessage(urid, uri);
  697. return urid;
  698. }
  699. const char* getCustomURIDString(const LV2_URID urid) const noexcept
  700. {
  701. CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, kUnmapFallback);
  702. CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.size(), kUnmapFallback);
  703. carla_debug("CarlaLv2Client::getCustomURIDString(%i)", urid);
  704. return fCustomURIDs[urid].c_str();
  705. }
  706. // ----------------------------------------------------------------------------------------------------------------
  707. void handleProgramChanged(const int32_t index)
  708. {
  709. if (isPipeRunning())
  710. writeReloadProgramsMessage(index);
  711. }
  712. uint32_t handleUiPortMap(const char* const symbol)
  713. {
  714. CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
  715. carla_debug("CarlaLv2Client::handleUiPortMap(\"%s\")", symbol);
  716. for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
  717. {
  718. if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
  719. return i;
  720. }
  721. return LV2UI_INVALID_PORT_INDEX;
  722. }
  723. // ----------------------------------------------------------------------------------------------------------------
  724. char* handleStateMapToAbstractPath(const char* const absolutePath)
  725. {
  726. // may already be an abstract path
  727. if (! File::isAbsolutePath(absolutePath))
  728. return strdup(absolutePath);
  729. return strdup(File(absolutePath).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
  730. }
  731. char* handleStateMapToAbsolutePath(const bool createDir, const char* const abstractPath)
  732. {
  733. File target;
  734. if (File::isAbsolutePath(abstractPath))
  735. {
  736. target = abstractPath;
  737. }
  738. else
  739. {
  740. target = File::getCurrentWorkingDirectory().getChildFile(abstractPath);
  741. }
  742. if (createDir)
  743. {
  744. File dir(target.getParentDirectory());
  745. if (! dir.exists())
  746. dir.createDirectory();
  747. }
  748. return strdup(target.getFullPathName().toRawUTF8());
  749. }
  750. // ----------------------------------------------------------------------------------------------------------------
  751. LV2UI_Request_Value_Status handleUiRequestValue(const LV2_URID key,
  752. const LV2_URID type,
  753. const LV2_Feature* const* features)
  754. {
  755. CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
  756. carla_debug("CarlaLv2Client::handleUIRequestValue(%u, %u, %p)", key, type, features);
  757. if (type != kUridAtomPath)
  758. return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
  759. const char* const uri = getCustomURIDString(key);
  760. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri != kUnmapFallback, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
  761. // TODO check if a file browser is already open
  762. for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
  763. {
  764. if (fRdfDescriptor->Parameters[i].Type != LV2_PARAMETER_TYPE_PATH)
  765. continue;
  766. if (std::strcmp(fRdfDescriptor->Parameters[i].URI, uri) != 0)
  767. continue;
  768. // TODO file browser filters, also label for title
  769. if (isPipeRunning())
  770. {
  771. char tmpBuf[0xff];
  772. const CarlaMutexLocker cml(getPipeLock());
  773. writeMessage("requestvalue\n", 13);
  774. std::snprintf(tmpBuf, 0xff-1, "%u\n", key);
  775. tmpBuf[0xff-1] = '\0';
  776. writeMessage(tmpBuf);
  777. std::snprintf(tmpBuf, 0xff-1, "%u\n", type);
  778. tmpBuf[0xff-1] = '\0';
  779. writeMessage(tmpBuf);
  780. }
  781. return LV2UI_REQUEST_VALUE_SUCCESS;
  782. }
  783. return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
  784. // may be unused
  785. (void)features;
  786. }
  787. int handleUiResize(const int width, const int height)
  788. {
  789. CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, 1);
  790. CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
  791. CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
  792. carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height);
  793. fToolkit->setSize(static_cast<uint>(width), static_cast<uint>(height));
  794. return 0;
  795. }
  796. void handleUiWrite(uint32_t rindex, uint32_t bufferSize, uint32_t format, const void* buffer)
  797. {
  798. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
  799. CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
  800. carla_debug("CarlaLv2Client::handleUiWrite(%i, %i, %i, %p)", rindex, bufferSize, format, buffer);
  801. switch (format)
  802. {
  803. case kUridNull:
  804. CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),);
  805. if (isPipeRunning())
  806. {
  807. const float value(*(const float*)buffer);
  808. writeControlMessage(rindex, value);
  809. }
  810. break;
  811. case kUridAtomTransferAtom:
  812. case kUridAtomTransferEvent:
  813. CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),);
  814. if (isPipeRunning())
  815. {
  816. const LV2_Atom* const atom((const LV2_Atom*)buffer);
  817. // plugins sometimes fail on this, not good...
  818. const uint32_t totalSize = lv2_atom_total_size(atom);
  819. const uint32_t paddedSize = lv2_atom_pad_size(totalSize);
  820. if (bufferSize != totalSize && bufferSize != paddedSize)
  821. carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u",
  822. bufferSize, totalSize, paddedSize);
  823. writeLv2AtomMessage(rindex, atom);
  824. }
  825. break;
  826. default:
  827. carla_stderr("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format",
  828. rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
  829. break;
  830. }
  831. }
  832. // ----------------------------------------------------------------------------------------------------------------
  833. private:
  834. LV2UI_Handle fHandle;
  835. LV2UI_Widget fWidget;
  836. LV2_Feature* fFeatures[kFeatureCount+1];
  837. const LV2UI_Descriptor* fDescriptor;
  838. const LV2_RDF_Descriptor* fRdfDescriptor;
  839. const LV2_RDF_UI* fRdfUiDescriptor;
  840. uint32_t fControlDesignatedPort;
  841. Lv2PluginOptions fLv2Options;
  842. Options fUiOptions;
  843. std::vector<std::string> fCustomURIDs;
  844. struct Extensions {
  845. const LV2_Options_Interface* options;
  846. const LV2_Programs_UI_Interface* programs;
  847. const LV2UI_Idle_Interface* idle;
  848. const LV2UI_Resize* resize;
  849. Extensions()
  850. : options(nullptr),
  851. programs(nullptr),
  852. idle(nullptr),
  853. resize(nullptr) {}
  854. } fExt;
  855. // ----------------------------------------------------------------------------------------------------------------
  856. // Logs Feature
  857. static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
  858. {
  859. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  860. CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
  861. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  862. #ifndef DEBUG
  863. if (type == kUridLogTrace)
  864. return 0;
  865. #endif
  866. va_list args;
  867. va_start(args, fmt);
  868. const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
  869. va_end(args);
  870. return ret;
  871. }
  872. static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
  873. {
  874. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
  875. CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
  876. CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
  877. int ret = 0;
  878. switch (type)
  879. {
  880. case kUridLogError:
  881. std::fprintf(stderr, "\x1b[31m");
  882. ret = std::vfprintf(stderr, fmt, ap);
  883. std::fprintf(stderr, "\x1b[0m");
  884. break;
  885. case kUridLogNote:
  886. ret = std::vfprintf(stdout, fmt, ap);
  887. break;
  888. case kUridLogTrace:
  889. #ifdef DEBUG
  890. std::fprintf(stdout, "\x1b[30;1m");
  891. ret = std::vfprintf(stdout, fmt, ap);
  892. std::fprintf(stdout, "\x1b[0m");
  893. #endif
  894. break;
  895. case kUridLogWarning:
  896. ret = std::vfprintf(stderr, fmt, ap);
  897. break;
  898. default:
  899. break;
  900. }
  901. return ret;
  902. }
  903. // ----------------------------------------------------------------------------------------------------------------
  904. // Programs Feature
  905. static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
  906. {
  907. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  908. carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
  909. ((CarlaLv2Client*)handle)->handleProgramChanged(index);
  910. }
  911. // ----------------------------------------------------------------------------------------------------------------
  912. // State Feature
  913. static void carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle, char* path)
  914. {
  915. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  916. carla_debug("carla_lv2_state_free_path(%p, \"%s\")", handle, path);
  917. std::free(path);
  918. }
  919. static char* carla_lv2_state_make_path_tmp(LV2_State_Make_Path_Handle handle, const char* path)
  920. {
  921. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  922. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
  923. carla_debug("carla_lv2_state_make_path_tmp(%p, \"%s\")", handle, path);
  924. return ((CarlaLv2Client*)handle)->handleStateMapToAbsolutePath(true, path);
  925. }
  926. static char* carla_lv2_state_map_abstract_path_tmp(LV2_State_Map_Path_Handle handle, const char* absolute_path)
  927. {
  928. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  929. CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
  930. carla_debug("carla_lv2_state_map_abstract_path_tmp(%p, \"%s\")", handle, absolute_path);
  931. return ((CarlaLv2Client*)handle)->handleStateMapToAbstractPath(absolute_path);
  932. }
  933. static char* carla_lv2_state_map_absolute_path_tmp(LV2_State_Map_Path_Handle handle, const char* abstract_path)
  934. {
  935. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  936. CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
  937. carla_debug("carla_lv2_state_map_absolute_path_tmp(%p, \"%s\")", handle, abstract_path);
  938. return ((CarlaLv2Client*)handle)->handleStateMapToAbsolutePath(false, abstract_path);
  939. }
  940. // ----------------------------------------------------------------------------------------------------------------
  941. // URI-Map Feature
  942. static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
  943. {
  944. carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
  945. return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
  946. // unused
  947. (void)map;
  948. }
  949. // ----------------------------------------------------------------------------------------------------------------
  950. // URID Feature
  951. static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
  952. {
  953. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, kUridNull);
  954. CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
  955. carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
  956. // Atom types
  957. if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
  958. return kUridAtomBlank;
  959. if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
  960. return kUridAtomBool;
  961. if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
  962. return kUridAtomChunk;
  963. if (std::strcmp(uri, LV2_ATOM__Double) == 0)
  964. return kUridAtomDouble;
  965. if (std::strcmp(uri, LV2_ATOM__Event) == 0)
  966. return kUridAtomEvent;
  967. if (std::strcmp(uri, LV2_ATOM__Float) == 0)
  968. return kUridAtomFloat;
  969. if (std::strcmp(uri, LV2_ATOM__Int) == 0)
  970. return kUridAtomInt;
  971. if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
  972. return kUridAtomLiteral;
  973. if (std::strcmp(uri, LV2_ATOM__Long) == 0)
  974. return kUridAtomLong;
  975. if (std::strcmp(uri, LV2_ATOM__Number) == 0)
  976. return kUridAtomNumber;
  977. if (std::strcmp(uri, LV2_ATOM__Object) == 0)
  978. return kUridAtomObject;
  979. if (std::strcmp(uri, LV2_ATOM__Path) == 0)
  980. return kUridAtomPath;
  981. if (std::strcmp(uri, LV2_ATOM__Property) == 0)
  982. return kUridAtomProperty;
  983. if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
  984. return kUridAtomResource;
  985. if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
  986. return kUridAtomSequence;
  987. if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
  988. return kUridAtomSound;
  989. if (std::strcmp(uri, LV2_ATOM__String) == 0)
  990. return kUridAtomString;
  991. if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
  992. return kUridAtomTuple;
  993. if (std::strcmp(uri, LV2_ATOM__URI) == 0)
  994. return kUridAtomURI;
  995. if (std::strcmp(uri, LV2_ATOM__URID) == 0)
  996. return kUridAtomURID;
  997. if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
  998. return kUridAtomVector;
  999. if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  1000. return kUridAtomTransferAtom;
  1001. if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  1002. return kUridAtomTransferEvent;
  1003. // BufSize types
  1004. if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
  1005. return kUridBufMaxLength;
  1006. if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
  1007. return kUridBufMinLength;
  1008. if (std::strcmp(uri, LV2_BUF_SIZE__nominalBlockLength) == 0)
  1009. return kUridBufNominalLength;
  1010. if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
  1011. return kUridBufSequenceSize;
  1012. // Log types
  1013. if (std::strcmp(uri, LV2_LOG__Error) == 0)
  1014. return kUridLogError;
  1015. if (std::strcmp(uri, LV2_LOG__Note) == 0)
  1016. return kUridLogNote;
  1017. if (std::strcmp(uri, LV2_LOG__Trace) == 0)
  1018. return kUridLogTrace;
  1019. if (std::strcmp(uri, LV2_LOG__Warning) == 0)
  1020. return kUridLogWarning;
  1021. // Patch types
  1022. if (std::strcmp(uri, LV2_PATCH__Set) == 0)
  1023. return kUridPatchSet;
  1024. if (std::strcmp(uri, LV2_PATCH__property) == 0)
  1025. return kUridPatchProperty;
  1026. if (std::strcmp(uri, LV2_PATCH__subject) == 0)
  1027. return kUridPatchSubject;
  1028. if (std::strcmp(uri, LV2_PATCH__value) == 0)
  1029. return kUridPatchValue;
  1030. // Time types
  1031. if (std::strcmp(uri, LV2_TIME__Position) == 0)
  1032. return kUridTimePosition;
  1033. if (std::strcmp(uri, LV2_TIME__bar) == 0)
  1034. return kUridTimeBar;
  1035. if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
  1036. return kUridTimeBarBeat;
  1037. if (std::strcmp(uri, LV2_TIME__beat) == 0)
  1038. return kUridTimeBeat;
  1039. if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
  1040. return kUridTimeBeatUnit;
  1041. if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
  1042. return kUridTimeBeatsPerBar;
  1043. if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
  1044. return kUridTimeBeatsPerMinute;
  1045. if (std::strcmp(uri, LV2_TIME__frame) == 0)
  1046. return kUridTimeFrame;
  1047. if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
  1048. return kUridTimeFramesPerSecond;
  1049. if (std::strcmp(uri, LV2_TIME__speed) == 0)
  1050. return kUridTimeSpeed;
  1051. if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  1052. return kUridTimeTicksPerBeat;
  1053. // Others
  1054. if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  1055. return kUridMidiEvent;
  1056. if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
  1057. return kUridParamSampleRate;
  1058. if (std::strcmp(uri, LV2_UI__backgroundColor) == 0)
  1059. return kUridBackgroundColor;
  1060. if (std::strcmp(uri, LV2_UI__foregroundColor) == 0)
  1061. return kUridForegroundColor;
  1062. if (std::strcmp(uri, LV2_UI__scaleFactor) == 0)
  1063. return kUridScaleFactor;
  1064. if (std::strcmp(uri, LV2_UI__windowTitle) == 0)
  1065. return kUridWindowTitle;
  1066. // Custom Carla types
  1067. if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_IN) == 0)
  1068. return kUridCarlaAtomWorkerIn;
  1069. if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_RESP) == 0)
  1070. return kUridCarlaAtomWorkerResp;
  1071. if (std::strcmp(uri, URI_CARLA_PARAMETER_CHANGE) == 0)
  1072. return kUridCarlaParameterChange;
  1073. if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0)
  1074. return kUridCarlaTransientWindowId;
  1075. // Custom plugin types
  1076. return ((CarlaLv2Client*)handle)->getCustomURID(uri);
  1077. }
  1078. static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  1079. {
  1080. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
  1081. CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, nullptr);
  1082. carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
  1083. switch (urid)
  1084. {
  1085. // Atom types
  1086. case kUridAtomBlank:
  1087. return LV2_ATOM__Blank;
  1088. case kUridAtomBool:
  1089. return LV2_ATOM__Bool;
  1090. case kUridAtomChunk:
  1091. return LV2_ATOM__Chunk;
  1092. case kUridAtomDouble:
  1093. return LV2_ATOM__Double;
  1094. case kUridAtomEvent:
  1095. return LV2_ATOM__Event;
  1096. case kUridAtomFloat:
  1097. return LV2_ATOM__Float;
  1098. case kUridAtomInt:
  1099. return LV2_ATOM__Int;
  1100. case kUridAtomLiteral:
  1101. return LV2_ATOM__Literal;
  1102. case kUridAtomLong:
  1103. return LV2_ATOM__Long;
  1104. case kUridAtomNumber:
  1105. return LV2_ATOM__Number;
  1106. case kUridAtomObject:
  1107. return LV2_ATOM__Object;
  1108. case kUridAtomPath:
  1109. return LV2_ATOM__Path;
  1110. case kUridAtomProperty:
  1111. return LV2_ATOM__Property;
  1112. case kUridAtomResource:
  1113. return LV2_ATOM__Resource;
  1114. case kUridAtomSequence:
  1115. return LV2_ATOM__Sequence;
  1116. case kUridAtomSound:
  1117. return LV2_ATOM__Sound;
  1118. case kUridAtomString:
  1119. return LV2_ATOM__String;
  1120. case kUridAtomTuple:
  1121. return LV2_ATOM__Tuple;
  1122. case kUridAtomURI:
  1123. return LV2_ATOM__URI;
  1124. case kUridAtomURID:
  1125. return LV2_ATOM__URID;
  1126. case kUridAtomVector:
  1127. return LV2_ATOM__Vector;
  1128. case kUridAtomTransferAtom:
  1129. return LV2_ATOM__atomTransfer;
  1130. case kUridAtomTransferEvent:
  1131. return LV2_ATOM__eventTransfer;
  1132. // BufSize types
  1133. case kUridBufMaxLength:
  1134. return LV2_BUF_SIZE__maxBlockLength;
  1135. case kUridBufMinLength:
  1136. return LV2_BUF_SIZE__minBlockLength;
  1137. case kUridBufNominalLength:
  1138. return LV2_BUF_SIZE__nominalBlockLength;
  1139. case kUridBufSequenceSize:
  1140. return LV2_BUF_SIZE__sequenceSize;
  1141. // Log types
  1142. case kUridLogError:
  1143. return LV2_LOG__Error;
  1144. case kUridLogNote:
  1145. return LV2_LOG__Note;
  1146. case kUridLogTrace:
  1147. return LV2_LOG__Trace;
  1148. case kUridLogWarning:
  1149. return LV2_LOG__Warning;
  1150. // Patch types
  1151. case kUridPatchSet:
  1152. return LV2_PATCH__Set;
  1153. case kUridPatchProperty:
  1154. return LV2_PATCH__property;
  1155. case kUridPatchSubject:
  1156. return LV2_PATCH__subject;
  1157. case kUridPatchValue:
  1158. return LV2_PATCH__value;
  1159. // Time types
  1160. case kUridTimePosition:
  1161. return LV2_TIME__Position;
  1162. case kUridTimeBar:
  1163. return LV2_TIME__bar;
  1164. case kUridTimeBarBeat:
  1165. return LV2_TIME__barBeat;
  1166. case kUridTimeBeat:
  1167. return LV2_TIME__beat;
  1168. case kUridTimeBeatUnit:
  1169. return LV2_TIME__beatUnit;
  1170. case kUridTimeBeatsPerBar:
  1171. return LV2_TIME__beatsPerBar;
  1172. case kUridTimeBeatsPerMinute:
  1173. return LV2_TIME__beatsPerMinute;
  1174. case kUridTimeFrame:
  1175. return LV2_TIME__frame;
  1176. case kUridTimeFramesPerSecond:
  1177. return LV2_TIME__framesPerSecond;
  1178. case kUridTimeSpeed:
  1179. return LV2_TIME__speed;
  1180. case kUridTimeTicksPerBeat:
  1181. return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat;
  1182. // Others
  1183. case kUridMidiEvent:
  1184. return LV2_MIDI__MidiEvent;
  1185. case kUridParamSampleRate:
  1186. return LV2_PARAMETERS__sampleRate;
  1187. case kUridBackgroundColor:
  1188. return LV2_UI__backgroundColor;
  1189. case kUridForegroundColor:
  1190. return LV2_UI__foregroundColor;
  1191. case kUridScaleFactor:
  1192. return LV2_UI__scaleFactor;
  1193. case kUridWindowTitle:
  1194. return LV2_UI__windowTitle;
  1195. // Custom Carla types
  1196. case kUridCarlaAtomWorkerIn:
  1197. return URI_CARLA_ATOM_WORKER_IN;
  1198. case kUridCarlaAtomWorkerResp:
  1199. return URI_CARLA_ATOM_WORKER_RESP;
  1200. case kUridCarlaParameterChange:
  1201. return URI_CARLA_PARAMETER_CHANGE;
  1202. case kUridCarlaTransientWindowId:
  1203. return LV2_KXSTUDIO_PROPERTIES__TransientWindowId;
  1204. }
  1205. // Custom types
  1206. return ((CarlaLv2Client*)handle)->getCustomURIDString(urid);
  1207. }
  1208. // ----------------------------------------------------------------------------------------------------------------
  1209. // UI Port-Map Feature
  1210. static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
  1211. {
  1212. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
  1213. carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
  1214. return ((CarlaLv2Client*)handle)->handleUiPortMap(symbol);
  1215. }
  1216. // ----------------------------------------------------------------------------------------------------------------
  1217. // UI Request Parameter Feature
  1218. static LV2UI_Request_Value_Status carla_lv2_ui_request_value(LV2UI_Feature_Handle handle,
  1219. LV2_URID key,
  1220. LV2_URID type,
  1221. const LV2_Feature* const* features)
  1222. {
  1223. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
  1224. carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle, key, type, features);
  1225. return ((CarlaLv2Client*)handle)->handleUiRequestValue(key, type, features);
  1226. }
  1227. // ----------------------------------------------------------------------------------------------------------------
  1228. // UI Resize Feature
  1229. static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
  1230. {
  1231. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
  1232. carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  1233. return ((CarlaLv2Client*)handle)->handleUiResize(width, height);
  1234. }
  1235. // ----------------------------------------------------------------------------------------------------------------
  1236. // UI Extension
  1237. static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
  1238. {
  1239. CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
  1240. carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  1241. ((CarlaLv2Client*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
  1242. }
  1243. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client)
  1244. };
  1245. // --------------------------------------------------------------------------------------------------------------------
  1246. CARLA_BRIDGE_UI_END_NAMESPACE
  1247. // --------------------------------------------------------------------------------------------------------------------
  1248. int main(int argc, const char* argv[])
  1249. {
  1250. CARLA_BRIDGE_UI_USE_NAMESPACE
  1251. if (argc < 2)
  1252. {
  1253. carla_stderr("usage: %s <plugin-uri> [ui-uri]", argv[0]);
  1254. return 1;
  1255. }
  1256. const bool testingModeOnly = (argc != 7);
  1257. // try to get sampleRate value
  1258. if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE"))
  1259. {
  1260. const CarlaScopedLocale csl;
  1261. gInitialSampleRate = std::atof(sampleRateStr);
  1262. }
  1263. // Init LV2 client
  1264. CarlaLv2Client client;
  1265. // Load UI
  1266. int ret;
  1267. if (client.init(argc, argv))
  1268. {
  1269. client.exec(testingModeOnly);
  1270. ret = 0;
  1271. }
  1272. else
  1273. {
  1274. ret = 1;
  1275. }
  1276. return ret;
  1277. }
  1278. // --------------------------------------------------------------------------------------------------------------------