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.

1586 lines
56KB

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