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.

397 lines
16KB

  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. }