summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/instance.c91
-rw-r--r--src/suil_internal.h16
-rw-r--r--src/uis.c42
-rw-r--r--suil/suil.h14
4 files changed, 124 insertions, 39 deletions
diff --git a/src/instance.c b/src/instance.c
index 83ec2d9..74d0948 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -29,9 +29,10 @@
SUIL_API
bool
-suil_ui_type_supported(const char* uri)
+suil_ui_type_supported(const char* host_type_uri,
+ const char* ui_type_uri)
{
- return !strcmp(uri, "http://lv2plug.in/ns/extensions/ui#GtkUI");
+ return !strcmp(ui_type_uri, "http://lv2plug.in/ns/extensions/ui#GtkUI");
}
SUIL_API
@@ -43,16 +44,20 @@ suil_instance_new(SuilUIs uis,
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;
+ // Find the UI to use
+ SuilUI ui = NULL;
+ if (ui_uri) {
+ ui = suil_uis_get(uis, ui_uri);
+ } else {
+ ui = suil_uis_get_best(uis, type_uri);
+ }
+ if (!ui) {
+ SUIL_ERRORF("No suitable UI found for <%s>\n",
+ suil_uis_get_plugin_uri(uis));
+ return NULL;
}
- SuilUI ui = uis->uis[0]; // FIXME
-
+ // Open UI library
dlerror();
void* lib = dlopen(ui->binary_path, RTLD_NOW);
if (!lib) {
@@ -61,38 +66,51 @@ suil_instance_new(SuilUIs uis,
return NULL;
}
+ // Get discovery function
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;
- }
+ }
+
+ // Get UI descriptor
+ const LV2UI_Descriptor* descriptor = NULL;
+ for (uint32_t i = 0; true; ++i) {
+ const LV2UI_Descriptor* ld = df(i);
+ if (!strcmp(ld->URI, ui->uri)) {
+ descriptor = ld;
+ break;
}
}
+ if (!descriptor) {
+ SUIL_ERRORF("Failed to find descriptor for <%s> in %s\n",
+ ui->uri, ui->binary_path);
+ dlclose(lib);
+ return NULL;
+ }
+
+ // Create empty local features array if necessary
+ const bool local_features = (features == NULL);
+ if (local_features) {
+ features = malloc(sizeof(LV2_Feature));
+ ((LV2_Feature**)features)[0] = NULL;
+ }
+
+ // Instantiate UI
+ struct _SuilInstance* instance = malloc(sizeof(struct _SuilInstance));
+ instance->lib_handle = lib;
+ instance->descriptor = descriptor;
+ instance->handle = descriptor->instantiate(
+ descriptor,
+ uis->plugin_uri,
+ ui->bundle_path,
+ write_function,
+ controller,
+ &instance->widget,
+ features);
if (local_features) {
free((LV2_Feature**)features);
@@ -100,12 +118,17 @@ suil_instance_new(SuilUIs uis,
// Failed to find or instantiate UI
if (!instance || !instance->handle) {
+ SUIL_ERRORF("Failed to instantiate UI <%s> in %s\n",
+ ui->uri, ui->binary_path);
free(instance);
+ dlclose(lib);
return NULL;
}
- // Failed to create a widget, but still got a handle (buggy UI)
+ // Got a handle, but failed to create a widget (buggy UI)
if (!instance->widget) {
+ SUIL_ERRORF("Widget creation failed for UI <%s> in %s\n",
+ ui->uri, ui->binary_path);
suil_instance_free(instance);
return NULL;
}
diff --git a/src/suil_internal.h b/src/suil_internal.h
index 4940b69..ed7ebd2 100644
--- a/src/suil_internal.h
+++ b/src/suil_internal.h
@@ -38,9 +38,9 @@ struct _SuilUI {
typedef struct _SuilUI* SuilUI;
struct _SuilUIs {
- char* plugin_uri;
- SuilUI* uis;
- size_t n_uis;
+ char* plugin_uri;
+ SuilUI* uis;
+ unsigned n_uis;
};
struct _SuilInstance {
@@ -50,6 +50,16 @@ struct _SuilInstance {
LV2UI_Widget widget;
};
+/** Get the UI with the given URI. */
+SuilUI
+suil_uis_get(SuilUIs uis,
+ const char* ui_uri);
+
+/** Get the best UI for the given type. */
+SuilUI
+suil_uis_get_best(SuilUIs uis,
+ const char* type_uri);
+
typedef void (*SuilVoidFunc)();
/** dlsym wrapper to return a function pointer (without annoying warning) */
diff --git a/src/uis.c b/src/uis.c
index 1880254..2ba234a 100644
--- a/src/uis.c
+++ b/src/uis.c
@@ -42,6 +42,48 @@ suil_uis_free(SuilUIs uis)
}
SUIL_API
+const char*
+suil_uis_get_plugin_uri(SuilUIs uis)
+{
+ return uis->plugin_uri;
+}
+
+SUIL_API
+SuilUI
+suil_uis_get(SuilUIs uis,
+ const char* ui_uri)
+{
+ for (unsigned i = 0; i < uis->n_uis; ++i) {
+ if (!strcmp(uis->uis[i]->uri, ui_uri)) {
+ return uis->uis[i];
+ }
+ }
+ return NULL;
+}
+
+SUIL_API
+SuilUI
+suil_uis_get_best(SuilUIs uis,
+ const char* type_uri)
+{
+ // Check for an exact type match
+ for (unsigned i = 0; i < uis->n_uis; ++i) {
+ if (!strcmp(uis->uis[i]->type_uri, type_uri)) {
+ return uis->uis[i];
+ }
+ }
+
+ // No exact match, use the first supported UI
+ for (unsigned i = 0; i < uis->n_uis; ++i) {
+ if (suil_ui_type_supported(type_uri, uis->uis[i]->type_uri)) {
+ return uis->uis[i];
+ }
+ }
+
+ return NULL;
+}
+
+SUIL_API
void
suil_uis_add(SuilUIs uis,
const char* uri,
diff --git a/suil/suil.h b/suil/suil.h
index 7e0dbec..f5e5584 100644
--- a/suil/suil.h
+++ b/suil/suil.h
@@ -59,10 +59,15 @@ typedef struct _SuilUIs* SuilUIs;
/** An instance of an LV2 plugin UI. */
typedef struct _SuilInstance* SuilInstance;
-/** Return true iff UIs of the given type are supported. */
+/** Return true iff it is possible to load a UI of a given type.
+ * @param host_type_uri The URI of the desired widget type of the host,
+ * corresponding to the @a type_uri parameter of @ref suil_instance_new.
+ * @param ui_type_uri The URI of the UI widget type.
+ */
SUIL_API
bool
-suil_ui_type_supported(const char* uri);
+suil_ui_type_supported(const char* host_type_uri,
+ const char* ui_type_uri);
/** Create a new empty set of UIs for a particular LV2 plugin. */
SUIL_API
@@ -74,6 +79,11 @@ SUIL_API
void
suil_uis_free(SuilUIs uis);
+/** Return the URI of the plugin this set of UIs is for. */
+SUIL_API
+const char*
+suil_uis_get_plugin_uri(SuilUIs uis);
+
/** Add a discovered UI to @a uis. */
SUIL_API
void