DISTRHO Plugin Framework
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.

734 lines
28KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2017 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;
  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. manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
  124. manifestString += " ui:resize ,\n";
  125. manifestString += " ui:touch ;\n";
  126. manifestString += "\n";
  127. # endif
  128. manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
  129. manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
  130. manifestString += " <" LV2_OPTIONS__options "> ,\n";
  131. manifestString += " <" LV2_URID__map "> .\n";
  132. # else
  133. manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
  134. # endif
  135. manifestString += "\n";
  136. #endif
  137. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  138. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  139. char strBuf[0xff+1];
  140. strBuf[0xff] = '\0';
  141. String presetString;
  142. // Presets
  143. for (uint32_t i = 0; i < plugin.getProgramCount(); ++i)
  144. {
  145. std::snprintf(strBuf, 0xff, "%03i", i+1);
  146. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  147. presetString += " a pset:Preset ;\n";
  148. presetString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n";
  149. presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n";
  150. presetString += " rdfs:seeAlso <presets.ttl> .\n";
  151. presetString += "\n";
  152. manifestString += presetString;
  153. }
  154. #endif
  155. manifestFile << manifestString << std::endl;
  156. manifestFile.close();
  157. std::cout << " done!" << std::endl;
  158. }
  159. // ---------------------------------------------
  160. {
  161. std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
  162. std::fstream pluginFile(pluginTTL, std::ios::out);
  163. String pluginString;
  164. // header
  165. #if DISTRHO_LV2_USE_EVENTS_IN
  166. pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
  167. #endif
  168. pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
  169. pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
  170. pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  171. #ifdef DISTRHO_PLUGIN_BRAND
  172. pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n";
  173. #endif
  174. pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
  175. pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  176. pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
  177. #if DISTRHO_PLUGIN_HAS_UI
  178. pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  179. #endif
  180. pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
  181. pluginString += "\n";
  182. // plugin
  183. pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
  184. #ifdef DISTRHO_PLUGIN_LV2_CATEGORY
  185. pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n";
  186. #elif DISTRHO_PLUGIN_IS_SYNTH
  187. pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
  188. #else
  189. pluginString += " a lv2:Plugin ;\n";
  190. #endif
  191. pluginString += "\n";
  192. // extensionData
  193. pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
  194. #if DISTRHO_PLUGIN_WANT_STATE
  195. pluginString += ",\n <" LV2_OPTIONS__interface "> ";
  196. pluginString += ",\n <" LV2_WORKER__interface "> ";
  197. #endif
  198. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  199. pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
  200. #endif
  201. #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
  202. pluginString += ",\n <" MOD_LICENSE__interface "> ";
  203. #endif
  204. pluginString += ";\n\n";
  205. // optionalFeatures
  206. #if DISTRHO_PLUGIN_IS_RT_SAFE
  207. pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
  208. pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  209. #else
  210. pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  211. #endif
  212. pluginString += "\n";
  213. // requiredFeatures
  214. pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
  215. pluginString += ",\n <" LV2_URID__map "> ";
  216. #if DISTRHO_PLUGIN_WANT_STATE
  217. pluginString += ",\n <" LV2_WORKER__schedule "> ";
  218. #endif
  219. #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
  220. pluginString += ",\n <" MOD_LICENSE__feature "> ";
  221. #endif
  222. pluginString += ";\n\n";
  223. // supportedOptions
  224. pluginString += " opts:supportedOption <" LV2_BUF_SIZE__nominalBlockLength "> ,\n";
  225. pluginString += " <" LV2_BUF_SIZE__maxBlockLength "> ,\n";
  226. pluginString += " <" LV2_PARAMETERS__sampleRate "> ,\n";
  227. pluginString += " <" LV2_CORE__sampleRate "> ;\n";
  228. pluginString += "\n";
  229. // UI
  230. #if DISTRHO_PLUGIN_HAS_UI
  231. pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
  232. pluginString += "\n";
  233. #endif
  234. {
  235. uint32_t portIndex = 0;
  236. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  237. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
  238. {
  239. const AudioPort& port(plugin.getAudioPort(true, i));
  240. if (i == 0)
  241. pluginString += " lv2:port [\n";
  242. else
  243. pluginString += " [\n";
  244. if (port.hints & kAudioPortIsCV)
  245. pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
  246. else
  247. pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
  248. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  249. pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
  250. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  251. if (port.hints & kAudioPortIsSidechain)
  252. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  253. if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
  254. pluginString += " ] ;\n";
  255. else
  256. pluginString += " ] ,\n";
  257. }
  258. pluginString += "\n";
  259. #endif
  260. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  261. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
  262. {
  263. const AudioPort& port(plugin.getAudioPort(false, i));
  264. if (i == 0)
  265. pluginString += " lv2:port [\n";
  266. else
  267. pluginString += " [\n";
  268. if (port.hints & kAudioPortIsCV)
  269. pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
  270. else
  271. pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
  272. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  273. pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
  274. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  275. if (port.hints & kAudioPortIsSidechain)
  276. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  277. if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
  278. pluginString += " ] ;\n";
  279. else
  280. pluginString += " ] ,\n";
  281. }
  282. pluginString += "\n";
  283. #endif
  284. #if DISTRHO_LV2_USE_EVENTS_IN
  285. pluginString += " lv2:port [\n";
  286. pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
  287. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  288. pluginString += " lv2:name \"Events Input\" ;\n";
  289. pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
  290. pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  291. pluginString += " atom:bufferType atom:Sequence ;\n";
  292. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  293. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  294. # endif
  295. # if DISTRHO_PLUGIN_WANT_MIDI_INPUT
  296. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  297. # endif
  298. # if DISTRHO_PLUGIN_WANT_TIMEPOS
  299. pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
  300. # endif
  301. pluginString += " ] ;\n\n";
  302. ++portIndex;
  303. #endif
  304. #if DISTRHO_LV2_USE_EVENTS_OUT
  305. pluginString += " lv2:port [\n";
  306. pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
  307. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  308. pluginString += " lv2:name \"Events Output\" ;\n";
  309. pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
  310. pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  311. pluginString += " atom:bufferType atom:Sequence ;\n";
  312. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  313. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  314. # endif
  315. # if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  316. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  317. # endif
  318. pluginString += " ] ;\n\n";
  319. ++portIndex;
  320. #endif
  321. #if DISTRHO_PLUGIN_WANT_LATENCY
  322. pluginString += " lv2:port [\n";
  323. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  324. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  325. pluginString += " lv2:name \"Latency\" ;\n";
  326. pluginString += " lv2:symbol \"lv2_latency\" ;\n";
  327. pluginString += " lv2:designation lv2:latency ;\n";
  328. pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer, <" LV2_PORT_PROPS__notOnGUI "> ;\n";
  329. pluginString += " ] ;\n\n";
  330. ++portIndex;
  331. #endif
  332. for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
  333. {
  334. if (i == 0)
  335. pluginString += " lv2:port [\n";
  336. else
  337. pluginString += " [\n";
  338. if (plugin.isParameterOutput(i))
  339. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  340. else
  341. pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";
  342. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  343. bool designated = false;
  344. // designation
  345. if (! plugin.isParameterOutput(i))
  346. {
  347. switch (plugin.getParameterDesignation(i))
  348. {
  349. case kParameterDesignationNull:
  350. break;
  351. case kParameterDesignationBypass:
  352. designated = true;
  353. pluginString += " lv2:name \"Enabled\" ;\n";
  354. pluginString += " lv2:symbol \"lv2_enabled\" ;\n";
  355. pluginString += " lv2:default 1 ;\n";
  356. pluginString += " lv2:minimum 0 ;\n";
  357. pluginString += " lv2:maximum 1 ;\n";
  358. pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
  359. pluginString += " lv2:designation lv2:enabled ;\n";
  360. break;
  361. }
  362. }
  363. // name and symbol
  364. if (! designated)
  365. {
  366. pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";
  367. String symbol(plugin.getParameterSymbol(i));
  368. if (symbol.isEmpty())
  369. symbol = "lv2_port_" + String(portIndex-1);
  370. pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
  371. }
  372. // ranges
  373. if (! designated)
  374. {
  375. const ParameterRanges& ranges(plugin.getParameterRanges(i));
  376. if (plugin.getParameterHints(i) & kParameterIsInteger)
  377. {
  378. if (! plugin.isParameterOutput(i))
  379. pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
  380. pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
  381. pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
  382. }
  383. else
  384. {
  385. if (! plugin.isParameterOutput(i))
  386. pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
  387. pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
  388. pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
  389. }
  390. }
  391. // unit
  392. if (! designated)
  393. {
  394. const String& unit(plugin.getParameterUnit(i));
  395. if (! unit.isEmpty())
  396. {
  397. if (unit == "db" || unit == "dB")
  398. {
  399. pluginString += " unit:unit unit:db ;\n";
  400. }
  401. else if (unit == "hz" || unit == "Hz")
  402. {
  403. pluginString += " unit:unit unit:hz ;\n";
  404. }
  405. else if (unit == "khz" || unit == "kHz")
  406. {
  407. pluginString += " unit:unit unit:khz ;\n";
  408. }
  409. else if (unit == "mhz" || unit == "mHz")
  410. {
  411. pluginString += " unit:unit unit:mhz ;\n";
  412. }
  413. else if (unit == "ms")
  414. {
  415. pluginString += " unit:unit unit:ms ;\n";
  416. }
  417. else if (unit == "s")
  418. {
  419. pluginString += " unit:unit unit:s ;\n";
  420. }
  421. else if (unit == "%")
  422. {
  423. pluginString += " unit:unit unit:pc ;\n";
  424. }
  425. else
  426. {
  427. pluginString += " unit:unit [\n";
  428. pluginString += " rdfs:label \"" + unit + "\" ;\n";
  429. pluginString += " unit:symbol \"" + unit + "\" ;\n";
  430. pluginString += " unit:render \"%f " + unit + "\" ;\n";
  431. pluginString += " ] ;\n";
  432. }
  433. }
  434. }
  435. // hints
  436. if (! designated)
  437. {
  438. const uint32_t hints(plugin.getParameterHints(i));
  439. if (hints & kParameterIsBoolean)
  440. pluginString += " lv2:portProperty lv2:toggled ;\n";
  441. if (hints & kParameterIsInteger)
  442. pluginString += " lv2:portProperty lv2:integer ;\n";
  443. if (hints & kParameterIsLogarithmic)
  444. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
  445. if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
  446. {
  447. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
  448. pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
  449. }
  450. }
  451. if (i+1 == count)
  452. pluginString += " ] ;\n\n";
  453. else
  454. pluginString += " ] ,\n";
  455. }
  456. }
  457. // comment
  458. {
  459. const String comment(plugin.getDescription());
  460. if (comment.isNotEmpty())
  461. pluginString += " rdfs:comment \"\"\"\n" + comment + "\n\"\"\" ;\n\n";
  462. }
  463. #ifdef DISTRHO_PLUGIN_BRAND
  464. // MOD
  465. pluginString += " mod:brand \"" DISTRHO_PLUGIN_BRAND "\" ;\n";
  466. pluginString += " mod:label \"" DISTRHO_PLUGIN_NAME "\" ;\n\n";
  467. #endif
  468. // name
  469. pluginString += " doap:name \"" + String(plugin.getName()) + "\" ;\n";
  470. // license
  471. {
  472. const String license(plugin.getLicense());
  473. if (license.contains("://"))
  474. pluginString += " doap:license <" + license + "> ;\n\n";
  475. else
  476. pluginString += " doap:license \"" + license + "\" ;\n\n";
  477. }
  478. // developer
  479. {
  480. const String homepage(plugin.getHomePage());
  481. pluginString += " doap:maintainer [\n";
  482. pluginString += " foaf:name \"" + String(plugin.getMaker()) + "\" ;\n";
  483. if (homepage.isNotEmpty())
  484. pluginString += " foaf:homepage <" + homepage + "> ;\n";
  485. pluginString += " ] ;\n\n";
  486. }
  487. {
  488. const uint32_t version(plugin.getVersion());
  489. const uint32_t majorVersion = (version & 0xFF0000) >> 16;
  490. const uint32_t microVersion = (version & 0x00FF00) >> 8;
  491. /* */ uint32_t minorVersion = (version & 0x0000FF) >> 0;
  492. // NOTE: LV2 ignores 'major' version and says 0 for minor is pre-release/unstable.
  493. if (majorVersion > 0)
  494. minorVersion += 2;
  495. pluginString += " lv2:microVersion " + String(microVersion) + " ;\n";
  496. pluginString += " lv2:minorVersion " + String(minorVersion) + " .\n";
  497. }
  498. pluginFile << pluginString << std::endl;
  499. pluginFile.close();
  500. std::cout << " done!" << std::endl;
  501. }
  502. // ---------------------------------------------
  503. #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  504. {
  505. std::cout << "Writing " << uiTTL << "..."; std::cout.flush();
  506. std::fstream uiFile(uiTTL, std::ios::out);
  507. String uiString;
  508. uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  509. uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  510. uiString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
  511. uiString += "\n";
  512. uiString += "<" DISTRHO_UI_URI ">\n";
  513. uiString += " lv2:extensionData ui:idleInterface ,\n";
  514. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  515. uiString += " ui:showInterface ,\n";
  516. uiString += " <" LV2_PROGRAMS__Interface "> ;\n";
  517. # else
  518. uiString += " ui:showInterface ;\n";
  519. # endif
  520. uiString += "\n";
  521. # if DISTRHO_PLUGIN_HAS_EMBED_UI
  522. uiString += " lv2:optionalFeature ui:noUserResize ,\n";
  523. uiString += " ui:resize ,\n";
  524. uiString += " ui:touch ;\n";
  525. uiString += "\n";
  526. # endif
  527. uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
  528. uiString += " <" LV2_URID__map "> ;\n";
  529. uiString += " opts:supportedOption <" LV2_PARAMETERS__sampleRate "> ,\n";
  530. uiString += " opts:supportedOption <" LV2_CORE__sampleRate "> .";
  531. uiString += "\n\n";
  532. uiFile << uiString << std::endl;
  533. uiFile.close();
  534. std::cout << " done!" << std::endl;
  535. }
  536. #endif
  537. // ---------------------------------------------
  538. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  539. {
  540. std::cout << "Writing presets.ttl..."; std::cout.flush();
  541. std::fstream presetsFile("presets.ttl", std::ios::out);
  542. String presetsString;
  543. presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  544. presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
  545. # if DISTRHO_PLUGIN_WANT_STATE
  546. presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n";
  547. # endif
  548. presetsString += "\n";
  549. const uint32_t numParameters = plugin.getParameterCount();
  550. const uint32_t numPrograms = plugin.getProgramCount();
  551. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  552. const uint32_t numStates = plugin.getStateCount();
  553. # endif
  554. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  555. char strBuf[0xff+1];
  556. strBuf[0xff] = '\0';
  557. String presetString;
  558. for (uint32_t i=0; i<numPrograms; ++i)
  559. {
  560. std::snprintf(strBuf, 0xff, "%03i", i+1);
  561. plugin.loadProgram(i);
  562. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  563. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  564. if (numParameters == 0 && numStates == 0)
  565. #else
  566. if (numParameters == 0)
  567. #endif
  568. {
  569. presetString += " .";
  570. presetsString += presetString;
  571. continue;
  572. }
  573. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  574. presetString += " state:state [\n";
  575. for (uint32_t j=0; j<numStates; ++j)
  576. {
  577. const String key = plugin.getStateKey(j);
  578. const String value = plugin.getState(key);
  579. presetString += " <urn:distrho:" + key + ">";
  580. if (value.length() < 10)
  581. presetString += " \"" + value + "\" ;\n";
  582. else
  583. presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n";
  584. }
  585. if (numParameters > 0)
  586. presetString += " ] ;\n\n";
  587. else
  588. presetString += " ] .\n\n";
  589. # endif
  590. bool firstParameter = true;
  591. for (uint32_t j=0; j <numParameters; ++j)
  592. {
  593. if (plugin.isParameterOutput(j))
  594. continue;
  595. if (firstParameter)
  596. {
  597. presetString += " lv2:port [\n";
  598. firstParameter = false;
  599. }
  600. else
  601. {
  602. presetString += " [\n";
  603. }
  604. presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n";
  605. if (plugin.getParameterHints(j) & kParameterIsInteger)
  606. presetString += " pset:value " + String(int(plugin.getParameterValue(j))) + " ;\n";
  607. else
  608. presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n";
  609. if (j+1 == numParameters || plugin.isParameterOutput(j+1))
  610. presetString += " ] .\n\n";
  611. else
  612. presetString += " ] ,\n";
  613. }
  614. presetsString += presetString;
  615. }
  616. presetsFile << presetsString << std::endl;
  617. presetsFile.close();
  618. std::cout << " done!" << std::endl;
  619. }
  620. #endif
  621. }