Collection of DPF-based plugins for packaging
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.

767 lines
30KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "DistrhoPluginInternal.hpp"
  17. #include "lv2/atom.h"
  18. #include "lv2/buf-size.h"
  19. #include "lv2/data-access.h"
  20. #include "lv2/instance-access.h"
  21. #include "lv2/midi.h"
  22. #include "lv2/options.h"
  23. #include "lv2/port-props.h"
  24. #include "lv2/presets.h"
  25. #include "lv2/resize-port.h"
  26. #include "lv2/state.h"
  27. #include "lv2/time.h"
  28. #include "lv2/ui.h"
  29. #include "lv2/units.h"
  30. #include "lv2/urid.h"
  31. #include "lv2/worker.h"
  32. #include "lv2/lv2_kxstudio_properties.h"
  33. #include "lv2/lv2_programs.h"
  34. #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
  35. # include "mod-license.h"
  36. #endif
  37. #include <fstream>
  38. #include <iostream>
  39. #ifndef DISTRHO_PLUGIN_URI
  40. # error DISTRHO_PLUGIN_URI undefined!
  41. #endif
  42. #ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE
  43. # define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048
  44. #endif
  45. #ifndef DISTRHO_PLUGIN_USES_MODGUI
  46. # define DISTRHO_PLUGIN_USES_MODGUI 0
  47. #endif
  48. #if DISTRHO_PLUGIN_HAS_EMBED_UI
  49. # if DISTRHO_OS_HAIKU
  50. # define DISTRHO_LV2_UI_TYPE "BeUI"
  51. # elif DISTRHO_OS_MAC
  52. # define DISTRHO_LV2_UI_TYPE "CocoaUI"
  53. # elif DISTRHO_OS_WINDOWS
  54. # define DISTRHO_LV2_UI_TYPE "WindowsUI"
  55. # else
  56. # define DISTRHO_LV2_UI_TYPE "X11UI"
  57. # endif
  58. #else
  59. # define DISTRHO_LV2_UI_TYPE "UI"
  60. #endif
  61. #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
  62. #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
  63. // -----------------------------------------------------------------------
  64. DISTRHO_PLUGIN_EXPORT
  65. void lv2_generate_ttl(const char* const basename)
  66. {
  67. USE_NAMESPACE_DISTRHO
  68. // Dummy plugin to get data from
  69. d_lastBufferSize = 512;
  70. d_lastSampleRate = 44100.0;
  71. PluginExporter plugin(nullptr, nullptr);
  72. d_lastBufferSize = 0;
  73. d_lastSampleRate = 0.0;
  74. String pluginDLL(basename);
  75. String pluginTTL(pluginDLL + ".ttl");
  76. #if DISTRHO_PLUGIN_HAS_UI
  77. String pluginUI(pluginDLL);
  78. # if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  79. pluginUI.truncate(pluginDLL.rfind("_dsp"));
  80. pluginUI += "_ui";
  81. const String uiTTL(pluginUI + ".ttl");
  82. # endif
  83. #endif
  84. // ---------------------------------------------
  85. {
  86. std::cout << "Writing manifest.ttl..."; std::cout.flush();
  87. std::fstream manifestFile("manifest.ttl", std::ios::out);
  88. String manifestString;
  89. manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  90. manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  91. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  92. manifestString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
  93. #endif
  94. #if DISTRHO_PLUGIN_HAS_UI
  95. manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  96. #endif
  97. manifestString += "\n";
  98. manifestString += "<" DISTRHO_PLUGIN_URI ">\n";
  99. manifestString += " a lv2:Plugin ;\n";
  100. manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
  101. #if DISTRHO_PLUGIN_USES_MODGUI
  102. manifestString += " rdfs:seeAlso <" + pluginTTL + "> ,\n";
  103. manifestString += " <modgui.ttl> .\n";
  104. #else
  105. manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n";
  106. #endif
  107. manifestString += "\n";
  108. #if DISTRHO_PLUGIN_HAS_UI
  109. manifestString += "<" DISTRHO_UI_URI ">\n";
  110. manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n";
  111. manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
  112. # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  113. manifestString += "\n";
  114. manifestString += " lv2:extensionData ui:idleInterface ,\n";
  115. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  116. manifestString += " ui:showInterface ,\n";
  117. manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
  118. # else
  119. manifestString += " ui:showInterface ;\n";
  120. # endif
  121. manifestString += "\n";
  122. # if DISTRHO_PLUGIN_HAS_EMBED_UI
  123. # if DISTRHO_UI_USER_RESIZABLE
  124. manifestString += " lv2:optionalFeature ui:resize ,\n";
  125. manifestString += " ui:touch ;\n";
  126. manifestString += "\n";
  127. # else // DISTRHO_UI_USER_RESIZABLE
  128. manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
  129. manifestString += " ui:resize ,\n";
  130. manifestString += " ui:touch ;\n";
  131. manifestString += "\n";
  132. # endif // DISTRHO_UI_USER_RESIZABLE
  133. # endif // DISTRHO_PLUGIN_HAS_EMBED_UI
  134. manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
  135. manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
  136. manifestString += " <" LV2_OPTIONS__options "> ,\n";
  137. manifestString += " <" LV2_URID__map "> ;\n";
  138. manifestString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> ;\n";
  139. # else // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  140. manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
  141. # endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  142. manifestString += "\n";
  143. #endif
  144. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  145. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  146. char strBuf[0xff+1];
  147. strBuf[0xff] = '\0';
  148. String presetString;
  149. // Presets
  150. for (uint32_t i = 0; i < plugin.getProgramCount(); ++i)
  151. {
  152. std::snprintf(strBuf, 0xff, "%03i", i+1);
  153. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  154. presetString += " a pset:Preset ;\n";
  155. presetString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n";
  156. presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n";
  157. presetString += " rdfs:seeAlso <presets.ttl> .\n";
  158. presetString += "\n";
  159. manifestString += presetString;
  160. }
  161. #endif
  162. manifestFile << manifestString << std::endl;
  163. manifestFile.close();
  164. std::cout << " done!" << std::endl;
  165. }
  166. // ---------------------------------------------
  167. {
  168. std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
  169. std::fstream pluginFile(pluginTTL, std::ios::out);
  170. String pluginString;
  171. // header
  172. #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
  173. pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
  174. #endif
  175. pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
  176. pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
  177. pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  178. #ifdef DISTRHO_PLUGIN_BRAND
  179. pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n";
  180. #endif
  181. pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
  182. pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
  183. pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  184. pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
  185. #if DISTRHO_PLUGIN_HAS_UI
  186. pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  187. #endif
  188. pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
  189. pluginString += "\n";
  190. // plugin
  191. pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
  192. #ifdef DISTRHO_PLUGIN_LV2_CATEGORY
  193. pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n";
  194. #elif DISTRHO_PLUGIN_IS_SYNTH
  195. pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
  196. #else
  197. pluginString += " a lv2:Plugin ;\n";
  198. #endif
  199. pluginString += "\n";
  200. // extensionData
  201. pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
  202. #if DISTRHO_PLUGIN_WANT_STATE
  203. pluginString += ",\n <" LV2_OPTIONS__interface "> ";
  204. pluginString += ",\n <" LV2_WORKER__interface "> ";
  205. #endif
  206. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  207. pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
  208. #endif
  209. #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
  210. pluginString += ",\n <" MOD_LICENSE__interface "> ";
  211. #endif
  212. pluginString += ";\n\n";
  213. // optionalFeatures
  214. #if DISTRHO_PLUGIN_IS_RT_SAFE
  215. pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
  216. pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  217. #else
  218. pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  219. #endif
  220. pluginString += "\n";
  221. // requiredFeatures
  222. pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
  223. pluginString += ",\n <" LV2_URID__map "> ";
  224. #if DISTRHO_PLUGIN_WANT_STATE
  225. pluginString += ",\n <" LV2_WORKER__schedule "> ";
  226. #endif
  227. #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
  228. pluginString += ",\n <" MOD_LICENSE__feature "> ";
  229. #endif
  230. pluginString += ";\n\n";
  231. // supportedOptions
  232. pluginString += " opts:supportedOption <" LV2_BUF_SIZE__nominalBlockLength "> ,\n";
  233. pluginString += " <" LV2_BUF_SIZE__maxBlockLength "> ,\n";
  234. pluginString += " <" LV2_PARAMETERS__sampleRate "> ;\n";
  235. pluginString += "\n";
  236. // UI
  237. #if DISTRHO_PLUGIN_HAS_UI
  238. pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
  239. pluginString += "\n";
  240. #endif
  241. {
  242. uint32_t portIndex = 0;
  243. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  244. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
  245. {
  246. const AudioPort& port(plugin.getAudioPort(true, i));
  247. if (i == 0)
  248. pluginString += " lv2:port [\n";
  249. else
  250. pluginString += " [\n";
  251. if (port.hints & kAudioPortIsCV)
  252. pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
  253. else
  254. pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
  255. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  256. pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
  257. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  258. if (port.hints & kAudioPortIsSidechain)
  259. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  260. if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
  261. pluginString += " ] ;\n";
  262. else
  263. pluginString += " ] ,\n";
  264. }
  265. pluginString += "\n";
  266. #endif
  267. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  268. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
  269. {
  270. const AudioPort& port(plugin.getAudioPort(false, i));
  271. if (i == 0)
  272. pluginString += " lv2:port [\n";
  273. else
  274. pluginString += " [\n";
  275. if (port.hints & kAudioPortIsCV)
  276. pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
  277. else
  278. pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
  279. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  280. pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
  281. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  282. if (port.hints & kAudioPortIsSidechain)
  283. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  284. if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
  285. pluginString += " ] ;\n";
  286. else
  287. pluginString += " ] ,\n";
  288. }
  289. pluginString += "\n";
  290. #endif
  291. #if DISTRHO_LV2_USE_EVENTS_IN
  292. pluginString += " lv2:port [\n";
  293. pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
  294. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  295. pluginString += " lv2:name \"Events Input\" ;\n";
  296. pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
  297. pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  298. pluginString += " atom:bufferType atom:Sequence ;\n";
  299. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  300. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  301. # endif
  302. # if DISTRHO_PLUGIN_WANT_MIDI_INPUT
  303. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  304. # endif
  305. # if DISTRHO_PLUGIN_WANT_TIMEPOS
  306. pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
  307. # endif
  308. pluginString += " ] ;\n\n";
  309. ++portIndex;
  310. #endif
  311. #if DISTRHO_LV2_USE_EVENTS_OUT
  312. pluginString += " lv2:port [\n";
  313. pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
  314. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  315. pluginString += " lv2:name \"Events Output\" ;\n";
  316. pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
  317. pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  318. pluginString += " atom:bufferType atom:Sequence ;\n";
  319. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  320. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  321. # endif
  322. # if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  323. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  324. # endif
  325. pluginString += " ] ;\n\n";
  326. ++portIndex;
  327. #endif
  328. #if DISTRHO_PLUGIN_WANT_LATENCY
  329. pluginString += " lv2:port [\n";
  330. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  331. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  332. pluginString += " lv2:name \"Latency\" ;\n";
  333. pluginString += " lv2:symbol \"lv2_latency\" ;\n";
  334. pluginString += " lv2:designation lv2:latency ;\n";
  335. pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer, <" LV2_PORT_PROPS__notOnGUI "> ;\n";
  336. pluginString += " ] ;\n\n";
  337. ++portIndex;
  338. #endif
  339. for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
  340. {
  341. if (i == 0)
  342. pluginString += " lv2:port [\n";
  343. else
  344. pluginString += " [\n";
  345. if (plugin.isParameterOutput(i))
  346. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  347. else
  348. pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";
  349. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  350. bool designated = false;
  351. // designation
  352. if (plugin.isParameterInput(i))
  353. {
  354. switch (plugin.getParameterDesignation(i))
  355. {
  356. case kParameterDesignationNull:
  357. break;
  358. case kParameterDesignationBypass:
  359. designated = true;
  360. pluginString += " lv2:name \"Enabled\" ;\n";
  361. pluginString += " lv2:symbol \"lv2_enabled\" ;\n";
  362. pluginString += " lv2:default 1 ;\n";
  363. pluginString += " lv2:minimum 0 ;\n";
  364. pluginString += " lv2:maximum 1 ;\n";
  365. pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
  366. pluginString += " lv2:designation lv2:enabled ;\n";
  367. break;
  368. }
  369. }
  370. if (! designated)
  371. {
  372. // name and symbol
  373. pluginString += " lv2:name \"\"\"" + plugin.getParameterName(i) + "\"\"\" ;\n";
  374. String symbol(plugin.getParameterSymbol(i));
  375. if (symbol.isEmpty())
  376. symbol = "lv2_port_" + String(portIndex-1);
  377. pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
  378. // ranges
  379. const ParameterRanges& ranges(plugin.getParameterRanges(i));
  380. if (plugin.getParameterHints(i) & kParameterIsInteger)
  381. {
  382. if (plugin.isParameterInput(i))
  383. pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
  384. pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
  385. pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
  386. }
  387. else
  388. {
  389. if (plugin.isParameterInput(i))
  390. pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
  391. pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
  392. pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
  393. }
  394. // enumeration
  395. const ParameterEnumerationValues& enumValues(plugin.getParameterEnumValues(i));
  396. if (enumValues.count > 0)
  397. {
  398. if (enumValues.count >= 2 && enumValues.restrictedMode)
  399. pluginString += " lv2:portProperty lv2:enumeration ;\n";
  400. for (uint8_t j=0; j < enumValues.count; ++j)
  401. {
  402. const ParameterEnumerationValue& enumValue(enumValues.values[j]);
  403. if (j == 0)
  404. pluginString += " lv2:scalePoint [\n";
  405. else
  406. pluginString += " [\n";
  407. pluginString += " rdfs:label \"\"\"" + enumValue.label + "\"\"\" ;\n";
  408. pluginString += " rdf:value " + String(enumValue.value) + " ;\n";
  409. if (j+1 == enumValues.count)
  410. pluginString += " ] ;\n\n";
  411. else
  412. pluginString += " ] ,\n";
  413. }
  414. }
  415. // unit
  416. const String& unit(plugin.getParameterUnit(i));
  417. if (! unit.isEmpty())
  418. {
  419. if (unit == "db" || unit == "dB")
  420. {
  421. pluginString += " unit:unit unit:db ;\n";
  422. }
  423. else if (unit == "hz" || unit == "Hz")
  424. {
  425. pluginString += " unit:unit unit:hz ;\n";
  426. }
  427. else if (unit == "khz" || unit == "kHz")
  428. {
  429. pluginString += " unit:unit unit:khz ;\n";
  430. }
  431. else if (unit == "mhz" || unit == "mHz")
  432. {
  433. pluginString += " unit:unit unit:mhz ;\n";
  434. }
  435. else if (unit == "ms")
  436. {
  437. pluginString += " unit:unit unit:ms ;\n";
  438. }
  439. else if (unit == "s")
  440. {
  441. pluginString += " unit:unit unit:s ;\n";
  442. }
  443. else if (unit == "%")
  444. {
  445. pluginString += " unit:unit unit:pc ;\n";
  446. }
  447. else
  448. {
  449. pluginString += " unit:unit [\n";
  450. pluginString += " rdfs:label \"" + unit + "\" ;\n";
  451. pluginString += " unit:symbol \"" + unit + "\" ;\n";
  452. pluginString += " unit:render \"%f " + unit + "\" ;\n";
  453. pluginString += " ] ;\n";
  454. }
  455. }
  456. // hints
  457. const uint32_t hints(plugin.getParameterHints(i));
  458. if (hints & kParameterIsBoolean)
  459. {
  460. if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
  461. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__trigger "> ;\n";
  462. pluginString += " lv2:portProperty lv2:toggled ;\n";
  463. }
  464. if (hints & kParameterIsInteger)
  465. pluginString += " lv2:portProperty lv2:integer ;\n";
  466. if (hints & kParameterIsLogarithmic)
  467. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
  468. if ((hints & kParameterIsAutomable) == 0 && plugin.isParameterInput(i))
  469. {
  470. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
  471. pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
  472. }
  473. } // ! designated
  474. if (i+1 == count)
  475. pluginString += " ] ;\n\n";
  476. else
  477. pluginString += " ] ,\n";
  478. }
  479. }
  480. // comment
  481. {
  482. const String comment(plugin.getDescription());
  483. if (comment.isNotEmpty())
  484. pluginString += " rdfs:comment \"\"\"\n" + comment + "\n\"\"\" ;\n\n";
  485. }
  486. #ifdef DISTRHO_PLUGIN_BRAND
  487. // MOD
  488. pluginString += " mod:brand \"" DISTRHO_PLUGIN_BRAND "\" ;\n";
  489. pluginString += " mod:label \"" DISTRHO_PLUGIN_NAME "\" ;\n\n";
  490. #endif
  491. // name
  492. pluginString += " doap:name \"\"\"" + String(plugin.getName()) + "\"\"\" ;\n";
  493. // license
  494. {
  495. const String license(plugin.getLicense());
  496. if (license.contains("://"))
  497. pluginString += " doap:license <" + license + "> ;\n\n";
  498. else
  499. pluginString += " doap:license \"\"\"" + license + "\"\"\" ;\n\n";
  500. }
  501. // developer
  502. {
  503. const String homepage(plugin.getHomePage());
  504. pluginString += " doap:maintainer [\n";
  505. pluginString += " foaf:name \"\"\"" + String(plugin.getMaker()) + "\"\"\" ;\n";
  506. if (homepage.isNotEmpty())
  507. pluginString += " foaf:homepage <" + homepage + "> ;\n";
  508. pluginString += " ] ;\n\n";
  509. }
  510. {
  511. const uint32_t version(plugin.getVersion());
  512. const uint32_t majorVersion = (version & 0xFF0000) >> 16;
  513. const uint32_t microVersion = (version & 0x00FF00) >> 8;
  514. /* */ uint32_t minorVersion = (version & 0x0000FF) >> 0;
  515. // NOTE: LV2 ignores 'major' version and says 0 for minor is pre-release/unstable.
  516. if (majorVersion > 0)
  517. minorVersion += 2;
  518. pluginString += " lv2:microVersion " + String(microVersion) + " ;\n";
  519. pluginString += " lv2:minorVersion " + String(minorVersion) + " .\n";
  520. }
  521. pluginFile << pluginString << std::endl;
  522. pluginFile.close();
  523. std::cout << " done!" << std::endl;
  524. }
  525. // ---------------------------------------------
  526. #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  527. {
  528. std::cout << "Writing " << uiTTL << "..."; std::cout.flush();
  529. std::fstream uiFile(uiTTL, std::ios::out);
  530. String uiString;
  531. uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  532. uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  533. uiString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
  534. uiString += "\n";
  535. uiString += "<" DISTRHO_UI_URI ">\n";
  536. uiString += " lv2:extensionData ui:idleInterface ,\n";
  537. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  538. uiString += " ui:showInterface ,\n";
  539. uiString += " <" LV2_PROGRAMS__Interface "> ;\n";
  540. # else
  541. uiString += " ui:showInterface ;\n";
  542. # endif
  543. uiString += "\n";
  544. # if DISTRHO_PLUGIN_HAS_EMBED_UI
  545. # if DISTRHO_UI_USER_RESIZABLE
  546. uiString += " lv2:optionalFeature ui:resize ,\n";
  547. uiString += " ui:touch ;\n";
  548. uiString += "\n";
  549. # else // DISTRHO_UI_USER_RESIZABLE
  550. uiString += " lv2:optionalFeature ui:noUserResize ,\n";
  551. uiString += " ui:resize ,\n";
  552. uiString += " ui:touch ;\n";
  553. uiString += "\n";
  554. # endif // DISTRHO_UI_USER_RESIZABLE
  555. # endif // DISTRHO_PLUGIN_HAS_EMBED_UI
  556. uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
  557. uiString += " <" LV2_URID__map "> ;\n";
  558. uiString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> .\n";
  559. uiFile << uiString << std::endl;
  560. uiFile.close();
  561. std::cout << " done!" << std::endl;
  562. }
  563. #endif
  564. // ---------------------------------------------
  565. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  566. {
  567. std::cout << "Writing presets.ttl..."; std::cout.flush();
  568. std::fstream presetsFile("presets.ttl", std::ios::out);
  569. String presetsString;
  570. presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  571. presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
  572. # if DISTRHO_PLUGIN_WANT_STATE
  573. presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n";
  574. # endif
  575. presetsString += "\n";
  576. const uint32_t numParameters = plugin.getParameterCount();
  577. const uint32_t numPrograms = plugin.getProgramCount();
  578. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  579. const uint32_t numStates = plugin.getStateCount();
  580. # endif
  581. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  582. char strBuf[0xff+1];
  583. strBuf[0xff] = '\0';
  584. String presetString;
  585. for (uint32_t i=0; i<numPrograms; ++i)
  586. {
  587. std::snprintf(strBuf, 0xff, "%03i", i+1);
  588. plugin.loadProgram(i);
  589. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  590. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  591. if (numParameters == 0 && numStates == 0)
  592. #else
  593. if (numParameters == 0)
  594. #endif
  595. {
  596. presetString += " .";
  597. presetsString += presetString;
  598. continue;
  599. }
  600. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  601. presetString += " state:state [\n";
  602. for (uint32_t j=0; j<numStates; ++j)
  603. {
  604. const String key = plugin.getStateKey(j);
  605. const String value = plugin.getState(key);
  606. presetString += " <urn:distrho:" + key + ">";
  607. if (value.length() < 10)
  608. presetString += " \"" + value + "\" ;\n";
  609. else
  610. presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n";
  611. }
  612. if (numParameters > 0)
  613. presetString += " ] ;\n\n";
  614. else
  615. presetString += " ] .\n\n";
  616. # endif
  617. bool firstParameter = true;
  618. for (uint32_t j=0; j <numParameters; ++j)
  619. {
  620. if (plugin.isParameterOutput(j))
  621. continue;
  622. if (firstParameter)
  623. {
  624. presetString += " lv2:port [\n";
  625. firstParameter = false;
  626. }
  627. else
  628. {
  629. presetString += " [\n";
  630. }
  631. presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n";
  632. if (plugin.getParameterHints(j) & kParameterIsInteger)
  633. presetString += " pset:value " + String(int(plugin.getParameterValue(j))) + " ;\n";
  634. else
  635. presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n";
  636. if (j+1 == numParameters || plugin.isParameterOutput(j+1))
  637. presetString += " ] .\n\n";
  638. else
  639. presetString += " ] ,\n";
  640. }
  641. presetsString += presetString;
  642. }
  643. presetsFile << presetsString << std::endl;
  644. presetsFile.close();
  645. std::cout << " done!" << std::endl;
  646. }
  647. #endif
  648. }