summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-02-24 09:00:54 +0000
committerDavid Robillard <d@drobilla.net>2011-02-24 09:00:54 +0000
commit25bd8988fb82e6132ae6c1b87e6d0b8087d61f1b (patch)
tree63d8b4a0a69c07d012af30b711a0a9cb80a160e6
parent5a7ed3f46fa2e0151a0f403824ae3a7df10a6c34 (diff)
downloadlilv-25bd8988fb82e6132ae6c1b87e6d0b8087d61f1b.tar.gz
lilv-25bd8988fb82e6132ae6c1b87e6d0b8087d61f1b.tar.bz2
lilv-25bd8988fb82e6132ae6c1b87e6d0b8087d61f1b.zip
Make Suil exclusively deal with instantiating (not choosing) UIs.
Add slv2_ui_instance_new as a replacement for slv2_ui_instantiate (now deprecated), which supports cross-toolkit embedding by taking an additional widget type pointer. Remove direct Suil dependency from Ingen. git-svn-id: http://svn.drobilla.net/lad/trunk/slv2@3022 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--slv2.pc.in2
-rw-r--r--slv2/slv2.h86
-rw-r--r--src/plugin.c82
-rw-r--r--src/pluginui.c19
-rw-r--r--src/pluginuiinstance.c182
-rw-r--r--src/slv2_internal.h10
-rw-r--r--wscript11
7 files changed, 272 insertions, 120 deletions
diff --git a/slv2.pc.in b/slv2.pc.in
index 87f807d..24b89a6 100644
--- a/slv2.pc.in
+++ b/slv2.pc.in
@@ -6,5 +6,5 @@ includedir=@includedir@
Name: libslv2
Version: @SLV2_VERSION@
Description: Convenience library for hosts to simplify LV2 plugin support
-Libs: @GLIB_LIBS@ @SORD_LIBS@ -L${libdir} -lslv2 -ldl
+Libs: @GLIB_LIBS@ @SORD_LIBS@ @SUIL_LIBS@ -L${libdir} -lslv2 -ldl
Cflags: @GLIB_CFLAGS@ @SORD_CFLAGS@ -I${includedir}
diff --git a/slv2/slv2.h b/slv2/slv2.h
index e703689..b7ce5bd 100644
--- a/slv2/slv2.h
+++ b/slv2/slv2.h
@@ -1085,17 +1085,31 @@ SLV2UI
slv2_uis_get_by_uri(SLV2UIs uis,
SLV2Value uri);
-/** Get a list of all UIs available for this plugin.
- * Note this returns the URI of the UI, and not the path/URI to its shared
- * library, use slv2_ui_get_library_uri with the values returned
- * here for that.
- *
+/** Get all UIs for @a plugin.
* Returned value must be freed by caller using slv2_uis_free.
*/
SLV2_API
SLV2UIs
slv2_plugin_get_uis(SLV2Plugin plugin);
+/** Get the default UI for @a plugin.
+ * This function makes a best effort at choosing a default UI for the given
+ * widget type. A native UI for the given widget type will be returned if one
+ * exists, otherwise a UI which can be wrapped by SLV2 will be returned.
+ *
+ * This function makes the common case (a plugin with a single UI, or a single
+ * UI per toolkit) simple, but is not fully powerful since a plugin may have
+ * several usable UIs. To support multiple UIs per plugin, use
+ * @ref slv2_ui_supported to determine which UIs are usable and choose a UI
+ * to instantiate from among them.
+ *
+ * @return NULL if there is no suitable UI.
+ */
+SLV2_API
+SLV2UI
+slv2_plugin_get_default_ui(SLV2Plugin plugin,
+ SLV2Value widget_type_uri);
+
/** @name Plugin UI
* @{
*/
@@ -1108,6 +1122,13 @@ SLV2_API
SLV2Value
slv2_ui_get_uri(SLV2UI ui);
+/** Return true iff @a ui can be instantiated to a widget of the given type.
+ */
+SLV2_API
+bool
+slv2_ui_supported(SLV2UI ui,
+ SLV2Value widget_type_uri);
+
/** Get the types (URIs of RDF classes) of a Plugin UI.
* @param ui The Plugin UI
* @return a shared value which must not be modified or freed.
@@ -1147,27 +1168,37 @@ slv2_ui_get_binary_uri(SLV2UI ui);
typedef struct _SLV2UIInstance* SLV2UIInstance;
+/** DEPRECATED: Instantiate a plugin UI.
+ * This function is deprecated, it does not support widget wrapping.
+ * Use @ref slv2_ui_instantiate instead.
+ */
+SLV2_DEPRECATED
+SLV2_API
+SLV2UIInstance
+slv2_ui_instantiate(SLV2Plugin plugin,
+ SLV2UI ui,
+ LV2UI_Write_Function write_function,
+ LV2UI_Controller controller,
+ const LV2_Feature* const* features);
+
/** Instantiate a plugin UI.
* The returned object represents shared library objects loaded into memory,
* it must be cleaned up with slv2_ui_instance_free when no longer
* needed.
*
- * @a plugin is not modified or directly referenced by the returned object
- * (instances store only a copy of the plugin's URI).
- *
- * @a features NULL-terminated array of features the host supports.
- * NULL may be passed if the host supports no additional features (unlike
- * the LV2 specification - SLV2 takes care of it).
+ * @param features NULL-terminated array of features the host supports.
+ * NULL may be passed if the host supports no additional features.
*
* @return NULL if instantiation failed.
*/
SLV2_API
SLV2UIInstance
-slv2_ui_instantiate(SLV2Plugin plugin,
- SLV2UI ui,
- LV2UI_Write_Function write_function,
- LV2UI_Controller controller,
- const LV2_Feature* const* features);
+slv2_ui_instance_new(SLV2Plugin plugin,
+ SLV2UI ui,
+ SLV2Value widget_type_uri,
+ LV2UI_Write_Function write_function,
+ LV2UI_Controller controller,
+ const LV2_Feature* const* features);
/** Free a plugin UI instance.
* @a instance is invalid after this call.
@@ -1185,24 +1216,39 @@ SLV2_API
LV2UI_Widget
slv2_ui_instance_get_widget(SLV2UIInstance instance);
-/** DEPRECATED: Get the LV2UI_Descriptor of the plugin UI instance.
+/** Notify a UI about a change in a plugin port.
+ */
+SLV2_API
+void
+slv2_ui_instance_port_event(SLV2UIInstance instance,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer);
+
+/** Return a data structure defined by some LV2 extension URI.
+ */
+SLV2_API
+const void*
+slv2_ui_instance_extension_data(SLV2UIInstance instance,
+ const char* uri);
+
+/** Get the LV2UI_Descriptor of the plugin UI instance.
* Normally hosts should not need to access the LV2UI_Descriptor directly,
* use the slv2_ui_instance_* functions.
*
* The returned descriptor is shared and must not be deleted.
*/
-SLV2_DEPRECATED
SLV2_API
const LV2UI_Descriptor*
slv2_ui_instance_get_descriptor(SLV2UIInstance instance);
-/** DEPRECATED: Get the LV2UI_Handle of the plugin UI instance.
+/** Get the LV2UI_Handle of the plugin UI instance.
* Normally hosts should not need to access the LV2UI_Handle directly,
* use the slv2_ui_instance_* functions.
*
* The returned handle is shared and must not be deleted.
*/
-SLV2_DEPRECATED
SLV2_API
LV2UI_Handle
slv2_ui_instance_get_handle(SLV2UIInstance instance);
diff --git a/src/plugin.c b/src/plugin.c
index f06cfd7..14a4266 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -27,8 +27,17 @@
#include <dlfcn.h>
#endif
+#include "slv2-config.h"
#include "slv2_internal.h"
+#ifdef HAVE_SUIL
+#include "suil/suil.h"
+#endif
+
+#define NS_UI (const uint8_t*)"http://lv2plug.in/ns/extensions/ui#"
+#define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#"
+#define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/"
+
/** Ownership of @a uri is taken */
SLV2Plugin
slv2_plugin_new(SLV2World world, SLV2Value uri, SLV2Value bundle_uri)
@@ -694,9 +703,6 @@ slv2_plugin_get_port_by_symbol(SLV2Plugin p,
return NULL;
}
-#define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#"
-#define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/"
-
static SLV2Node
slv2_plugin_get_author(SLV2Plugin p)
{
@@ -764,16 +770,14 @@ SLV2_API
SLV2UIs
slv2_plugin_get_uis(SLV2Plugin p)
{
-#define NS_UI (const uint8_t*)"http://lv2plug.in/ns/extensions/ui#"
-
- SLV2Node ui_ui = sord_new_uri(p->world->world, NS_UI "ui");
+ SLV2Node ui_ui_node = sord_new_uri(p->world->world, NS_UI "ui");
SLV2Node ui_binary_node = sord_new_uri(p->world->world, NS_UI "binary");
SLV2UIs result = slv2_uis_new();
SLV2Matches uis = slv2_plugin_find_statements(
p,
p->plugin_uri->val.uri_val,
- ui_ui,
+ ui_ui_node,
NULL);
FOREACH_MATCH(uis) {
@@ -801,7 +805,7 @@ slv2_plugin_get_uis(SLV2Plugin p)
slv2_match_end(uis);
slv2_node_free(ui_binary_node);
- slv2_node_free(ui_ui);
+ slv2_node_free(ui_ui_node);
if (slv2_uis_size(result) > 0) {
return result;
@@ -810,3 +814,65 @@ slv2_plugin_get_uis(SLV2Plugin p)
return NULL;
}
}
+
+SLV2_API
+SLV2UI
+slv2_plugin_get_default_ui(SLV2Plugin p,
+ SLV2Value widget_type_uri)
+{
+#ifdef HAVE_SUIL
+ SLV2Node ui_ui_node = sord_new_uri(p->world->world, NS_UI "ui");
+ SLV2Node ui_binary_node = sord_new_uri(p->world->world, NS_UI "binary");
+
+ SLV2Matches uis = slv2_plugin_find_statements(
+ p,
+ p->plugin_uri->val.uri_val,
+ ui_ui_node,
+ NULL);
+
+ SLV2UI native = NULL;
+ SLV2UI foreign = NULL;
+ FOREACH_MATCH(uis) {
+ SLV2Node ui = slv2_match_object(uis);
+ SLV2Value type = slv2_plugin_get_unique(p, ui, p->world->rdf_a_node);
+ SLV2Value binary = slv2_plugin_get_unique(p, ui, ui_binary_node);
+
+ if (sord_node_get_type(ui) != SORD_URI
+ || !slv2_value_is_uri(type)
+ || !slv2_value_is_uri(binary)) {
+ slv2_value_free(binary);
+ slv2_value_free(type);
+ SLV2_ERROR("Corrupt UI\n");
+ continue;
+ }
+
+ if (!native && slv2_value_equals(type, widget_type_uri)) {
+ native = slv2_ui_new(
+ p->world,
+ slv2_value_new_from_node(p->world, ui),
+ type,
+ binary);
+ break;
+ } else if (!foreign && suil_ui_type_supported(
+ slv2_value_as_uri(widget_type_uri),
+ slv2_value_as_uri(type))) {
+ foreign = slv2_ui_new(
+ p->world,
+ slv2_value_new_from_node(p->world, ui),
+ type,
+ binary);
+ } else {
+ slv2_value_free(binary);
+ slv2_value_free(type);
+ }
+ }
+ slv2_match_end(uis);
+
+ slv2_node_free(ui_binary_node);
+ slv2_node_free(ui_ui_node);
+
+ return (native) ? native : foreign;
+#else
+ return NULL;
+#endif
+}
diff --git a/src/pluginui.c b/src/pluginui.c
index d4ce24f..2c3bc94 100644
--- a/src/pluginui.c
+++ b/src/pluginui.c
@@ -24,6 +24,10 @@
#include "slv2_internal.h"
+#ifdef HAVE_SUIL
+#include "suil/suil.h"
+#endif
+
SLV2UI
slv2_ui_new(SLV2World world,
SLV2Value uri,
@@ -79,6 +83,20 @@ slv2_ui_get_uri(SLV2UI ui)
}
SLV2_API
+bool
+slv2_ui_supported(SLV2UI ui,
+ SLV2Value widget_type_uri)
+{
+#ifdef HAVE_SUIL
+ return suil_ui_type_supported(
+ slv2_value_as_uri(widget_type_uri),
+ slv2_value_as_uri(slv2_values_get_at(ui->classes, 0)));
+#else
+ return false;
+#endif
+}
+
+SLV2_API
SLV2Values
slv2_ui_get_classes(SLV2UI ui)
{
@@ -109,4 +127,3 @@ slv2_ui_get_binary_uri(SLV2UI ui)
assert(ui->binary_uri);
return ui->binary_uri;
}
-
diff --git a/src/pluginuiinstance.c b/src/pluginuiinstance.c
index b3cda0d..475340b 100644
--- a/src/pluginuiinstance.c
+++ b/src/pluginuiinstance.c
@@ -24,10 +24,13 @@
#include <stdlib.h>
#include <string.h>
-#include <dlfcn.h>
+#ifdef HAVE_SUIL
+#include "suil/suil.h"
+#endif
#include "slv2_internal.h"
+SLV2_DEPRECATED
SLV2_API
SLV2UIInstance
slv2_ui_instantiate(SLV2Plugin plugin,
@@ -36,116 +39,129 @@ slv2_ui_instantiate(SLV2Plugin plugin,
LV2UI_Controller controller,
const LV2_Feature* const* features)
{
- struct _SLV2UIInstance* result = NULL;
-
- const bool local_features = (features == NULL);
- if (local_features) {
- features = malloc(sizeof(LV2_Feature));
- ((LV2_Feature**)features)[0] = NULL;
- }
-
- const char* const lib_uri = slv2_value_as_string(slv2_ui_get_binary_uri(ui));
- 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) {
- SLV2_ERRORF("Unable to open UI library %s (%s)\n", lib_path, dlerror());
- return NULL;
- }
-
- LV2UI_DescriptorFunction df = (LV2UI_DescriptorFunction)
- slv2_dlfunc(lib, "lv2ui_descriptor");
+ return slv2_ui_instance_new(
+ plugin, ui, NULL, write_function, controller, features);
+}
- if (!df) {
- SLV2_ERRORF("Could not find symbol 'lv2ui_descriptor', "
- "%s is not a LV2 plugin UI.\n", lib_path);
- dlclose(lib);
+SLV2_API
+SLV2UIInstance
+slv2_ui_instance_new(SLV2Plugin plugin,
+ SLV2UI ui,
+ SLV2Value widget_type_uri,
+ LV2UI_Write_Function write_function,
+ LV2UI_Controller controller,
+ const LV2_Feature* const* features)
+{
+#ifdef HAVE_SUIL
+ const char* const bundle_uri = slv2_value_as_uri(slv2_ui_get_bundle_uri(ui));
+ const char* const bundle_path = slv2_uri_to_path(bundle_uri);
+ const char* const lib_uri = slv2_value_as_string(slv2_ui_get_binary_uri(ui));
+ const char* const lib_path = slv2_uri_to_path(lib_uri);
+ if (!bundle_path || !lib_path) {
return NULL;
- } else {
- const char* bundle_uri = slv2_value_as_uri(slv2_ui_get_bundle_uri(ui));
- const char* bundle_path = slv2_uri_to_path(bundle_uri);
-
- for (uint32_t i = 0; true; ++i) {
- const LV2UI_Descriptor* ld = df(i);
- if (!ld) {
- SLV2_ERRORF("Did not find UI %s in %s\n",
- slv2_value_as_uri(slv2_ui_get_uri(ui)), lib_path);
- dlclose(lib);
- break; // return NULL
- } else if (!strcmp(ld->URI, slv2_value_as_uri(slv2_ui_get_uri(ui)))) {
- assert(plugin->plugin_uri);
- assert(ld->instantiate);
-
- // Create SLV2UIInstance to return
- result = malloc(sizeof(struct _SLV2UIInstance));
- result->lv2ui_descriptor = ld;
- result->lv2ui_handle = ld->instantiate(
- ld,
- slv2_value_as_uri(slv2_plugin_get_uri(plugin)),
- (char*)bundle_path,
- write_function,
- controller,
- &result->widget,
- features);
- result->lib_handle = lib;
- break;
- }
- }
}
- // Failed to instantiate
- if (result == NULL || result->lv2ui_handle == NULL) {
- free(result);
- return NULL;
+ SLV2Value ui_type = slv2_values_get_at(ui->classes, 0);
+ if (!widget_type_uri) {
+ widget_type_uri = ui_type;
}
- // Failed to create a widget, but still got a handle (buggy UI)
- if (result->widget == NULL) {
- slv2_ui_instance_free(result);
+ SuilInstance suil_instance = suil_instance_new(
+ slv2_value_as_uri(slv2_plugin_get_uri(plugin)),
+ slv2_value_as_uri(slv2_ui_get_uri(ui)),
+ bundle_path,
+ lib_path,
+ slv2_value_as_uri(ui_type),
+ slv2_value_as_uri(widget_type_uri),
+ write_function,
+ controller,
+ features);
+
+ if (!suil_instance) {
return NULL;
}
- if (local_features) {
- free((LV2_Feature**)features);
- }
+ // Create SLV2UIInstance to return
+ struct _SLV2UIInstance* result = malloc(sizeof(struct _SLV2UIInstance));
+ result->instance = suil_instance;
return result;
+#else
+ return NULL;
+#endif
}
SLV2_API
void
slv2_ui_instance_free(SLV2UIInstance instance)
{
- if (instance == NULL)
- return;
-
- struct _SLV2UIInstance* i = (struct _SLV2UIInstance*)instance;
- i->lv2ui_descriptor->cleanup(i->lv2ui_handle);
- i->lv2ui_descriptor = NULL;
- dlclose(i->lib_handle);
- i->lib_handle = NULL;
- free(i);
+#ifdef HAVE_SUIL
+ if (instance) {
+ suil_instance_free(instance->instance);
+ free(instance);
+ }
+#else
+ return NULL;
+#endif
}
SLV2_API
LV2UI_Widget
-slv2_ui_instance_get_widget(SLV2UIInstance instance) {
- return instance->widget;
+slv2_ui_instance_get_widget(SLV2UIInstance instance)
+{
+#ifdef HAVE_SUIL
+ return suil_instance_get_widget(instance->instance);
+#else
+ return NULL;
+#endif
+}
+
+SLV2_API
+void
+slv2_ui_instance_port_event(SLV2UIInstance instance,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer)
+{
+ suil_instance_port_event(instance->instance,
+ port_index,
+ buffer_size,
+ format,
+ buffer);
+}
+
+SLV2_API
+const void*
+slv2_ui_instance_extension_data(SLV2UIInstance instance,
+ const char* uri)
+{
+#ifdef HAVE_SUIL
+ return suil_instance_extension_data(instance->instance, uri);
+#else
+ return NULL;
+#endif
}
SLV2_API
const LV2UI_Descriptor*
-slv2_ui_instance_get_descriptor(SLV2UIInstance instance) {
- return instance->lv2ui_descriptor;
+slv2_ui_instance_get_descriptor(SLV2UIInstance instance)
+{
+#ifdef HAVE_SUIL
+ return suil_instance_get_descriptor(instance->instance);
+#else
+ return NULL;
+#endif
}
SLV2_API
LV2UI_Handle
-slv2_ui_instance_get_handle(SLV2UIInstance instance) {
- return instance->lv2ui_handle;
+slv2_ui_instance_get_handle(SLV2UIInstance instance)
+{
+#ifdef HAVE_SUIL
+ return suil_instance_get_handle(instance->instance);
+#else
+ return NULL;
+#endif
}
diff --git a/src/slv2_internal.h b/src/slv2_internal.h
index 4314a73..1313bd3 100644
--- a/src/slv2_internal.h
+++ b/src/slv2_internal.h
@@ -41,6 +41,10 @@ extern "C" {
#include "lv2/lv2plug.in/ns/ext/dyn-manifest/dyn-manifest.h"
#endif
+#ifdef HAVE_SUIL
+#include "suil/suil.h"
+#endif
+
#include "slv2/slv2.h"
#define SLV2_NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#"
@@ -151,10 +155,7 @@ struct _SLV2InstanceImpl {
/* ********* UI Instance ********* */
struct _SLV2UIInstance {
- void* lib_handle;
- const LV2UI_Descriptor* lv2ui_descriptor;
- LV2UI_Handle lv2ui_handle;
- LV2UI_Widget widget;
+ SuilInstance instance;
};
/* ********* Plugin Class ********* */
@@ -238,6 +239,7 @@ struct _SLV2UI {
};
SLV2UIs slv2_uis_new();
+
SLV2UI
slv2_ui_new(SLV2World world,
SLV2Value uri,
diff --git a/wscript b/wscript
index b2073d2..5ca6ec0 100644
--- a/wscript
+++ b/wscript
@@ -89,7 +89,9 @@ def configure(conf):
autowaf.check_pkg(conf, 'jack', uselib_store='JACK',
atleast_version='0.107.0', mandatory=False)
autowaf.check_pkg(conf, 'jack', uselib_store='NEW_JACK',
- atleast_version='0.120.0', mandatory=False)
+ atleast_version='0.120.0', mandatory=False)
+ autowaf.check_pkg(conf, 'suil', uselib_store='SUIL',
+ atleast_version='0.0.0', mandatory=True)
autowaf.check_header(conf, 'lv2/lv2plug.in/ns/lv2core/lv2.h')
autowaf.check_header(conf, 'lv2/lv2plug.in/ns/extensions/ui/ui.h')
@@ -163,6 +165,9 @@ def configure(conf):
bool(conf.env['SLV2_DYN_MANIFEST']))
autowaf.display_msg(conf, "Python bindings",
bool(conf.env['SLV2_SWIG']))
+ autowaf.display_msg(conf, "UI wrapping support (via Suil)",
+ bool(conf.env['HAVE_SUIL']))
+
print
def build(bld):
@@ -200,7 +205,7 @@ def build(bld):
obj.install_path = '${LIBDIR}'
obj.cflags = [ '-fvisibility=hidden', '-DSLV2_SHARED', '-DSLV2_INTERNAL' ]
obj.linkflags = [ '-ldl' ]
- autowaf.use_lib(bld, obj, 'SORD SERD LV2CORE GLIB')
+ autowaf.use_lib(bld, obj, 'SORD SERD LV2CORE GLIB SUIL')
if bld.env['BUILD_TESTS']:
# Static library (for unit test code coverage)
@@ -212,7 +217,7 @@ def build(bld):
obj.install_path = ''
obj.cflags = [ '-fprofile-arcs', '-ftest-coverage' ]
obj.linkflags = [ '-ldl' ]
- autowaf.use_lib(bld, obj, 'SORD SERD LV2CORE GLIB')
+ autowaf.use_lib(bld, obj, 'SORD SERD LV2CORE GLIB SUIL')
# Unit test program
obj = bld(features = 'c cprogram')