Fixing, almost there
[juce-lv2.git] / juce / source / src / audio / plugin_client / LV2 / lv2_rdf_gen.cpp
blobde3fb0b5d9753325f1893df91fc5c05b7d8a3633
1 /*
2 * LV2 ttl generator for JUCE Plugins
3 */
5 #include <fstream>
6 #include <iostream>
7 #include <stdint.h>
9 #include "juce.h"
10 #include "JucePluginCharacteristics.h"
12 // These are dummy values!
13 enum FakePlugCategory
15 kPlugCategUnknown,
16 kPlugCategEffect,
17 kPlugCategSynth,
18 kPlugCategAnalysis,
19 kPlugCategMastering,
20 kPlugCategSpacializer,
21 kPlugCategRoomFx,
22 kPlugSurroundFx,
23 kPlugCategRestoration,
24 kPlugCategOfflineProcess,
25 kPlugCategGenerator
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] == '_') {
36 // nothing
37 } else {
38 Symbol[i] == '_';
41 return Symbol;
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;
49 String string(value);
50 if (!string.contains(".")) {
51 string += ".0";
53 return string;
56 String get_uri()
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()
78 String ptype;
80 switch (JucePlugin_VSTCategory) {
81 case kPlugCategSynth:
82 ptype += "lv2:InstrumentPlugin";
83 break;
84 case kPlugCategAnalysis:
85 ptype += "lv2:AnalyserPlugin";
86 break;
87 case kPlugCategMastering:
88 ptype += "lv2:DynamicsPlugin";
89 break;
90 case kPlugCategSpacializer:
91 ptype += "lv2:SpatialPlugin";
92 break;
93 case kPlugCategRoomFx:
94 ptype += "lv2:ModulatorPlugin";
95 break;
96 case kPlugCategRestoration:
97 ptype += "lv2:UtilityPlugin";
98 break;
99 case kPlugCategGenerator:
100 ptype += "lv2:GeneratorPlugin";
101 break;
104 if (ptype.isNotEmpty()) {
105 ptype += ", ";
108 ptype += "lv2:Plugin";
109 return ptype;
112 String get_manifest_ttl(String URI, String Binary)
114 String manifest;
115 manifest += "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
116 manifest += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
117 manifest += "\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";
122 return manifest;
125 String get_plugin_ttl(String URI, String Binary)
127 AudioProcessor* filter = createPluginFilter();
129 String plugin;
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";
136 plugin += "\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";
145 plugin += "\n";
148 plugin += "<" + URI + ">\n";
149 plugin += " a " + get_plugin_type() + " ;\n";
150 plugin += "\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";
162 port_index++;
163 #endif
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";
173 port_index++;
174 #endif
176 for (i=0; i<JucePlugin_MaxNumInputChannels; i++) {
177 if (i == 0) {
178 plugin += " lv2:port [\n";
179 } else {
180 plugin += " [\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";
191 } else {
192 plugin += " ],\n";
195 port_index++;
198 for (i=0; i<JucePlugin_MaxNumOutputChannels; i++) {
199 if (i == 0) {
200 plugin += " lv2:port [\n";
201 } else {
202 plugin += " [\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";
213 } else {
214 plugin += " ],\n";
217 port_index++;
220 for (i=0; i < filter->getNumParameters(); i++) {
221 if (i == 0) {
222 plugin += " lv2:port [\n";
223 } else {
224 plugin += " [\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";
236 // TODO - units
238 if (i == filter->getNumParameters()-1) {
239 plugin += " ] ;\n\n";
240 } else {
241 plugin += " ],\n";
244 port_index++;
247 if (filter->getNumParameters() > 0) {
248 plugin += "\n";
251 plugin += " doap:name \"" + String(JucePlugin_Name) + "\" ;\n";
252 plugin += " doap:creator \"" + String(JucePlugin_Manufacturer) + "\" .\n";
254 delete filter;
255 return plugin;
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;
267 manifest.close();
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;
273 plugin.close();
274 std::cout << " done!" << std::endl;
276 return 0;