diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | src/host.c | 38 | ||||
-rw-r--r-- | src/instance.c | 31 | ||||
-rw-r--r-- | src/qt4_in_gtk2.cpp | 3 | ||||
-rw-r--r-- | src/qt5_in_gtk2.cpp | 3 | ||||
-rw-r--r-- | src/suil_internal.h | 41 | ||||
-rw-r--r-- | src/x11.c | 28 | ||||
-rw-r--r-- | suil/suil.h | 19 | ||||
-rw-r--r-- | wscript | 17 |
10 files changed, 151 insertions, 37 deletions
@@ -18,3 +18,4 @@ Contributors: * Qt5 wrappers * Stefan Westerfeld * Qt5 in Gtk2 support + * Initialization API @@ -1,8 +1,11 @@ -suil (0.8.5) unstable; +suil (0.8.7) unstable; * Add support for X11 in Gtk3 + * Add support for Qt5 in Gtk2 + * Add suil_init() to support early initialization and passing any necessary + information that may be needed in the future (thanks Stefan Westerfeld) - -- David Robillard <d@drobilla.net> Sat, 10 Dec 2016 10:08:03 -0500 + -- David Robillard <d@drobilla.net> Sat, 18 Mar 2017 12:01:55 +0100 suil (0.8.4) stable; @@ -1,5 +1,6 @@ /* - Copyright 2011-2015 David Robillard <http://drobilla.net> + Copyright 2011-2017 David Robillard <http://drobilla.net> + Copyright 2017 Stefan Westerfeld <stefan@space.twc.de> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -16,6 +17,9 @@ #include "./suil_internal.h" +int suil_argc = 0; +char** suil_argv = NULL; + SUIL_API SuilHost* suil_host_new(SuilPortWriteFunc write_func, @@ -28,6 +32,8 @@ suil_host_new(SuilPortWriteFunc write_func, host->index_func = index_func; host->subscribe_func = subscribe_func; host->unsubscribe_func = unsubscribe_func; + host->argc = suil_argc; + host->argv = suil_argv; return host; } @@ -50,3 +56,33 @@ suil_host_free(SuilHost* host) free(host); } } + +static void +suil_load_init_module(const char* module_name) +{ + void* const lib = suil_open_module(module_name); + if (!lib) { + return; + } + + SuilVoidFunc init_func = (SuilVoidFunc)suil_dlfunc(lib, "suil_host_init"); + if (init_func) { + (*init_func)(); + } else { + SUIL_ERRORF("Corrupt init module %s\n", module_name); + } + + dlclose(lib); +} + +SUIL_API +void +suil_init(int* argc, char*** argv, SuilArg key, ...) +{ + suil_argc = argc ? *argc : 0; + suil_argv = argv ? *argv : NULL; + +#if SUIL_WITH_X11 + suil_load_init_module("suil_x11"); +#endif +} diff --git a/src/instance.c b/src/instance.c index f05cc86..2563bf6 100644 --- a/src/instance.c +++ b/src/instance.c @@ -143,25 +143,8 @@ open_wrapper(SuilHost* host, return NULL; } - const char* const env_dir = getenv("SUIL_MODULE_DIR"); - const char* const mod_dir = env_dir ? env_dir : SUIL_MODULE_DIR; - - const size_t path_len = strlen(mod_dir) - + strlen(SUIL_DIR_SEP SUIL_MODULE_PREFIX SUIL_MODULE_EXT) - + strlen(module_name) - + 2; - - char* const path = (char*)calloc(path_len, 1); - snprintf(path, path_len, "%s%s%s%s%s", - mod_dir, SUIL_DIR_SEP, - SUIL_MODULE_PREFIX, module_name, SUIL_MODULE_EXT); - - // Open wrap module - dlerror(); - void* lib = dlopen(path, RTLD_NOW); + void* const lib = suil_open_module(module_name); if (!lib) { - SUIL_ERRORF("Unable to open wrap module %s (%s)\n", path, dlerror()); - free(path); return NULL; } @@ -176,17 +159,13 @@ open_wrapper(SuilHost* host, n_features) : NULL; - if (!wrapper) { - SUIL_ERRORF("Corrupt module %s\n", path); + if (wrapper) { + wrapper->lib = lib; + } else { + SUIL_ERRORF("Corrupt wrap module %s\n", module_name); dlclose(lib); - free(path); - return NULL; } - free(path); - - wrapper->lib = lib; - return wrapper; } diff --git a/src/qt4_in_gtk2.cpp b/src/qt4_in_gtk2.cpp index 443c8f0..fbec381 100644 --- a/src/qt4_in_gtk2.cpp +++ b/src/qt4_in_gtk2.cpp @@ -142,8 +142,7 @@ suil_wrapper_new(SuilHost* host, if (qApp) { wrap->app = qApp; } else { - static int argc = 0; - wrap->app = new QApplication(argc, NULL, true); + wrap->app = new QApplication(host->argc, host->argv, true); } wrap->wrapper = NULL; diff --git a/src/qt5_in_gtk2.cpp b/src/qt5_in_gtk2.cpp index 0823afc..bd7957e 100644 --- a/src/qt5_in_gtk2.cpp +++ b/src/qt5_in_gtk2.cpp @@ -146,8 +146,7 @@ suil_wrapper_new(SuilHost* host, if (qApp) { wrap->app = qApp; } else { - static int argc = 0; - wrap->app = new QApplication(argc, NULL, true); + wrap->app = new QApplication(host->argc, host->argv, true); } wrap->wrapper = NULL; diff --git a/src/suil_internal.h b/src/suil_internal.h index 67f1412..4b7452f 100644 --- a/src/suil_internal.h +++ b/src/suil_internal.h @@ -1,5 +1,5 @@ /* - Copyright 2007-2012 David Robillard <http://drobilla.net> + Copyright 2007-2017 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -18,6 +18,7 @@ #define SUIL_INTERNAL_H #include <assert.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -49,6 +50,8 @@ struct SuilHostImpl { SuilPortUnsubscribeFunc unsubscribe_func; SuilTouchFunc touch_func; void* gtk_lib; + int argc; + char** argv; }; struct _SuilWrapper; @@ -92,7 +95,7 @@ typedef SuilWrapper* (*SuilWrapperNewFunc)(SuilHost* host, LV2_Feature*** features, unsigned n_features); -/** Prototype for suil_wrapper_new in each module. */ +/** Prototype for suil_wrapper_new in each wrapper module. */ SUIL_LIB_EXPORT SuilWrapper* suil_wrapper_new(SuilHost* host, @@ -101,6 +104,37 @@ suil_wrapper_new(SuilHost* host, LV2_Feature*** features, unsigned n_features); +/** Prototype for suil_host_init in each init module. */ +SUIL_LIB_EXPORT +void +suil_host_init(void); + +/** Dynamically load the suil module with the given name. */ +static inline void* +suil_open_module(const char* module_name) +{ + const char* const env_dir = getenv("SUIL_MODULE_DIR"); + const char* const mod_dir = env_dir ? env_dir : SUIL_MODULE_DIR; + const size_t path_len = strlen(mod_dir) + + strlen(SUIL_DIR_SEP SUIL_MODULE_PREFIX SUIL_MODULE_EXT) + + strlen(module_name) + + 2; + + char* const path = (char*)calloc(path_len, 1); + snprintf(path, path_len, "%s%s%s%s%s", + mod_dir, SUIL_DIR_SEP, + SUIL_MODULE_PREFIX, module_name, SUIL_MODULE_EXT); + + dlerror(); + void* lib = dlopen(path, RTLD_NOW); + if (!lib) { + SUIL_ERRORF("Failed to open module %s (%s)\n", path, dlerror()); + } + + free(path); + return lib; +} + typedef void (*SuilVoidFunc)(void); /** dlsym wrapper to return a function pointer (without annoying warning) */ @@ -140,6 +174,9 @@ suil_add_feature(LV2_Feature*** features, *n += 1; } +extern int suil_argc; +extern char** suil_argv; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/x11.c b/src/x11.c new file mode 100644 index 0000000..4c8a15a --- /dev/null +++ b/src/x11.c @@ -0,0 +1,28 @@ +/* + Copyright 2017 David Robillard <http://drobilla.net> + Copyright 2017 Stefan Westerfeld <stefan@space.twc.de> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include <X11/Xlib.h> + +#include "./suil_internal.h" + +SUIL_LIB_EXPORT +void +suil_host_init(void) +{ + // This must be called first for Qt5 in Gtk2 to function correctly + XInitThreads(); +} diff --git a/suil/suil.h b/suil/suil.h index 16df9bd..5f1b7fe 100644 --- a/suil/suil.h +++ b/suil/suil.h @@ -1,5 +1,5 @@ /* - Copyright 2011-2014 David Robillard <http://drobilla.net> + Copyright 2011-2017 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -124,6 +124,23 @@ typedef void (*SuilTouchFunc)( uint32_t port_index, bool grabbed); +/** Initialization argument. */ +typedef enum { + SUIL_ARG_NONE +} SuilArg; + +/** + Initialize suil. + + This function should be called as early as possible, before any other GUI + toolkit functions. The variable argument list is a sequence of SuilArg keys + and corresponding value pairs for passing any necessary platform-specific + information. It must be terminated with SUIL_ARG_NONE. +*/ +SUIL_API +void +suil_init(int* argc, char*** argv, SuilArg key, ...); + /** Create a new UI host descriptor. @param write_func Function to send a value to a plugin port. @@ -10,7 +10,7 @@ from waflib import TaskGen # major increment <=> incompatible changes # minor increment <=> compatible changes (additions) # micro increment <=> no interface changes -SUIL_VERSION = '0.8.5' +SUIL_VERSION = '0.8.7' SUIL_MAJOR_VERSION = '0' # Mandatory waf variables @@ -65,6 +65,7 @@ def configure(conf): conf.env.NODELETE_FLAGS = ['-Wl,-z,nodelete'] autowaf.check_pkg(conf, 'lv2', atleast_version='1.12.0', uselib_store='LV2') + autowaf.check_pkg(conf, 'x11', uselib_store='X11') if not Options.options.no_gtk: autowaf.check_pkg(conf, 'gtk+-2.0', uselib_store='GTK2', @@ -133,6 +134,9 @@ def configure(conf): if conf.env.HAVE_QT5: autowaf.define(conf, 'SUIL_WITH_X11_IN_QT5', 1) + if conf.env.HAVE_X11: + autowaf.define(conf, 'SUIL_WITH_X11', 1) + module_prefix = '' module_ext = '' if conf.env.PARDEBUG: @@ -346,6 +350,17 @@ def build(bld): lib = modlib) autowaf.use_lib(bld, obj, 'QT5 LV2') + if bld.env.SUIL_WITH_X11: + obj = bld(features = 'c cshlib', + source = 'src/x11.c', + target = 'suil_x11', + includes = ['.'], + defines = ['SUIL_SHARED', 'SUIL_INTERNAL'], + install_path = module_dir, + cflags = cflags, + lib = modlib) + autowaf.use_lib(bld, obj, 'X11') + # Documentation autowaf.build_dox(bld, 'SUIL', SUIL_VERSION, top, out) |