From 3d3ae423b30e61c624b737a306d4fa66a9af411e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 22 Feb 2011 07:57:23 +0000 Subject: Initial UI instance implementation. git-svn-id: http://svn.drobilla.net/lad/trunk/suil@3010 a436a847-0d15-0410-975c-d299462d15a1 --- src/instance.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/suil_internal.h | 38 ++++++++++++++ src/uis.c | 45 ++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 src/instance.c (limited to 'src') diff --git a/src/instance.c b/src/instance.c new file mode 100644 index 0000000..82ace11 --- /dev/null +++ b/src/instance.c @@ -0,0 +1,147 @@ +/* Suil, a lightweight RDF syntax library. + * Copyright 2011 David Robillard + * + * Suil 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. + * + * Suil 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 details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#define _XOPEN_SOURCE 500 + +#include +#include +#include +#include +#include + +#include + +#include "suil_internal.h" + +SUIL_API +bool +suil_ui_type_supported(const char* uri) +{ + return !strcmp(uri, "http://lv2plug.in/ns/extensions/ui#GtkUI"); +} + +SUIL_API +SuilInstance +suil_instance_new(SuilUIs uis, + const char* type_uri, + const char* ui_uri, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + const LV2_Feature* const* features) +{ + struct _SuilInstance* instance = NULL; + + const bool local_features = (features == NULL); + if (local_features) { + features = malloc(sizeof(LV2_Feature)); + ((LV2_Feature**)features)[0] = NULL; + } + + SuilUI ui = uis->uis[0]; // FIXME + + dlerror(); + void* lib = dlopen(ui->binary_path, RTLD_NOW); + if (!lib) { + SUIL_ERRORF("Unable to open UI library %s (%s)\n", + ui->binary_path, dlerror()); + return NULL; + } + + LV2UI_DescriptorFunction df = (LV2UI_DescriptorFunction) + suil_dlfunc(lib, "lv2ui_descriptor"); + + if (!df) { + SUIL_ERRORF("Broken LV2 UI %s (no lv2ui_descriptor symbol found)\n", + ui->binary_path); + dlclose(lib); + return NULL; + } else { + for (uint32_t i = 0; true; ++i) { + const LV2UI_Descriptor* ld = df(i); + if (!ld) { + SUIL_ERRORF("No UI %s in %s\n", ui->uri, ui->binary_path); + dlclose(lib); + break; // return NULL + } else if ((ui_uri && !strcmp(ld->URI, ui_uri)) + || !strcmp(ui->type_uri, type_uri)) { + instance = malloc(sizeof(struct _SuilInstance)); + instance->descriptor = ld; + instance->handle = ld->instantiate( + ld, + uis->plugin_uri, + ui->bundle_path, + write_function, + controller, + &instance->widget, + features); + instance->lib_handle = lib; + break; + } + } + } + + if (local_features) { + free((LV2_Feature**)features); + } + + // Failed to find or instantiate UI + if (!instance || !instance->handle) { + free(instance); + return NULL; + } + + // Failed to create a widget, but still got a handle (buggy UI) + if (!instance->widget) { + suil_instance_free(instance); + return NULL; + } + + return instance; +} + +SUIL_API +void +suil_instance_free(SuilInstance instance) +{ + if (instance) { + instance->descriptor->cleanup(instance->handle); + dlclose(instance->lib_handle); + free(instance); + } +} + +SUIL_API +LV2UI_Widget +suil_instance_get_widget(SuilInstance instance) +{ + return instance->widget; +} + +SUIL_API +void +suil_instance_port_event(SuilInstance instance, + uint32_t port_index, + uint32_t buffer_size, + uint32_t format, + const void* buffer) +{ + instance->descriptor->port_event(instance->handle, + port_index, + buffer_size, + format, + buffer); +} diff --git a/src/suil_internal.h b/src/suil_internal.h index a755187..4940b69 100644 --- a/src/suil_internal.h +++ b/src/suil_internal.h @@ -21,6 +21,44 @@ #include #include +#include + #include "suil/suil.h" +#define SUIL_ERRORF(fmt, ...) fprintf(stderr, "error: %s: " fmt, \ + __func__, __VA_ARGS__) + +struct _SuilUI { + char* uri; + char* type_uri; + char* bundle_path; + char* binary_path; +}; + +typedef struct _SuilUI* SuilUI; + +struct _SuilUIs { + char* plugin_uri; + SuilUI* uis; + size_t n_uis; +}; + +struct _SuilInstance { + void* lib_handle; + const LV2UI_Descriptor* descriptor; + LV2UI_Handle handle; + LV2UI_Widget widget; +}; + +typedef void (*SuilVoidFunc)(); + +/** dlsym wrapper to return a function pointer (without annoying warning) */ +static inline SuilVoidFunc +suil_dlfunc(void* handle, const char* symbol) +{ + typedef SuilVoidFunc (*VoidFuncGetter)(void*, const char*); + VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; + return dlfunc(handle, symbol); +} + #endif // SUIL_INTERNAL_H diff --git a/src/uis.c b/src/uis.c index 51ea512..a2a4946 100644 --- a/src/uis.c +++ b/src/uis.c @@ -15,4 +15,49 @@ * along with this program. If not, see . */ +#define _XOPEN_SOURCE 500 + +#include + #include "suil_internal.h" + +SUIL_API +SuilUIs +suil_uis_new(const char* plugin_uri) +{ + SuilUIs uis = (SuilUIs)malloc(sizeof(struct _SuilUIs)); + uis->plugin_uri = strdup(plugin_uri); + uis->uis = malloc(sizeof(SuilUI)); + uis->uis[0] = (SuilUI)NULL; + uis->n_uis = 0; + return uis; +} + +SUIL_API +void +suil_uis_free(SuilUIs uis) +{ + free(uis->plugin_uri); + free(uis); +} + +SUIL_API +void +suil_uis_add(SuilUIs uis, + const char* uri, + const char* type_uri, + const char* bundle_path, + const char* binary_path) +{ + SuilUI ui = (SuilUI)malloc(sizeof(struct _SuilUI)); + ui->uri = strdup(uri); + ui->type_uri = strdup(type_uri); + ui->bundle_path = strdup(bundle_path); + ui->binary_path = strdup(binary_path); + + ++uis->n_uis; + uis->uis = realloc(uis->uis, sizeof(SuilUI) * (uis->n_uis + 1)); + assert(uis->uis[uis->n_uis - 1] == NULL); + uis->uis[uis->n_uis - 1] = ui; + uis->uis[uis->n_uis] = NULL; +} -- cgit v1.2.1