mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 06:09:47 +02:00
446 lines
12 KiB
C
446 lines
12 KiB
C
/*
|
|
Copyright 2007-2014 David Robillard <http://drobilla.net>
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <float.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "lv2/lv2plug.in/ns/ext/port-groups/port-groups.h"
|
|
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
|
|
#include "lv2/lv2plug.in/ns/ext/event/event.h"
|
|
|
|
#include "lilv/lilv.h"
|
|
|
|
#include "lilv_config.h"
|
|
|
|
#ifdef _MSC_VER
|
|
# define isnan _isnan
|
|
#endif
|
|
|
|
LilvNode* applies_to_pred = NULL;
|
|
LilvNode* control_class = NULL;
|
|
LilvNode* event_class = NULL;
|
|
LilvNode* group_pred = NULL;
|
|
LilvNode* label_pred = NULL;
|
|
LilvNode* preset_class = NULL;
|
|
LilvNode* designation_pred = NULL;
|
|
LilvNode* supports_event_pred = NULL;
|
|
|
|
static void
|
|
print_port(const LilvPlugin* p,
|
|
uint32_t index,
|
|
float* mins,
|
|
float* maxes,
|
|
float* defaults)
|
|
{
|
|
const LilvPort* port = lilv_plugin_get_port_by_index(p, index);
|
|
|
|
printf("\n\tPort %d:\n", index);
|
|
|
|
if (!port) {
|
|
printf("\t\tERROR: Illegal/nonexistent port\n");
|
|
return;
|
|
}
|
|
|
|
bool first = true;
|
|
|
|
const LilvNodes* classes = lilv_port_get_classes(p, port);
|
|
printf("\t\tType: ");
|
|
LILV_FOREACH(nodes, i, classes) {
|
|
const LilvNode* value = lilv_nodes_get(classes, i);
|
|
if (!first) {
|
|
printf("\n\t\t ");
|
|
}
|
|
printf("%s", lilv_node_as_uri(value));
|
|
first = false;
|
|
}
|
|
|
|
if (lilv_port_is_a(p, port, event_class)) {
|
|
LilvNodes* supported = lilv_port_get_value(
|
|
p, port, supports_event_pred);
|
|
if (lilv_nodes_size(supported) > 0) {
|
|
printf("\n\t\tSupported events:\n");
|
|
LILV_FOREACH(nodes, i, supported) {
|
|
const LilvNode* value = lilv_nodes_get(supported, i);
|
|
printf("\t\t\t%s\n", lilv_node_as_uri(value));
|
|
}
|
|
}
|
|
lilv_nodes_free(supported);
|
|
}
|
|
|
|
LilvScalePoints* points = lilv_port_get_scale_points(p, port);
|
|
if (points)
|
|
printf("\n\t\tScale Points:\n");
|
|
LILV_FOREACH(scale_points, i, points) {
|
|
const LilvScalePoint* point = lilv_scale_points_get(points, i);
|
|
printf("\t\t\t%s = \"%s\"\n",
|
|
lilv_node_as_string(lilv_scale_point_get_value(point)),
|
|
lilv_node_as_string(lilv_scale_point_get_label(point)));
|
|
}
|
|
lilv_scale_points_free(points);
|
|
|
|
const LilvNode* sym = lilv_port_get_symbol(p, port);
|
|
printf("\n\t\tSymbol: %s\n", lilv_node_as_string(sym));
|
|
|
|
LilvNode* name = lilv_port_get_name(p, port);
|
|
printf("\t\tName: %s\n", lilv_node_as_string(name));
|
|
lilv_node_free(name);
|
|
|
|
LilvNodes* groups = lilv_port_get_value(p, port, group_pred);
|
|
if (lilv_nodes_size(groups) > 0) {
|
|
printf("\t\tGroup: %s\n",
|
|
lilv_node_as_string(lilv_nodes_get_first(groups)));
|
|
}
|
|
lilv_nodes_free(groups);
|
|
|
|
LilvNodes* designations = lilv_port_get_value(p, port, designation_pred);
|
|
if (lilv_nodes_size(designations) > 0) {
|
|
printf("\t\tDesignation: %s\n",
|
|
lilv_node_as_string(lilv_nodes_get_first(designations)));
|
|
}
|
|
lilv_nodes_free(designations);
|
|
|
|
if (lilv_port_is_a(p, port, control_class)) {
|
|
if (!isnan(mins[index]))
|
|
printf("\t\tMinimum: %f\n", mins[index]);
|
|
if (!isnan(maxes[index]))
|
|
printf("\t\tMaximum: %f\n", maxes[index]);
|
|
if (!isnan(defaults[index]))
|
|
printf("\t\tDefault: %f\n", defaults[index]);
|
|
}
|
|
|
|
LilvNodes* properties = lilv_port_get_properties(p, port);
|
|
if (lilv_nodes_size(properties) > 0)
|
|
printf("\t\tProperties: ");
|
|
first = true;
|
|
LILV_FOREACH(nodes, i, properties) {
|
|
if (!first) {
|
|
printf("\t\t ");
|
|
}
|
|
printf("%s\n", lilv_node_as_uri(lilv_nodes_get(properties, i)));
|
|
first = false;
|
|
}
|
|
if (lilv_nodes_size(properties) > 0)
|
|
printf("\n");
|
|
lilv_nodes_free(properties);
|
|
}
|
|
|
|
static void
|
|
print_plugin(LilvWorld* world,
|
|
const LilvPlugin* p)
|
|
{
|
|
LilvNode* val = NULL;
|
|
|
|
printf("%s\n\n", lilv_node_as_uri(lilv_plugin_get_uri(p)));
|
|
|
|
val = lilv_plugin_get_name(p);
|
|
if (val) {
|
|
printf("\tName: %s\n", lilv_node_as_string(val));
|
|
lilv_node_free(val);
|
|
}
|
|
|
|
const LilvPluginClass* pclass = lilv_plugin_get_class(p);
|
|
const LilvNode* class_label = lilv_plugin_class_get_label(pclass);
|
|
if (class_label) {
|
|
printf("\tClass: %s\n", lilv_node_as_string(class_label));
|
|
}
|
|
|
|
val = lilv_plugin_get_author_name(p);
|
|
if (val) {
|
|
printf("\tAuthor: %s\n", lilv_node_as_string(val));
|
|
lilv_node_free(val);
|
|
}
|
|
|
|
val = lilv_plugin_get_author_email(p);
|
|
if (val) {
|
|
printf("\tAuthor Email: %s\n", lilv_node_as_uri(val));
|
|
lilv_node_free(val);
|
|
}
|
|
|
|
val = lilv_plugin_get_author_homepage(p);
|
|
if (val) {
|
|
printf("\tAuthor Homepage: %s\n", lilv_node_as_uri(val));
|
|
lilv_node_free(val);
|
|
}
|
|
|
|
if (lilv_plugin_has_latency(p)) {
|
|
uint32_t latency_port = lilv_plugin_get_latency_port_index(p);
|
|
printf("\tHas latency: yes, reported by port %d\n", latency_port);
|
|
} else {
|
|
printf("\tHas latency: no\n");
|
|
}
|
|
|
|
printf("\tBundle: %s\n",
|
|
lilv_node_as_uri(lilv_plugin_get_bundle_uri(p)));
|
|
|
|
const LilvNode* binary_uri = lilv_plugin_get_library_uri(p);
|
|
if (binary_uri) {
|
|
printf("\tBinary: %s\n",
|
|
lilv_node_as_uri(lilv_plugin_get_library_uri(p)));
|
|
}
|
|
|
|
LilvUIs* uis = lilv_plugin_get_uis(p);
|
|
if (lilv_nodes_size(uis) > 0) {
|
|
printf("\tUIs:\n");
|
|
LILV_FOREACH(uis, i, uis) {
|
|
const LilvUI* ui = lilv_uis_get(uis, i);
|
|
printf("\t\t%s\n", lilv_node_as_uri(lilv_ui_get_uri(ui)));
|
|
|
|
const char* binary = lilv_node_as_uri(lilv_ui_get_binary_uri(ui));
|
|
|
|
const LilvNodes* types = lilv_ui_get_classes(ui);
|
|
LILV_FOREACH(nodes, t, types) {
|
|
printf("\t\t\tClass: %s\n",
|
|
lilv_node_as_uri(lilv_nodes_get(types, t)));
|
|
}
|
|
|
|
if (binary)
|
|
printf("\t\t\tBinary: %s\n", binary);
|
|
|
|
printf("\t\t\tBundle: %s\n",
|
|
lilv_node_as_uri(lilv_ui_get_bundle_uri(ui)));
|
|
}
|
|
}
|
|
lilv_uis_free(uis);
|
|
|
|
printf("\tData URIs: ");
|
|
const LilvNodes* data_uris = lilv_plugin_get_data_uris(p);
|
|
bool first = true;
|
|
LILV_FOREACH(nodes, i, data_uris) {
|
|
if (!first) {
|
|
printf("\n\t ");
|
|
}
|
|
printf("%s", lilv_node_as_uri(lilv_nodes_get(data_uris, i)));
|
|
first = false;
|
|
}
|
|
printf("\n");
|
|
|
|
/* Required Features */
|
|
|
|
LilvNodes* features = lilv_plugin_get_required_features(p);
|
|
if (features)
|
|
printf("\tRequired Features: ");
|
|
first = true;
|
|
LILV_FOREACH(nodes, i, features) {
|
|
if (!first) {
|
|
printf("\n\t ");
|
|
}
|
|
printf("%s", lilv_node_as_uri(lilv_nodes_get(features, i)));
|
|
first = false;
|
|
}
|
|
if (features)
|
|
printf("\n");
|
|
lilv_nodes_free(features);
|
|
|
|
/* Optional Features */
|
|
|
|
features = lilv_plugin_get_optional_features(p);
|
|
if (features)
|
|
printf("\tOptional Features: ");
|
|
first = true;
|
|
LILV_FOREACH(nodes, i, features) {
|
|
if (!first) {
|
|
printf("\n\t ");
|
|
}
|
|
printf("%s", lilv_node_as_uri(lilv_nodes_get(features, i)));
|
|
first = false;
|
|
}
|
|
if (features)
|
|
printf("\n");
|
|
lilv_nodes_free(features);
|
|
|
|
/* Extension Data */
|
|
|
|
LilvNodes* data = lilv_plugin_get_extension_data(p);
|
|
if (data)
|
|
printf("\tExtension Data: ");
|
|
first = true;
|
|
LILV_FOREACH(nodes, i, data) {
|
|
if (!first) {
|
|
printf("\n\t ");
|
|
}
|
|
printf("%s", lilv_node_as_uri(lilv_nodes_get(data, i)));
|
|
first = false;
|
|
}
|
|
if (data)
|
|
printf("\n");
|
|
lilv_nodes_free(data);
|
|
|
|
/* Presets */
|
|
|
|
LilvNodes* presets = lilv_plugin_get_related(p, preset_class);
|
|
if (presets)
|
|
printf("\tPresets: \n");
|
|
LILV_FOREACH(nodes, i, presets) {
|
|
const LilvNode* preset = lilv_nodes_get(presets, i);
|
|
lilv_world_load_resource(world, preset);
|
|
LilvNodes* titles = lilv_world_find_nodes(
|
|
world, preset, label_pred, NULL);
|
|
if (titles) {
|
|
const LilvNode* title = lilv_nodes_get_first(titles);
|
|
printf("\t %s\n", lilv_node_as_string(title));
|
|
lilv_nodes_free(titles);
|
|
} else {
|
|
fprintf(stderr, "Preset <%s> has no rdfs:label\n",
|
|
lilv_node_as_string(lilv_nodes_get(presets, i)));
|
|
}
|
|
}
|
|
lilv_nodes_free(presets);
|
|
|
|
/* Ports */
|
|
|
|
const uint32_t num_ports = lilv_plugin_get_num_ports(p);
|
|
float* mins = (float*)calloc(num_ports, sizeof(float));
|
|
float* maxes = (float*)calloc(num_ports, sizeof(float));
|
|
float* defaults = (float*)calloc(num_ports, sizeof(float));
|
|
lilv_plugin_get_port_ranges_float(p, mins, maxes, defaults);
|
|
|
|
for (uint32_t i = 0; i < num_ports; ++i)
|
|
print_port(p, i, mins, maxes, defaults);
|
|
|
|
free(mins);
|
|
free(maxes);
|
|
free(defaults);
|
|
}
|
|
|
|
static void
|
|
print_version(void)
|
|
{
|
|
printf(
|
|
"lv2info (lilv) " LILV_VERSION "\n"
|
|
"Copyright 2007-2014 David Robillard <http://drobilla.net>\n"
|
|
"License: <http://www.opensource.org/licenses/isc-license>\n"
|
|
"This is free software: you are free to change and redistribute it.\n"
|
|
"There is NO WARRANTY, to the extent permitted by law.\n");
|
|
}
|
|
|
|
static void
|
|
print_usage(void)
|
|
{
|
|
printf(
|
|
"Usage: lv2info [OPTION]... PLUGIN_URI\n"
|
|
"Print information about an installed LV2 plugin.\n\n"
|
|
" -p FILE Write Turtle description of plugin to FILE\n"
|
|
" -m FILE Add record of plugin to manifest FILE\n"
|
|
" --help Display this help and exit\n"
|
|
" --version Display version information and exit\n\n"
|
|
"For -p and -m, Turtle files are appended to (not overwritten),\n"
|
|
"and @prefix directives are only written if the file was empty.\n"
|
|
"This allows several plugins to be added to a single file.\n");
|
|
}
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
if (argc == 1) {
|
|
print_usage();
|
|
return 1;
|
|
}
|
|
|
|
const char* plugin_file = NULL;
|
|
const char* manifest_file = NULL;
|
|
const char* plugin_uri = NULL;
|
|
for (int i = 1; i < argc; ++i) {
|
|
if (!strcmp(argv[i], "--version")) {
|
|
print_version();
|
|
return 0;
|
|
} else if (!strcmp(argv[i], "--help")) {
|
|
print_usage();
|
|
return 0;
|
|
} else if (!strcmp(argv[i], "-p")) {
|
|
plugin_file = argv[++i];
|
|
} else if (!strcmp(argv[i], "-m")) {
|
|
manifest_file = argv[++i];
|
|
} else if (argv[i][0] == '-') {
|
|
print_usage();
|
|
return 1;
|
|
} else if (i == argc - 1) {
|
|
plugin_uri = argv[i];
|
|
}
|
|
}
|
|
|
|
int ret = 0;
|
|
|
|
LilvWorld* world = lilv_world_new();
|
|
lilv_world_load_all(world);
|
|
|
|
LilvNode* uri = lilv_new_uri(world, plugin_uri);
|
|
if (!uri) {
|
|
fprintf(stderr, "Invalid plugin URI\n");
|
|
lilv_world_free(world);
|
|
return 1;
|
|
}
|
|
|
|
applies_to_pred = lilv_new_uri(world, LV2_CORE__appliesTo);
|
|
control_class = lilv_new_uri(world, LILV_URI_CONTROL_PORT);
|
|
event_class = lilv_new_uri(world, LILV_URI_EVENT_PORT);
|
|
group_pred = lilv_new_uri(world, LV2_PORT_GROUPS__group);
|
|
label_pred = lilv_new_uri(world, LILV_NS_RDFS "label");
|
|
preset_class = lilv_new_uri(world, LV2_PRESETS__Preset);
|
|
designation_pred = lilv_new_uri(world, LV2_CORE__designation);
|
|
supports_event_pred = lilv_new_uri(world, LV2_EVENT__supportsEvent);
|
|
|
|
const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
|
|
const LilvPlugin* p = lilv_plugins_get_by_uri(plugins, uri);
|
|
|
|
if (p && plugin_file) {
|
|
LilvNode* base = lilv_new_file_uri(world, NULL, plugin_file);
|
|
|
|
FILE* plugin_fd = fopen(plugin_file, "a");
|
|
if (plugin_fd) {
|
|
lilv_plugin_write_description(world, p, base, plugin_fd);
|
|
fclose(plugin_fd);
|
|
} else {
|
|
fprintf(stderr, "error: Failed to open %s\n", plugin_file);
|
|
}
|
|
|
|
if (manifest_file) {
|
|
FILE* manifest_fd = fopen(manifest_file, "a");
|
|
if (manifest_fd) {
|
|
lilv_plugin_write_manifest_entry(
|
|
world, p, base, manifest_fd, plugin_file);
|
|
fclose(manifest_fd);
|
|
} else {
|
|
fprintf(stderr, "error: Failed to open %s\n", manifest_file);
|
|
}
|
|
}
|
|
lilv_node_free(base);
|
|
} else if (p) {
|
|
print_plugin(world, p);
|
|
} else {
|
|
fprintf(stderr, "Plugin not found.\n");
|
|
}
|
|
|
|
ret = (p != NULL ? 0 : -1);
|
|
|
|
lilv_node_free(uri);
|
|
|
|
lilv_node_free(supports_event_pred);
|
|
lilv_node_free(designation_pred);
|
|
lilv_node_free(preset_class);
|
|
lilv_node_free(label_pred);
|
|
lilv_node_free(group_pred);
|
|
lilv_node_free(event_class);
|
|
lilv_node_free(control_class);
|
|
lilv_node_free(applies_to_pred);
|
|
|
|
lilv_world_free(world);
|
|
return ret;
|
|
}
|
|
|