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.

368 lines
15KB

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