diff options
-rw-r--r-- | src/host.c | 48 | ||||
-rw-r--r-- | src/instance.c | 55 | ||||
-rw-r--r-- | src/suil_internal.h | 13 | ||||
-rw-r--r-- | suil/suil.h | 119 | ||||
-rw-r--r-- | wscript | 4 |
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); /** @@ -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', |