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.

DistrhoPluginLV2export.cpp 16KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 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/resize-port.h"
  24. #include "lv2/state.h"
  25. #include "lv2/time.h"
  26. #include "lv2/ui.h"
  27. #include "lv2/units.h"
  28. #include "lv2/urid.h"
  29. #include "lv2/worker.h"
  30. #include "lv2/lv2_programs.h"
  31. #include <fstream>
  32. #include <iostream>
  33. #ifndef DISTRHO_PLUGIN_URI
  34. # error DISTRHO_PLUGIN_URI undefined!
  35. #endif
  36. #ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE
  37. # define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048
  38. #endif
  39. #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
  40. #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  41. // -----------------------------------------------------------------------
  42. DISTRHO_PLUGIN_EXPORT
  43. void lv2_generate_ttl(const char* const basename)
  44. {
  45. USE_NAMESPACE_DISTRHO
  46. // Dummy plugin to get data from
  47. d_lastBufferSize = 512;
  48. d_lastSampleRate = 44100.0;
  49. PluginExporter plugin;
  50. d_lastBufferSize = 0;
  51. d_lastSampleRate = 0.0;
  52. d_string pluginDLL(basename);
  53. d_string pluginTTL(pluginDLL + ".ttl");
  54. // ---------------------------------------------
  55. {
  56. std::cout << "Writing manifest.ttl..."; std::cout.flush();
  57. std::fstream manifestFile("manifest.ttl", std::ios::out);
  58. d_string manifestString;
  59. manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  60. manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  61. #if DISTRHO_PLUGIN_HAS_UI
  62. manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  63. #endif
  64. manifestString += "\n";
  65. manifestString += "<" DISTRHO_PLUGIN_URI ">\n";
  66. manifestString += " a lv2:Plugin ;\n";
  67. manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
  68. manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n";
  69. manifestString += "\n";
  70. #if DISTRHO_PLUGIN_HAS_UI
  71. manifestString += "<" DISTRHO_UI_URI ">\n";
  72. # if DISTRHO_OS_HAIKU
  73. manifestString += " a ui:BeUI ;\n";
  74. # elif DISTRHO_OS_MACOS
  75. manifestString += " a ui:CocoaUI ;\n";
  76. # elif DISTRHO_OS_WINDOWS
  77. manifestString += " a ui:WindowsUI ;\n";
  78. # else
  79. manifestString += " a ui:X11UI ;\n";
  80. # endif
  81. # if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  82. d_string pluginUI(pluginDLL);
  83. pluginUI.truncate(pluginDLL.rfind("_dsp"));
  84. pluginUI += "_ui";
  85. manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
  86. # else
  87. manifestString += " ui:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
  88. #endif
  89. manifestString += " lv2:extensionData ui:idleInterface ,\n";
  90. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  91. manifestString += " ui:showInterface ,\n";
  92. manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
  93. # else
  94. manifestString += " ui:showInterface ;\n";
  95. # endif
  96. manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
  97. manifestString += " ui:resize ,\n";
  98. manifestString += " ui:touch ;\n";
  99. # if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  100. manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
  101. manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
  102. manifestString += " <" LV2_OPTIONS__options "> ,\n";
  103. # else
  104. manifestString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
  105. # endif
  106. manifestString += " <" LV2_URID__map "> .\n";
  107. #endif
  108. manifestFile << manifestString << std::endl;
  109. manifestFile.close();
  110. std::cout << " done!" << std::endl;
  111. }
  112. // ---------------------------------------------
  113. {
  114. std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
  115. std::fstream pluginFile(pluginTTL, std::ios::out);
  116. d_string pluginString;
  117. // header
  118. #if DISTRHO_LV2_USE_EVENTS_IN
  119. pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
  120. #endif
  121. pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
  122. pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
  123. pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
  124. pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
  125. #if DISTRHO_PLUGIN_HAS_UI
  126. pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
  127. #endif
  128. pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
  129. pluginString += "\n";
  130. // plugin
  131. pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
  132. #if DISTRHO_PLUGIN_IS_SYNTH
  133. pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
  134. #else
  135. pluginString += " a lv2:Plugin ;\n";
  136. #endif
  137. pluginString += "\n";
  138. // extensionData
  139. pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
  140. #if DISTRHO_PLUGIN_WANT_STATE
  141. pluginString += ",\n <" LV2_OPTIONS__interface "> ";
  142. pluginString += ",\n <" LV2_WORKER__interface "> ";
  143. #endif
  144. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  145. pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
  146. #endif
  147. pluginString += ";\n\n";
  148. // optionalFeatures
  149. #if DISTRHO_PLUGIN_IS_RT_SAFE
  150. pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
  151. pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  152. #else
  153. pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
  154. #endif
  155. pluginString += "\n";
  156. // requiredFeatures
  157. pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
  158. pluginString += ",\n <" LV2_URID__map "> ";
  159. #if DISTRHO_PLUGIN_WANT_STATE
  160. pluginString += ",\n <" LV2_WORKER__schedule "> ";
  161. #endif
  162. pluginString += ";\n\n";
  163. // UI
  164. #if DISTRHO_PLUGIN_HAS_UI
  165. pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
  166. pluginString += "\n";
  167. #endif
  168. {
  169. uint32_t portIndex = 0;
  170. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  171. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
  172. {
  173. if (i == 0)
  174. pluginString += " lv2:port [\n";
  175. else
  176. pluginString += " [\n";
  177. pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
  178. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  179. pluginString += " lv2:symbol \"lv2_audio_in_" + d_string(i+1) + "\" ;\n";
  180. pluginString += " lv2:name \"Audio Input " + d_string(i+1) + "\" ;\n";
  181. if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
  182. pluginString += " ] ;\n\n";
  183. else
  184. pluginString += " ] ,\n";
  185. }
  186. pluginString += "\n";
  187. #endif
  188. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  189. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
  190. {
  191. if (i == 0)
  192. pluginString += " lv2:port [\n";
  193. else
  194. pluginString += " [\n";
  195. pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
  196. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  197. pluginString += " lv2:symbol \"lv2_audio_out_" + d_string(i+1) + "\" ;\n";
  198. pluginString += " lv2:name \"Audio Output " + d_string(i+1) + "\" ;\n";
  199. if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
  200. pluginString += " ] ;\n\n";
  201. else
  202. pluginString += " ] ,\n";
  203. }
  204. pluginString += "\n";
  205. #endif
  206. #if DISTRHO_LV2_USE_EVENTS_IN
  207. pluginString += " lv2:port [\n";
  208. pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
  209. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  210. pluginString += " lv2:name \"Events Input\" ;\n";
  211. pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
  212. pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  213. pluginString += " atom:bufferType atom:Sequence ;\n";
  214. # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
  215. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  216. # endif
  217. # if DISTRHO_PLUGIN_WANT_TIMEPOS
  218. pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
  219. # endif
  220. # if DISTRHO_PLUGIN_IS_SYNTH
  221. pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
  222. # endif
  223. pluginString += " ] ;\n\n";
  224. ++portIndex;
  225. #endif
  226. #if DISTRHO_LV2_USE_EVENTS_OUT
  227. pluginString += " lv2:port [\n";
  228. pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
  229. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  230. pluginString += " lv2:name \"Events Output\" ;\n";
  231. pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
  232. pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
  233. pluginString += " atom:bufferType atom:Sequence ;\n";
  234. pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
  235. pluginString += " ] ;\n\n";
  236. ++portIndex;
  237. #endif
  238. #if DISTRHO_PLUGIN_WANT_LATENCY
  239. pluginString += " lv2:port [\n";
  240. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  241. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  242. pluginString += " lv2:name \"Latency\" ;\n";
  243. pluginString += " lv2:symbol \"lv2_latency\" ;\n";
  244. pluginString += " lv2:designation lv2:latency ;\n";
  245. pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer ;\n";
  246. pluginString += " ] ;\n\n";
  247. ++portIndex;
  248. #endif
  249. for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
  250. {
  251. if (i == 0)
  252. pluginString += " lv2:port [\n";
  253. else
  254. pluginString += " [\n";
  255. if (plugin.isParameterOutput(i))
  256. pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
  257. else
  258. pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";
  259. pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
  260. pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";
  261. // symbol
  262. {
  263. d_string symbol(plugin.getParameterSymbol(i));
  264. if (symbol.isEmpty())
  265. symbol = "lv2_port_" + d_string(portIndex-1);
  266. pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
  267. }
  268. // ranges
  269. {
  270. const ParameterRanges& ranges(plugin.getParameterRanges(i));
  271. if (plugin.getParameterHints(i) & kParameterIsInteger)
  272. {
  273. pluginString += " lv2:default " + d_string(int(plugin.getParameterValue(i))) + " ;\n";
  274. pluginString += " lv2:minimum " + d_string(int(ranges.min)) + " ;\n";
  275. pluginString += " lv2:maximum " + d_string(int(ranges.max)) + " ;\n";
  276. }
  277. else
  278. {
  279. pluginString += " lv2:default " + d_string(plugin.getParameterValue(i)) + " ;\n";
  280. pluginString += " lv2:minimum " + d_string(ranges.min) + " ;\n";
  281. pluginString += " lv2:maximum " + d_string(ranges.max) + " ;\n";
  282. }
  283. }
  284. // unit
  285. {
  286. const d_string& unit(plugin.getParameterUnit(i));
  287. if (! unit.isEmpty())
  288. {
  289. if (unit == "db" || unit == "dB")
  290. {
  291. pluginString += " unit:unit unit:db ;\n";
  292. }
  293. else if (unit == "hz" || unit == "Hz")
  294. {
  295. pluginString += " unit:unit unit:hz ;\n";
  296. }
  297. else if (unit == "khz" || unit == "kHz")
  298. {
  299. pluginString += " unit:unit unit:khz ;\n";
  300. }
  301. else if (unit == "mhz" || unit == "mHz")
  302. {
  303. pluginString += " unit:unit unit:mhz ;\n";
  304. }
  305. else if (unit == "%")
  306. {
  307. pluginString += " unit:unit unit:pc ;\n";
  308. }
  309. else
  310. {
  311. pluginString += " unit:unit [\n";
  312. pluginString += " a unit:Unit ;\n";
  313. pluginString += " unit:name \"" + unit + "\" ;\n";
  314. pluginString += " unit:symbol \"" + unit + "\" ;\n";
  315. pluginString += " unit:render \"%f " + unit + "\" ;\n";
  316. pluginString += " ] ;\n";
  317. }
  318. }
  319. }
  320. // hints
  321. {
  322. const uint32_t hints(plugin.getParameterHints(i));
  323. if (hints & kParameterIsBoolean)
  324. pluginString += " lv2:portProperty lv2:toggled ;\n";
  325. if (hints & kParameterIsInteger)
  326. pluginString += " lv2:portProperty lv2:integer ;\n";
  327. if (hints & kParameterIsLogarithmic)
  328. pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ;\n";
  329. if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
  330. pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#expensive> ;\n";
  331. }
  332. if (i+1 == count)
  333. pluginString += " ] ;\n\n";
  334. else
  335. pluginString += " ] ,\n";
  336. }
  337. }
  338. pluginString += " doap:name \"" + d_string(plugin.getName()) + "\" ;\n";
  339. pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.getMaker()) + "\" ] .\n";
  340. pluginFile << pluginString << std::endl;
  341. pluginFile.close();
  342. std::cout << " done!" << std::endl;
  343. }
  344. }