diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/plugin.c | 39 | ||||
-rw-r--r-- | src/pluginguiinstance.c | 168 | ||||
-rw-r--r-- | src/slv2_internal.h | 9 |
4 files changed, 217 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c7c70f6..43543b5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ libslv2_la_SOURCES = \ plugin.c \ pluginclass.c \ pluginclasses.c \ + pluginguiinstance.c \ plugininstance.c \ plugins.c \ port.c \ diff --git a/src/plugin.c b/src/plugin.c index 7dba104..1d63978 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -541,3 +541,42 @@ slv2_plugin_get_port_by_symbol(SLV2Plugin p, return NULL; } + +SLV2Values +slv2_plugin_get_guis(SLV2Plugin plugin) +{ + if (!plugin->rdf) + slv2_plugin_load(plugin); + + return slv2_plugin_get_value(plugin, SLV2_URI, + "http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#gui"); +} + + +SLV2Value +slv2_plugin_gui_get_library_uri(SLV2Plugin plugin, + SLV2Value gui) +{ + if (!plugin->rdf) + slv2_plugin_load(plugin); + + SLV2Values values = slv2_plugin_get_value_for_subject(plugin, gui, SLV2_URI, + "http://ll-plugins.nongnu.org/lv2/ext/gtk2gui#binary"); + + if (!values || slv2_values_size(values) == 0) { + slv2_values_free(values); + return NULL; + } + + SLV2Value value = slv2_values_get_at(values, 0); + if (!slv2_value_is_uri(value)) { + slv2_values_free(values); + return NULL; + } + + value = slv2_value_duplicate(value); + slv2_values_free(values); + + return value; +} + diff --git a/src/pluginguiinstance.c b/src/pluginguiinstance.c new file mode 100644 index 0000000..985f253 --- /dev/null +++ b/src/pluginguiinstance.c @@ -0,0 +1,168 @@ +/* SLV2 + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This library 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _XOPEN_SOURCE 500 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <dlfcn.h> +#include <slv2/types.h> +#include <slv2/plugin.h> +#include <slv2/pluginguiinstance.h> +#include <slv2/util.h> +#include "slv2_internal.h" + + +SLV2GUIInstance +slv2_plugin_gui_instantiate(SLV2Plugin plugin, + SLV2Value gui, + LV2UI_Set_Control_Function control_function, + LV2UI_Controller controller, + const LV2_Host_Feature** host_features) +{ + struct _GUIInstance* result = NULL; + + bool local_host_features = (host_features == NULL); + if (local_host_features) { + host_features = malloc(sizeof(LV2_Host_Feature)); + host_features[0] = NULL; + } + + const char* const lib_uri = slv2_value_as_uri(slv2_plugin_gui_get_library_uri(plugin, gui)); + const char* const lib_path = slv2_uri_to_path(lib_uri); + + if (!lib_path) + return NULL; + + dlerror(); + void* lib = dlopen(lib_path, RTLD_NOW); + if (!lib) { + fprintf(stderr, "Unable to open GUI library %s (%s)\n", lib_path, dlerror()); + return NULL; + } + + LV2UI_DescriptorFunction df = dlsym(lib, "lv2ui_descriptor"); + + if (!df) { + fprintf(stderr, "Could not find symbol 'lv2ui_descriptor', " + "%s is not a LV2 plugin GUI.\n", lib_path); + dlclose(lib); + return NULL; + } else { + // Search for plugin by URI + + // FIXME: Kluge to get bundle path (containing directory of binary) + char* bundle_path = strdup(plugin->binary_uri); + char* const bundle_path_end = strrchr(bundle_path, '/'); + if (bundle_path_end) + *(bundle_path_end+1) = '\0'; + printf("GUI bundle path: %s\n", bundle_path); + + for (uint32_t i=0; 1; ++i) { + + const LV2UI_Descriptor* ld = df(i); + + if (!ld) { + fprintf(stderr, "Did not find GUI %s in %s\n", + slv2_value_as_uri(gui), lib_path); + dlclose(lib); + break; // return NULL + } else if (!strcmp(ld->URI, slv2_value_as_uri(gui))) { + + printf("Found GUI %s at index %u in:\n\t%s\n\n", + librdf_uri_as_string(plugin->plugin_uri), i, lib_path); + + assert(ld->instantiate); + + // Create SLV2GUIInstance to return + result = malloc(sizeof(struct _GUIInstance)); + struct _GUIInstanceImpl* impl = malloc(sizeof(struct _GUIInstanceImpl)); + impl->lv2ui_descriptor = ld; + impl->lv2ui_handle = ld->instantiate(ld, + slv2_plugin_get_uri(plugin), + (char*)bundle_path, + control_function, + controller, + (struct _GtkWidget**)&impl->widget, + host_features); + impl->lib_handle = lib; + result->pimpl = impl; + break; + } + } + + free(bundle_path); + } + + assert(result); + assert(slv2_plugin_get_num_ports(plugin) > 0); + + // Failed to instantiate + if (result->pimpl->lv2ui_handle == NULL) { + //printf("Failed to instantiate %s\n", plugin->plugin_uri); + free(result); + return NULL; + } + + // Failed to create a widget, but still got a handle - this means that + // the plugin is buggy + if (result->pimpl->widget == NULL) { + slv2_gui_instance_free(result); + return NULL; + } + + if (local_host_features) + free(host_features); + + return result; +} + + +void +slv2_gui_instance_free(SLV2GUIInstance instance) +{ + struct _GUIInstance* i = (struct _GUIInstance*)instance; + i->pimpl->lv2ui_descriptor->cleanup(i->pimpl->lv2ui_handle); + i->pimpl->lv2ui_descriptor = NULL; + dlclose(i->pimpl->lib_handle); + i->pimpl->lib_handle = NULL; + free(i->pimpl); + i->pimpl = NULL; + free(i); +} + + +struct _GtkWidget* +slv2_gui_instance_get_widget(SLV2GUIInstance instance) { + return instance->pimpl->widget; +} + + +const LV2UI_Descriptor* +slv2_gui_instance_get_descriptor(SLV2GUIInstance instance) { + return instance->pimpl->lv2ui_descriptor; +} + + +LV2_Handle +slv2_gui_instance_get_handle(SLV2GUIInstance instance) { + return instance->pimpl->lv2ui_handle; +} + diff --git a/src/slv2_internal.h b/src/slv2_internal.h index 31913ad..4d20e4f 100644 --- a/src/slv2_internal.h +++ b/src/slv2_internal.h @@ -28,6 +28,7 @@ extern "C" { #include <inttypes.h> #include <librdf.h> #include <slv2/types.h> +#include <slv2/lv2-gtk2gui.h> @@ -97,6 +98,14 @@ struct _InstanceImpl { }; +/* ********* GUI Instance ********* */ +struct _GUIInstanceImpl { + void* lib_handle; + const LV2UI_Descriptor* lv2ui_descriptor; + LV2UI_Handle lv2ui_handle; + void* widget; +}; + /* ********* Plugin Class ********* */ |