diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2019-04-17 19:51:34 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2019-04-17 19:51:34 +0200 |
commit | fb8588d8a0013b8da78b796f84ddcccf2bc9238e (patch) | |
tree | 0333d12df5a9e813904e4f5b4a42de7d4dba7443 /ttlgen.cc | |
parent | 34bfc5046bd297311a38dace8914c51905ca9d2e (diff) |
Added ttlgen dynamic ttl manifest generator for LV2 plugins.
Diffstat (limited to 'ttlgen.cc')
-rw-r--r-- | ttlgen.cc | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/ttlgen.cc b/ttlgen.cc new file mode 100644 index 0000000..77780d0 --- /dev/null +++ b/ttlgen.cc @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * ttlgen.cc + * + * Fri Jul 15 09:27:19 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of PluginGizmo. + * + * PluginGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * PluginGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with PluginGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <iostream> +#include <fstream> +#include <dlfcn.h> + +#include "pluginlv2.h" + +typedef PluginLV2* create_t(); + +static void header(std::ostream& output) +{ + output << "\ +# LV2 Plugin\n\ +# Copyright 2019 Bent Bisballe Nyeng <deva@aasimon.org>\n\ +#\n\ +# Permission to use, copy, modify, and/or distribute this software for any\n\ +# purpose with or without fee is hereby granted, provided that the above\n\ +# copyright notice and this permission notice appear in all copies.\n\ +#\n\ +# THIS SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n\ +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n\ +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n\ +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n\ +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n\ +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n\ +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\ +"; +} + +static void includes(std::ostream& output) +{ + output << "\ +@prefix doap: <http://usefulinc.com/ns/doap#> .\n\ +@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n\ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\ +@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\ +@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n\ +@prefix state: <http://lv2plug.in/ns/ext/state#> .\n\ +@prefix pprops: <http://lv2plug.in/ns/ext/port-props#> .\n\ +@prefix idpy: <http://harrisonconsoles.com/lv2/inlinedisplay#> .\n\ +@prefix time: <http://lv2plug.in/ns/ext/time#> .\n\ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\ +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\ +"; +} + +static void ui(Plugin& plugin, const std::string& pluginfile, std::ostream& output) +{ + if(!plugin.hasGUI()) + { + return; + } + + output << "\ +<" << plugin.getURI() << "/lv2#ui>\n\ + a ui:X11UI ;\n\ + lv2:requiredFeature ui:resize ;\n\ + lv2:extensionData ui:resize ;\n\ + lv2:requiredFeature ui:idleInterface ;\n\ + lv2:extensionData ui:idleInterface ;\n\ + lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> ;\n\ + ui:binary <" << pluginfile << "> .\n"; +} + +static void ports(Plugin& plugin, std::ostream& output) +{ + std::size_t port_index = 2; + for(std::size_t i = 0; i < plugin.getNumberOfMidiInputs(); ++i) + { + output << "\ + , [\n\ + a atom:AtomPort ,\n\ + lv2:InputPort;\n\ + atom:bufferType atom:Sequence ;\n\ + atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\ + lv2:index " << port_index << " ;\n\ + lv2:symbol \"control\" ;\n\ + lv2:name \"Control\"\n\ + ]"; + ++port_index; + } + + for(std::size_t i = 0; i < plugin.getNumberOfMidiOutputs(); ++i) + { + output << "\ + , [\n\ + a atom:AtomPort ,\n\ + lv2:OutputPort;\n\ + atom:bufferType atom:Sequence ;\n\ + atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\ + lv2:index " << port_index << " ;\n\ + lv2:symbol \"control\" ;\n\ + lv2:name \"Control\"\n\ + ]"; + ++port_index; + } + + std::size_t input_port_index = 1; + for(std::size_t i = 0; i < plugin.getNumberOfAudioInputs(); ++i) + { + output << "\ + , [\n\ + a lv2:AudioPort ,\n\ + lv2:InputPort ;\n\ + lv2:index " << port_index << " ;\n\ + lv2:symbol \"in" << input_port_index << "\" ;\n\ + lv2:name \"In" << input_port_index << "\"\n\ + ]"; + ++port_index; + ++input_port_index; + } + + std::size_t output_port_index = 1; + for(std::size_t i = 0; i < plugin.getNumberOfAudioOutputs(); ++i) + { + output << "\ + , [\n\ + a lv2:AudioPort ,\n\ + lv2:OutputPort ;\n\ + lv2:index " << port_index << " ;\n\ + lv2:symbol \"out" << output_port_index << "\" ;\n\ + lv2:name \"Out" << output_port_index << "\"\n\ + ]"; + ++port_index; + ++output_port_index; + } +} + +int main(int argc, char* argv[]) +{ + if(argc != 3) + { + std::cerr << "Missing argument.\n"; + std::cout << "Usage: " << argv[0] << " <plugin binary> <output file>\n"; + return 1; + } + + std::string library = argv[1]; + auto seppos = library.rfind("/"); + std::string binary = library; + if(seppos != std::string::npos) + { + binary = library.substr(seppos + 1); + } + + // load the plugin library + void* plugin = dlopen(library.data(), RTLD_LAZY); + if(!plugin) + { + std::cerr << "Cannot load library: " << dlerror() << std::endl; + std::cerr << "Library must have absolute path or prefix ./myplugin.so.\n"; + return 1; + } + + // reset errors + dlerror(); + + // load the symbols + create_t* create_plugin = (create_t*) dlsym(plugin, "createEffectInstance"); + const char* dlsym_error = dlerror(); + if(dlsym_error) + { + std::cerr << "Cannot load symbol create: " << dlsym_error << '\n'; + return 1; + } + + std::ofstream output(argv[2]); + + // create an instance of the class + Plugin* p = create_plugin(); + + header(output); + output << std::endl; + includes(output); + output << std::endl; + ui(*p, binary, output); + output << std::endl; + + output << "\ +<" << p->getURI() << "/lv2>\n\ + a lv2:Plugin ;\n\ + lv2:binary <" << binary << "> ;\n \ + a lv2:InstrumentPlugin ;\n\ + doap:name \"" << p->getEffectName() << "\" ;\n\ + doap:maintainer [\n\ + foaf:name \"" << p->getVendorString() << "\" ;\n\ + foaf:homepage <" << p->getHomepage() << "> ;\n\ + ] ;\n\ + doap:license <http://usefulinc.com/doap/licenses/gpl> ;\n\ + ui:ui <" << p->getURI() << "/lv2#ui> ;\n\ + doap:license <http://opensource.org/licenses/gpl-3.0> ;\n\ + lv2:optionalFeature <http://lv2plug.in/ns/ext/uri-map> ;\n\ + lv2:optionalFeature <http://lv2plug.in/ns/ext/event> ;\n\ + lv2:optionalFeature idpy:queue_draw ;\n\ + lv2:extensionData state:interface ;\n\ + lv2:port [\n\ + a lv2:InputPort, lv2:ControlPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"lv2_freewheel\" ;\n\ + lv2:name \"Freewheel\" ;\n\ + lv2:default 0.0 ;\n\ + lv2:minimum 0.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:designation <http://lv2plug.in/ns/lv2core#freeWheeling> ;\n\ + lv2:portProperty <http://lv2plug.in/ns/lv2core#freeWheeling> ;\n\ + lv2:portProperty lv2:toggled ;\n\ + lv2:portProperty pprops:hasStrictBounds;\n\ + ] , [\n\ + a lv2:OutputPort, lv2:ControlPort ;\n\ + lv2:designation <http://lv2plug.in/ns/lv2core#latency>;\n\ + lv2:index 1;\n\ + lv2:symbol \"latency\";\n\ + lv2:name \"Latency\";\n\ + lv2:minimum 0;\n\ + lv2:maximum 192000;\n\ + lv2:portProperty lv2:reportsLatency, lv2:integer;\n\ + ]"; + + ports(*p, output); + + output << " .\n"; + + // FIXME: The plugin is never deleted, but since we're terminating now anyway + // it doesn't matter much... + + // unload the plugin library + dlclose(plugin); + + return 0; +} |