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.

607 lines
23KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2015 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. #include <fstream>
  35. #include <iostream>
  36. #ifndef DISTRHO_PLUGIN_URI
  37. # error DISTRHO_PLUGIN_URI undefined!
  38. #endif
  39. #ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE
  40. # define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048
  41. #endif
  42. #ifndef DISTRHO_PLUGIN_USES_MODGUI
  43. # define DISTRHO_PLUGIN_USES_MODGUI 0
  44. #endif
  45. #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL)
  46. # undef DISTRHO_PLUGIN_HAS_UI
  47. # define DISTRHO_PLUGIN_HAS_UI 0
  48. #endif
  49. #if DISTRHO_PLUGIN_HAS_UI
  50. # if DISTRHO_OS_HAIKU
  51. # define DISTRHO_LV2_UI_TYPE "BeUI"
  52. # elif DISTRHO_OS_MAC
  53. # define DISTRHO_LV2_UI_TYPE "CocoaUI"
  54. # elif DISTRHO_OS_WINDOWS
  55. # define DISTRHO_LV2_UI_TYPE "WindowsUI"
  56. # else
  57. # define DISTRHO_LV2_UI_TYPE "X11UI"
  58. # endif
  59. #endif
  60. #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
  61. #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
  62. // -----------------------------------------------------------------------
  63. DISTRHO_PLUGIN_EXPORT
  64. void lv2_generate_ttl(const char* const basename)
  65. {
  66. USE_NAMESPACE_DISTRHO
  67. // Dummy plugin to get data from
  68. d_lastBufferSize = 512;
  69. d_lastSampleRate = 44100.0;
  70. PluginExporter plugin;
  71. d_lastBufferSize = 0;
  72. d_lastSampleRate = 0.0;
  73. String pluginDLL(basename);
  74. String pluginTTL(pluginDLL + ".ttl");
  75. #if DISTRHO_PLUGIN_HAS_UI
  76. String pluginUI(pluginDLL);
  77. # if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  78. pluginUI.truncate(pluginDLL.rfind("_dsp"));
  79. pluginUI += "_ui";
  80. const String uiTTL(pluginUI + ".ttl");
  81. # endif
  82. #endif
  83. // ---------------------------------------------
  84. {
  85. std::cout << "Writing manifest.ttl..."; std::cout.flush();
  86. std::fstream manifestFile("manifest.ttl", std::ios::out);
  87. String manifestString;
  88. manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  89. manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  90. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  91. manifestString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
  92. #endif
  93. #if DISTRHO_PLUGIN_HAS_UI
  94. manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  95. #endif
  96. manifestString += "\n";
  97. manifestString += "<" DISTRHO_PLUGIN_URI ">\n";
  98. manifestString += " a lv2:Plugin ;\n";
  99. manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
  100. #if DISTRHO_PLUGIN_USES_MODGUI
  101. manifestString += " rdfs:seeAlso <" + pluginTTL + "> ,\n";
  102. manifestString += " <modgui.ttl> .\n";
  103. #else
  104. manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n";
  105. #endif
  106. manifestString += "\n";
  107. #if DISTRHO_PLUGIN_HAS_UI
  108. manifestString += "<" DISTRHO_UI_URI ">\n";
  109. manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n";
  110. manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
  111. # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  112. manifestString += "\n";
  113. manifestString += " lv2:extensionData ui:idleInterface ,\n";
  114. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  115. manifestString += " ui:showInterface ,\n";
  116. manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
  117. # else
  118. manifestString += " ui:showInterface ;\n";
  119. # endif
  120. manifestString += "\n";
  121. manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
  122. manifestString += " ui:resize ,\n";
  123. manifestString += " ui:touch ;\n";
  124. manifestString += "\n";
  125. manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
  126. manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
  127. manifestString += " <" LV2_OPTIONS__options "> ,\n";
  128. manifestString += " <" LV2_URID__map "> .\n";
  129. # else
  130. manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
  131. # endif
  132. manifestString += "\n";
  133. #endif
  134. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  135. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  136. char strBuf[0xff+1];
  137. strBuf[0xff] = '\0';
  138. String presetString;
  139. // Presets
  140. for (uint32_t i = 0; i < plugin.getProgramCount(); ++i)
  141. {
  142. std::snprintf(strBuf, 0xff, "%03i", i+1);
  143. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  144. presetString += " a pset:Preset ;\n";
  145. presetString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n";
  146. presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n";
  147. presetString += " rdfs:seeAlso <presets.ttl> .\n";
  148. presetString += "\n";
  149. manifestString += presetString;
  150. }
  151. #endif
  152. manifestFile << manifestString << std::endl;
  153. manifestFile.close();
  154. std::cout << " done!" << std::endl;
  155. }
  156. // ---------------------------------------------
  157. {
  158. std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
  159. std::fstream pluginFile(pluginTTL, std::ios::out);
  160. String pluginString;
  161. // header
  162. #if DISTRHO_LV2_USE_EVENTS_IN
  163. pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
  164. #endif
  165. pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
  166. pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
  167. pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  168. pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
  169. #if DISTRHO_PLUGIN_HAS_UI
  170. pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  171. #endif
  172. pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
  173. pluginString += "\n";
  174. // plugin
  175. pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
  176. #ifdef DISTRHO_PLUGIN_LV2_CATEGORY
  177. pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n";
  178. #elif DISTRHO_PLUGIN_IS_SYNTH
  179. pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
  180. #else
  181. pluginString += " a lv2:Plugin ;\n";
  182. #endif
  183. pluginString += "\n";
  184. // extensionData
  185. pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
  186. #if DISTRHO_PLUGIN_WANT_STATE
  187. pluginString += ",\n <" LV2_OPTIONS__interface "> ";
  188. pluginString += ",\n <" LV2_WORKER__interface "> ";
  189. #endif
  190. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  191. pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
  192. #endif
  193. pluginString += ";\n\n";
  194. // optionalFeatures
  195. #if DISTRHO_PLUGIN_IS_RT_SAFE
  196. pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
  197. pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  198. #else
  199. pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  200. #endif
  201. pluginString += "\n";
  202. // requiredFeatures
  203. pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
  204. pluginString += ",\n <" LV2_URID__map "> ";
  205. #if DISTRHO_PLUGIN_WANT_STATE
  206. pluginString += ",\n <" LV2_WORKER__schedule "> ";
  207. #endif
  208. pluginString += ";\n\n";
  209. // UI
  210. #if DISTRHO_PLUGIN_HAS_UI
  211. pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
  212. pluginString += "\n";
  213. #endif
  214. {
  215. uint32_t portIndex = 0;
  216. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  217. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
  218. {
  219. const AudioPort& port(plugin.getAudioPort(true, i));
  220. if (i == 0)
  221. pluginString += " lv2:port [\n";
  222. else
  223. pluginString += " [\n";
  224. if (port.hints & kAudioPortIsCV)
  225. pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
  226. else
  227. pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
  228. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  229. pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
  230. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  231. if (port.hints & kAudioPortIsSidechain)
  232. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  233. if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
  234. pluginString += " ] ;\n";
  235. else
  236. pluginString += " ] ,\n";
  237. }
  238. pluginString += "\n";
  239. #endif
  240. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  241. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
  242. {
  243. const AudioPort& port(plugin.getAudioPort(false, i));
  244. if (i == 0)
  245. pluginString += " lv2:port [\n";
  246. else
  247. pluginString += " [\n";
  248. if (port.hints & kAudioPortIsCV)
  249. pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
  250. else
  251. pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
  252. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  253. pluginString += " lv2:symbol \"" + port.symbol + "\" ;\n";
  254. pluginString += " lv2:name \"" + port.name + "\" ;\n";
  255. if (port.hints & kAudioPortIsSidechain)
  256. pluginString += " lv2:portProperty lv2:isSideChain;\n";
  257. if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
  258. pluginString += " ] ;\n";
  259. else
  260. pluginString += " ] ,\n";
  261. }
  262. pluginString += "\n";
  263. #endif
  264. #if DISTRHO_LV2_USE_EVENTS_IN
  265. pluginString += " lv2:port [\n";
  266. pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
  267. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  268. pluginString += " lv2:name \"Events Input\" ;\n";
  269. pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
  270. pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  271. pluginString += " atom:bufferType atom:Sequence ;\n";
  272. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  273. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  274. # endif
  275. # if DISTRHO_PLUGIN_WANT_MIDI_INPUT
  276. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  277. # endif
  278. # if DISTRHO_PLUGIN_WANT_TIMEPOS
  279. pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
  280. # endif
  281. pluginString += " ] ;\n\n";
  282. ++portIndex;
  283. #endif
  284. #if DISTRHO_LV2_USE_EVENTS_OUT
  285. pluginString += " lv2:port [\n";
  286. pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
  287. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  288. pluginString += " lv2:name \"Events Output\" ;\n";
  289. pluginString += " lv2:symbol \"lv2_events_out\" ;\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_OUTPUT
  296. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  297. # endif
  298. pluginString += " ] ;\n\n";
  299. ++portIndex;
  300. #endif
  301. #if DISTRHO_PLUGIN_WANT_LATENCY
  302. pluginString += " lv2:port [\n";
  303. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  304. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  305. pluginString += " lv2:name \"Latency\" ;\n";
  306. pluginString += " lv2:symbol \"lv2_latency\" ;\n";
  307. pluginString += " lv2:designation lv2:latency ;\n";
  308. pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer ;\n";
  309. pluginString += " ] ;\n\n";
  310. ++portIndex;
  311. #endif
  312. for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
  313. {
  314. if (i == 0)
  315. pluginString += " lv2:port [\n";
  316. else
  317. pluginString += " [\n";
  318. if (plugin.isParameterOutput(i))
  319. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  320. else
  321. pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";
  322. pluginString += " lv2:index " + String(portIndex) + " ;\n";
  323. pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";
  324. // symbol
  325. {
  326. String symbol(plugin.getParameterSymbol(i));
  327. if (symbol.isEmpty())
  328. symbol = "lv2_port_" + String(portIndex-1);
  329. pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
  330. }
  331. // ranges
  332. {
  333. const ParameterRanges& ranges(plugin.getParameterRanges(i));
  334. if (plugin.getParameterHints(i) & kParameterIsInteger)
  335. {
  336. pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
  337. pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
  338. pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
  339. }
  340. else
  341. {
  342. pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
  343. pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
  344. pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
  345. }
  346. }
  347. // unit
  348. {
  349. const String& unit(plugin.getParameterUnit(i));
  350. if (! unit.isEmpty())
  351. {
  352. if (unit == "db" || unit == "dB")
  353. {
  354. pluginString += " unit:unit unit:db ;\n";
  355. }
  356. else if (unit == "hz" || unit == "Hz")
  357. {
  358. pluginString += " unit:unit unit:hz ;\n";
  359. }
  360. else if (unit == "khz" || unit == "kHz")
  361. {
  362. pluginString += " unit:unit unit:khz ;\n";
  363. }
  364. else if (unit == "mhz" || unit == "mHz")
  365. {
  366. pluginString += " unit:unit unit:mhz ;\n";
  367. }
  368. else if (unit == "%")
  369. {
  370. pluginString += " unit:unit unit:pc ;\n";
  371. }
  372. else
  373. {
  374. pluginString += " unit:unit [\n";
  375. pluginString += " a unit:Unit ;\n";
  376. pluginString += " unit:name \"" + unit + "\" ;\n";
  377. pluginString += " unit:symbol \"" + unit + "\" ;\n";
  378. pluginString += " unit:render \"%f " + unit + "\" ;\n";
  379. pluginString += " ] ;\n";
  380. }
  381. }
  382. }
  383. // hints
  384. {
  385. const uint32_t hints(plugin.getParameterHints(i));
  386. if (hints & kParameterIsBoolean)
  387. pluginString += " lv2:portProperty lv2:toggled ;\n";
  388. if (hints & kParameterIsInteger)
  389. pluginString += " lv2:portProperty lv2:integer ;\n";
  390. if (hints & kParameterIsLogarithmic)
  391. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
  392. if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
  393. {
  394. pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
  395. pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
  396. }
  397. }
  398. if (i+1 == count)
  399. pluginString += " ] ;\n\n";
  400. else
  401. pluginString += " ] ,\n";
  402. }
  403. }
  404. pluginString += " doap:name \"" + String(plugin.getName()) + "\" ;\n";
  405. pluginString += " doap:maintainer [ foaf:name \"" + String(plugin.getMaker()) + "\" ] .\n";
  406. pluginFile << pluginString << std::endl;
  407. pluginFile.close();
  408. std::cout << " done!" << std::endl;
  409. }
  410. // ---------------------------------------------
  411. #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  412. {
  413. std::cout << "Writing " << uiTTL << "..."; std::cout.flush();
  414. std::fstream uiFile(uiTTL, std::ios::out);
  415. String uiString;
  416. uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  417. uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  418. uiString += "\n";
  419. uiString += "<" DISTRHO_UI_URI ">\n";
  420. uiString += " lv2:extensionData ui:idleInterface ,\n";
  421. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  422. uiString += " ui:showInterface ,\n";
  423. uiString += " <" LV2_PROGRAMS__Interface "> ;\n";
  424. # else
  425. uiString += " ui:showInterface ;\n";
  426. # endif
  427. uiString += "\n";
  428. uiString += " lv2:optionalFeature ui:noUserResize ,\n";
  429. uiString += " ui:resize ,\n";
  430. uiString += " ui:touch ;\n";
  431. uiString += "\n";
  432. uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
  433. uiString += " <" LV2_URID__map "> .\n";
  434. uiFile << uiString << std::endl;
  435. uiFile.close();
  436. std::cout << " done!" << std::endl;
  437. }
  438. #endif
  439. // ---------------------------------------------
  440. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  441. {
  442. std::cout << "Writing presets.ttl..."; std::cout.flush();
  443. std::fstream presetsFile("presets.ttl", std::ios::out);
  444. String presetsString;
  445. presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  446. presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
  447. presetsString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  448. # if DISTRHO_PLUGIN_WANT_STATE
  449. presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n";
  450. # endif
  451. presetsString += "\n";
  452. const uint32_t numParameters = plugin.getParameterCount();
  453. const uint32_t numPrograms = plugin.getProgramCount();
  454. # if DISTRHO_PLUGIN_WANT_STATE
  455. const uint32_t numStates = plugin.getStateCount();
  456. # endif
  457. const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");
  458. char strBuf[0xff+1];
  459. strBuf[0xff] = '\0';
  460. String presetString;
  461. for (uint32_t i=0; i<numPrograms; ++i)
  462. {
  463. std::snprintf(strBuf, 0xff, "%03i", i+1);
  464. plugin.loadProgram(i);
  465. presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
  466. # if DISTRHO_PLUGIN_WANT_STATE
  467. # warning "Exporting LV2 Presets with state not supported yet"
  468. # if 0
  469. for (uint32_t j=0; j<numStates; ++j)
  470. {
  471. if (j == 0)
  472. presetString += " state:state [\n";
  473. else
  474. presetString += " [\n";
  475. presetString += " <urn:distrho:" + plugin.getStateKey(j) + ">\n";
  476. presetString += "\"\"\"\n";
  477. presetString += plugin.getState(j);
  478. presetString += "\"\"\"\n";
  479. if (j+1 == numStates)
  480. {
  481. if (numParameters > 0)
  482. presetString += " ] ;\n\n";
  483. else
  484. presetString += " ] .\n\n";
  485. }
  486. else
  487. {
  488. presetString += " ] ,\n";
  489. }
  490. }
  491. # endif
  492. # endif
  493. for (uint32_t j=0; j <numParameters; ++j)
  494. {
  495. if (j == 0)
  496. presetString += " lv2:port [\n";
  497. else
  498. presetString += " [\n";
  499. presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n";
  500. if (plugin.getParameterHints(j) & kParameterIsInteger)
  501. presetString += " pset:value " + String(int(plugin.getParameterValue(j))) + " ;\n";
  502. else
  503. presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n";
  504. if (j+1 == numParameters)
  505. presetString += " ] .\n\n";
  506. else
  507. presetString += " ] ,\n";
  508. }
  509. presetsString += presetString;
  510. }
  511. presetsFile << presetsString << std::endl;
  512. presetsFile.close();
  513. std::cout << " done!" << std::endl;
  514. }
  515. #endif
  516. }