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.

1572 lines
55KB

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