summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-04-22 06:26:38 +0000
committerDavid Robillard <d@drobilla.net>2011-04-22 06:26:38 +0000
commite41990c185f07027a3516b8dc4eb6f47436936d9 (patch)
tree10ca47560bd782e00bc08c56915d3e7e31490b6d
parentcf46c161552ab4ca049326e22e75338825a7e004 (diff)
downloadsuil-e41990c185f07027a3516b8dc4eb6f47436936d9.tar.gz
suil-e41990c185f07027a3516b8dc4eb6f47436936d9.tar.bz2
suil-e41990c185f07027a3516b8dc4eb6f47436936d9.zip
Remove UI instance API from SLV2 (apps should implement UIs via Suil now).
Remove UI extension API and header from public APIs entirely. Rework UI instance API to support multiple UIs and a more precise notion of embedding support. git-svn-id: http://svn.drobilla.net/lad/trunk/suil@3186 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/host.c48
-rw-r--r--src/instance.c55
-rw-r--r--src/suil_internal.h13
-rw-r--r--suil/suil.h119
-rw-r--r--wscript4
5 files changed, 180 insertions, 59 deletions
diff --git a/src/host.c b/src/host.c
new file mode 100644
index 0000000..281142d
--- /dev/null
+++ b/src/host.c
@@ -0,0 +1,48 @@
+/*
+ Copyright 2011 David Robillard <http://drobilla.net>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "suil_internal.h"
+
+SUIL_API
+SuilHost
+suil_host_new(SuilPortWriteFunc write_func,
+ SuilPortIndexFunc index_func,
+ SuilPortSubscribeFunc subscribe_func,
+ SuilPortUnsubscribeFunc unsubscribe_func)
+{
+ SuilHost host = malloc(sizeof(struct _SuilHost));
+ host->write_func = write_func;
+ host->index_func = index_func;
+ host->subscribe_func = subscribe_func;
+ host->unsubscribe_func = unsubscribe_func;
+ return host;
+}
+
+SUIL_API
+void
+suil_host_free(SuilHost host)
+{
+ free(host);
+}
diff --git a/src/instance.c b/src/instance.c
index 6458d51..42b87d3 100644
--- a/src/instance.c
+++ b/src/instance.c
@@ -39,14 +39,25 @@
#define QT4_UI_URI NS_UI "Qt4UI"
SUIL_API
-bool
-suil_ui_type_supported(const char* host_type_uri,
- const char* ui_type_uri)
+unsigned
+suil_ui_supported(const char* container_type_uri,
+ const char* ui_type_uri)
{
- return (!strcmp(host_type_uri, GTK2_UI_URI)
- || !strcmp(host_type_uri, QT4_UI_URI))
- && (!strcmp(ui_type_uri, GTK2_UI_URI)
- || !strcmp(ui_type_uri, QT4_UI_URI));
+ enum {
+ SUIL_WRAPPING_UNSUPPORTED = 0,
+ SUIL_WRAPPING_NATIVE = 1,
+ SUIL_WRAPPING_EMBEDDED = 2
+ };
+ if (!strcmp(container_type_uri, ui_type_uri)) {
+ return SUIL_WRAPPING_NATIVE;
+ } else if ((!strcmp(container_type_uri, GTK2_UI_URI)
+ && !strcmp(ui_type_uri, QT4_UI_URI))
+ || (!strcmp(container_type_uri, QT4_UI_URI)
+ && !strcmp(ui_type_uri, GTK2_UI_URI))) {
+ return SUIL_WRAPPING_EMBEDDED;
+ } else {
+ return SUIL_WRAPPING_UNSUPPORTED;
+ }
}
struct _SuilModule {
@@ -57,25 +68,25 @@ struct _SuilModule {
typedef struct _SuilModule* SuilModule;
static SuilModule
-get_wrap_module(const char* host_type_uri,
+get_wrap_module(const char* container_type_uri,
const char* ui_type_uri)
{
- if (!strcmp(host_type_uri, ui_type_uri)) {
+ if (!strcmp(container_type_uri, ui_type_uri)) {
return NULL;
}
const char* module_name = NULL;
- if (!strcmp(host_type_uri, QT4_UI_URI)
+ if (!strcmp(container_type_uri, QT4_UI_URI)
&& !strcmp(ui_type_uri, GTK2_UI_URI)) {
module_name = "libsuil_gtk2_in_qt4";
- } else if (!strcmp(host_type_uri, GTK2_UI_URI)
+ } else if (!strcmp(container_type_uri, GTK2_UI_URI)
&& !strcmp(ui_type_uri, QT4_UI_URI)) {
module_name = "libsuil_qt4_in_gtk2";
}
if (!module_name) {
SUIL_ERRORF("Unable to wrap UI type <%s> as type <%s>\n",
- ui_type_uri, host_type_uri);
+ ui_type_uri, container_type_uri);
return NULL;
}
@@ -114,14 +125,14 @@ get_wrap_module(const char* host_type_uri,
SUIL_API
SuilInstance
-suil_instance_new(const char* plugin_uri,
+suil_instance_new(SuilHost host,
+ SuilController controller,
+ const char* container_type_uri,
+ const char* plugin_uri,
const char* ui_uri,
+ const char* ui_type_uri,
const char* ui_bundle_path,
const char* ui_binary_path,
- const char* ui_type_uri,
- const char* host_type_uri,
- LV2UI_Write_Function write_function,
- LV2UI_Controller controller,
const LV2_Feature* const* features)
{
// Open UI library
@@ -166,9 +177,9 @@ suil_instance_new(const char* plugin_uri,
features = (const LV2_Feature* const*)&local_features;
}
- SuilModule module = get_wrap_module(host_type_uri, ui_type_uri);
+ SuilModule module = get_wrap_module(container_type_uri, ui_type_uri);
if (module) {
- module->init(host_type_uri, ui_type_uri, features);
+ module->init(container_type_uri, ui_type_uri, features);
}
// Instantiate UI
@@ -181,7 +192,7 @@ suil_instance_new(const char* plugin_uri,
descriptor,
plugin_uri,
ui_bundle_path,
- write_function,
+ host->write_func,
controller,
&instance->ui_widget,
features);
@@ -204,9 +215,9 @@ suil_instance_new(const char* plugin_uri,
}
if (module) {
- if (module->wrap(host_type_uri, ui_type_uri, instance)) {
+ if (module->wrap(container_type_uri, ui_type_uri, instance)) {
SUIL_ERRORF("Failed to wrap UI <%s> in type <%s>\n",
- ui_uri, host_type_uri);
+ ui_uri, container_type_uri);
suil_instance_free(instance);
return NULL;
}
diff --git a/src/suil_internal.h b/src/suil_internal.h
index 12dee3e..b8e6f0b 100644
--- a/src/suil_internal.h
+++ b/src/suil_internal.h
@@ -29,6 +29,8 @@
#include <assert.h>
#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
+
#ifdef __WIN32__
#include <windows.h>
#define dlopen(path, flags) LoadLibrary(path)
@@ -44,12 +46,19 @@ static inline char* dlerror(void) { return "Unknown error"; }
#define SUIL_ERRORF(fmt, ...) fprintf(stderr, "error: %s: " fmt, \
__func__, __VA_ARGS__)
+struct _SuilHost {
+ SuilPortWriteFunc write_func;
+ SuilPortIndexFunc index_func;
+ SuilPortSubscribeFunc subscribe_func;
+ SuilPortUnsubscribeFunc unsubscribe_func;
+};
+
struct _SuilInstance {
void* lib_handle;
const LV2UI_Descriptor* descriptor;
LV2UI_Handle handle;
- LV2UI_Widget ui_widget;
- LV2UI_Widget host_widget;
+ SuilWidget ui_widget;
+ SuilWidget host_widget;
};
/** Type of a module's suil_wrap_init function.
diff --git a/suil/suil.h b/suil/suil.h
index 10cc26e..17ffcf1 100644
--- a/suil/suil.h
+++ b/suil/suil.h
@@ -33,7 +33,7 @@
#include <stdbool.h>
#include <stdint.h>
-#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
#ifdef SUIL_SHARED
# ifdef __WIN32__
@@ -62,48 +62,116 @@ extern "C" {
@{
*/
+/**
+ UI host descriptor.
+
+ This contains the various functions that a plugin UI may use to communicate
+ with the plugin. It is passed to @ref suil_instance_new to provide
+ these functions to the UI.
+*/
+typedef struct _SuilHost* SuilHost;
+
/** An instance of an LV2 plugin UI. */
typedef struct _SuilInstance* SuilInstance;
+/** Opaque pointer to a UI widget. */
+typedef void* SuilWidget;
+
+/**
+ UI controller.
+
+ This is an opaque pointer passed by the user which is passed to the various
+ UI control functions (e.g. SuilPortWriteFunc). It is typically used to pass
+ a pointer to some controller object the host uses to communicate with
+ plugins.
+*/
+typedef void* SuilController;
+
+/** Function to write/send a value to a port. */
+typedef void (*SuilPortWriteFunc)(SuilController controller,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t protocol,
+ void const* buffer);
+
+/** Function to return the index for a port by symbol. */
+typedef uint32_t (*SuilPortIndexFunc)(SuilController controller,
+ const char* port_symbol);
+
+/** Function to subscribe to notifications for a port. */
+typedef uint32_t (*SuilPortSubscribeFunc)(SuilController controller,
+ uint32_t port_index,
+ uint32_t protocol);
+
+/** Function to unsubscribe from notifications for a port. */
+typedef uint32_t (*SuilPortUnsubscribeFunc)(SuilController controller,
+ uint32_t port_index,
+ uint32_t protocol);
+
+/**
+ Create a new UI host descriptor.
+ @param write_func Function to send a value to a plugin port.
+ @param index_func Function to get the index for a port by symbol.
+ @param subscribe_func Function to subscribe to port updates.
+ @param unsubscribe_func Function to unsubscribe from port updates.
+*/
+SUIL_API
+SuilHost
+suil_host_new(SuilPortWriteFunc write_func,
+ SuilPortIndexFunc index_func,
+ SuilPortSubscribeFunc subscribe_func,
+ SuilPortUnsubscribeFunc unsubscribe_func);
+
+/**
+ Free @a host.
+*/
+SUIL_API
+void
+suil_host_free(SuilHost host);
+
/**
- Return true iff it is possible to load a UI of a given type.
+ Check if suil can wrap a UI 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.
+ @return 0 if wrapping is unsupported, otherwise the quality of the wrapping
+ where 1 is the highest quality (direct native embedding with no wrapping)
+ and increaing values are of a progressively lower quality and/or stability.
*/
SUIL_API
-bool
-suil_ui_type_supported(const char* host_type_uri,
- const char* ui_type_uri);
+unsigned
+suil_ui_supported(const char* host_type_uri,
+ const char* ui_type_uri);
/**
Instantiate a UI for an LV2 plugin.
+ @param host Host descriptor.
+ @param controller Opaque host controller pointer.
+ @param container_type_uri URI of the desired host container widget type.
@param plugin_uri URI of the plugin to instantiate this UI for.
@param ui_uri URI of a specifically desired UI, or NULL to use the
best choice given @a type_uri.
+ @param ui_type_uri URI of the actual UI widget type.
@param ui_bundle_path Path of the UI bundle.
@param ui_binary_path Path of the UI binary.
- @param ui_type_uri URI of the actual UI widget type.
- @param host_type_uri URI of the desired widget type.
- @param write_function Write function as defined by the LV2 UI extension.
- @param controller Opaque controller to be passed to @a write_function.
@param features NULL-terminated array of supported features, or NULL.
@return A new UI instance, or NULL if instantiation failed.
*/
SUIL_API
SuilInstance
-suil_instance_new(const char* plugin_uri,
+suil_instance_new(SuilHost host,
+ SuilController controller,
+ const char* container_type_uri,
+ const char* plugin_uri,
const char* ui_uri,
+ const char* ui_type_uri,
const char* ui_bundle_path,
const char* ui_binary_path,
- const char* ui_type_uri,
- const char* host_type_uri,
- LV2UI_Write_Function write_function,
- LV2UI_Controller controller,
const LV2_Feature* const* features);
/**
Free a plugin UI instance.
+
The caller must ensure all references to the UI have been dropped before
calling this function (e.g. it has been removed from its parent).
*/
@@ -112,30 +180,15 @@ void
suil_instance_free(SuilInstance instance);
/**
- Get the LV2UI_Descriptor of a UI instance.
- This function should not be needed under normal circumstances.
-*/
-SUIL_API
-const LV2UI_Descriptor*
-suil_instance_get_descriptor(SuilInstance instance);
-
-/**
- Get the LV2UI_Handle of a UI instance.
- This function should not be needed under normal circumstances.
-*/
-SUIL_API
-LV2UI_Handle
-suil_instance_get_handle(SuilInstance instance);
-
-/**
Get the widget for a UI instance.
+
Returns an opaque pointer to a widget, the type of which is defined by the
corresponding parameter to suil_instantiate. Note this may be a wrapper
- widget created by Suil, and not necessarily an LV2UI_Widget implemented
- in an LV2 bundle.
+ widget created by Suil, and not necessarily the widget directly implemented
+ by the UI.
*/
SUIL_API
-LV2UI_Widget
+SuilWidget
suil_instance_get_widget(SuilInstance instance);
/**
diff --git a/wscript b/wscript
index 2ac9c91..74dc10e 100644
--- a/wscript
+++ b/wscript
@@ -7,7 +7,7 @@ from waflib.extras import autowaf as autowaf
import waflib.Logs as Logs, waflib.Options as Options
# Version of this package (even if built as a child)
-SUIL_VERSION = '0.0.0'
+SUIL_VERSION = '0.1.0'
# Library version (UNIX style major, minor, micro)
# major increment <=> incompatible changes
@@ -70,7 +70,7 @@ def build(bld):
# Library
obj = bld(features = 'c cshlib',
export_includes = ['.'],
- source = 'src/instance.c',
+ source = 'src/host.c src/instance.c',
target = 'suil',
includes = ['.'],
name = 'libsuil',