2 * LV2 ttl generator for JUCE Plugins
10 #include "JucePluginCharacteristics.h"
12 // These are dummy values!
20 kPlugCategSpacializer
,
23 kPlugCategRestoration
,
24 kPlugCategOfflineProcess
,
28 extern AudioProcessor
* JUCE_CALLTYPE
createPluginFilter();
30 String
name_to_symbol(String Name
)
32 String Symbol
= Name
.trimStart().trimEnd().replace(" ", "_").toLowerCase();
34 for (int i
=0; i
< Symbol
.length(); i
++) {
35 if (std::isalpha(Symbol
[i
]) || std::isdigit(Symbol
[i
]) || Symbol
[i
] == '_') {
44 String
float_to_string(float value
)
46 if (value
< 0.0f
|| value
> 1.0f
) {
47 std::cerr
<< "WARNING - Parameter uses out-of-bounds default value -> " << value
<< std::endl
;
50 if (!string
.contains(".")) {
58 return String("urn:" JucePlugin_Manufacturer
":" JucePlugin_Name
":" JucePlugin_VersionString
).replace(" ", "_");
61 String
get_juce_ui_uri()
63 return String("urn:" JucePlugin_Manufacturer
":" JucePlugin_Name
":JUCE-Native-UI").replace(" ", "_");
66 String
get_external_ui_uri()
68 return String("urn:" JucePlugin_Manufacturer
":" JucePlugin_Name
":JUCE-External-UI").replace(" ", "_");
71 String
get_binary_name()
73 return String(JucePlugin_Name
).replace(" ", "_");
76 String
get_plugin_type()
80 switch (JucePlugin_VSTCategory
) {
82 ptype
+= "lv2:InstrumentPlugin";
84 case kPlugCategAnalysis
:
85 ptype
+= "lv2:AnalyserPlugin";
87 case kPlugCategMastering
:
88 ptype
+= "lv2:DynamicsPlugin";
90 case kPlugCategSpacializer
:
91 ptype
+= "lv2:SpatialPlugin";
93 case kPlugCategRoomFx
:
94 ptype
+= "lv2:ModulatorPlugin";
96 case kPlugCategRestoration
:
97 ptype
+= "lv2:UtilityPlugin";
99 case kPlugCategGenerator
:
100 ptype
+= "lv2:GeneratorPlugin";
104 if (ptype
.isNotEmpty()) {
108 ptype
+= "lv2:Plugin";
112 String
get_manifest_ttl(String URI
, String Binary
)
115 manifest
+= "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
116 manifest
+= "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
118 manifest
+= "<" + URI
+ ">\n";
119 manifest
+= " a lv2:Plugin ;\n";
120 manifest
+= " lv2:binary <" + Binary
+ ".so> ;\n";
121 manifest
+= " rdfs:seeAlso <" + Binary
+".ttl> .\n";
125 String
get_plugin_ttl(String URI
, String Binary
)
127 AudioProcessor
* filter
= createPluginFilter();
130 plugin
+= "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
131 //plugin += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
132 //plugin += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
133 plugin
+= "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
134 plugin
+= "@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> .\n";
135 plugin
+= "@prefix lv2ui: <http://lv2plug.in/ns/extensions/ui#> .\n";
138 if (filter
->hasEditor()) {
139 plugin
+= "<" + get_external_ui_uri() + ">\n";
140 plugin
+= " a lv2ui:external ;\n";
141 plugin
+= " lv2ui:binary <" + Binary
+ ".so> .\n";
142 plugin
+= "<" + get_juce_ui_uri() + ">\n";
143 plugin
+= " a lv2ui:JUCEUI ;\n";
144 plugin
+= " lv2ui:binary <" + Binary
+ ".so> .\n";
148 plugin
+= "<" + URI
+ ">\n";
149 plugin
+= " a " + get_plugin_type() + " ;\n";
152 uint32_t i
, port_index
= 0;
154 #if JucePlugin_WantsMidiInput
155 plugin
+= " lv2:port [\n";
156 plugin
+= " a lv2:InputPort, lv2ev:EventPort;\n";
157 plugin
+= " lv2ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n";
158 plugin
+= " lv2:index " + String(port_index
) + ";\n";
159 plugin
+= " lv2:symbol \"midi_in\";\n";
160 plugin
+= " lv2:name \"MIDI Input\";\n";
161 plugin
+= " ] ;\n\n";
165 #if JucePlugin_ProducesMidiOutput
166 plugin
+= " lv2:port [\n";
167 plugin
+= " a lv2:OutputPort, lv2ev:EventPort;\n";
168 plugin
+= " lv2ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n";
169 plugin
+= " lv2:index " + String(port_index
) + ";\n";
170 plugin
+= " lv2:symbol \"midi_out\";\n";
171 plugin
+= " lv2:name \"MIDI Output\";\n";
172 plugin
+= " ] ;\n\n";
176 for (i
=0; i
<JucePlugin_MaxNumInputChannels
; i
++) {
178 plugin
+= " lv2:port [\n";
183 plugin
+= " a lv2:InputPort, lv2:AudioPort;\n";
184 //plugin += " lv2:datatype lv2:float;\n";
185 plugin
+= " lv2:index " + String(port_index
) + ";\n";
186 plugin
+= " lv2:symbol \"audio_in_" + String(i
+1) + "\";\n";
187 plugin
+= " lv2:name \"Audio Input " + String(i
+1) + "\";\n";
189 if (i
== JucePlugin_MaxNumInputChannels
-1) {
190 plugin
+= " ] ;\n\n";
198 for (i
=0; i
<JucePlugin_MaxNumOutputChannels
; i
++) {
200 plugin
+= " lv2:port [\n";
205 plugin
+= " a lv2:OutputPort, lv2:AudioPort;\n";
206 //plugin += " lv2:datatype lv2:float;\n";
207 plugin
+= " lv2:index " + String(port_index
) + ";\n";
208 plugin
+= " lv2:symbol \"audio_out_" + String(i
+1) + "\";\n";
209 plugin
+= " lv2:name \"Audio Output " + String(i
+1) + "\";\n";
211 if (i
== JucePlugin_MaxNumOutputChannels
-1) {
212 plugin
+= " ] ;\n\n";
220 for (i
=0; i
< filter
->getNumParameters(); i
++) {
222 plugin
+= " lv2:port [\n";
227 plugin
+= " a lv2:InputPort;\n";
228 plugin
+= " a lv2:ControlPort;\n";
229 //plugin += " lv2:datatype lv2:float;\n";
230 plugin
+= " lv2:index " + String(port_index
) + ";\n";
231 plugin
+= " lv2:symbol \"" + name_to_symbol(filter
->getParameterName(i
)) + "\";\n";
232 plugin
+= " lv2:name \"" + filter
->getParameterName(i
) + "\";\n";
233 plugin
+= " lv2:default " + float_to_string(filter
->getParameter(i
)) + ";\n";
234 plugin
+= " lv2:minimum 0.0;\n";
235 plugin
+= " lv2:maximum 1.0;\n";
238 if (i
== filter
->getNumParameters()-1) {
239 plugin
+= " ] ;\n\n";
247 if (filter
->getNumParameters() > 0) {
251 plugin
+= " doap:name \"" + String(JucePlugin_Name
) + "\" ;\n";
252 plugin
+= " doap:creator \"" + String(JucePlugin_Manufacturer
) + "\" .\n";
258 int main(int argc
, char *argv
[])
260 String URI
= get_uri();
261 String Binary
= get_binary_name();
262 String BinaryTTL
= Binary
+ ".ttl";
264 std::cout
<< "Writing manifest.ttl...";
265 std::fstream
manifest("manifest.ttl", std::ios::out
);
266 manifest
<< get_manifest_ttl(URI
, Binary
) << std::endl
;
268 std::cout
<< " done!" << std::endl
;
270 std::cout
<< "Writing " << BinaryTTL
;
271 std::fstream
plugin(BinaryTTL
.toUTF8(), std::ios::out
);
272 plugin
<< get_plugin_ttl(URI
, Binary
) << std::endl
;
274 std::cout
<< " done!" << std::endl
;