diff --git a/configure.ac b/configure.ac index 5b2512122..1730b3bdc 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,8 @@ AC_COPYRIGHT([ AC_PROG_CC AC_PROG_CPP AC_PROG_CXX + +AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL # diff --git a/src/lib/plugin.c b/src/lib/plugin.c index ec7b3f0a6..6e18ab3a8 100644 --- a/src/lib/plugin.c +++ b/src/lib/plugin.c @@ -28,26 +28,18 @@ #include "plugin.h" -/* - TODO cinelerra_xmalloc which aborts on allocation error - or cinelerra_die() function - -TODO move CINELERRA_DIE elsewhere (cinlib.h?) -*/ -#define CINELERRA_DIE do{NOBUG_LOG(NOBUG_ON, LOG_EMERG, "aborting due fatal error"); abort();}while(0) - /* TODO should be set by the build system to the actual plugin path */ #define CINELERRA_PLUGIN_PATH "~/.cinelerra3/plugins:/usr/local/lib/cinelerra3/plugins" +#define CINELERRA_PLUGIN_PREFIX "lib" NOBUG_DEFINE_FLAG (cinelerra_plugin); /* errors */ -const char* CINELERRA_PLUGIN_SUCCESS = NULL; -const char* CINELERRA_PLUGIN_EDLOPEN = "Could not open plugin"; -const char* CINELERRA_PLUGIN_EHOOK = "Hook function failed"; -const char* CINELERRA_PLUGIN_ENFOUND = "No such plugin"; -const char* CINELERRA_PLUGIN_ENIFACE = "No such interface"; -const char* CINELERRA_PLUGIN_EREVISION = "Interface revision too old"; +CINELERRA_ERROR_DEFINE(PLUGIN_DLOPEN, "Could not open plugin"); +CINELERRA_ERROR_DEFINE(PLUGIN_HOOK, "Hook function failed"); +CINELERRA_ERROR_DEFINE(PLUGIN_NFILE, "No such plugin"); +CINELERRA_ERROR_DEFINE(PLUGIN_NIFACE, "No such interface"); +CINELERRA_ERROR_DEFINE(PLUGIN_REVISION, "Interface revision too old"); /* supported (planned) plugin types and their file extensions @@ -68,6 +60,7 @@ static const struct { {"plugin", CINELERRA_PLUGIN_DYNLIB}, {"so", CINELERRA_PLUGIN_DYNLIB}, + {"o", CINELERRA_PLUGIN_DYNLIB}, {"tcc", CINELERRA_PLUGIN_CSOURCE}, {"c", CINELERRA_PLUGIN_CSOURCE}, /* extend here */ @@ -103,16 +96,6 @@ void* cinelerra_plugin_registry = NULL; /* plugin operations are protected by one big mutex */ pthread_mutex_t cinelerra_plugin_mutex = PTHREAD_MUTEX_INITIALIZER; -/* Thread local storage, for now only the error state */ -static pthread_key_t cinelerra_plugin_tls_error; -static pthread_once_t cinelerra_plugin_initialized = PTHREAD_ONCE_INIT; - -void -cinelerra_plugin_tls_init (void) -{ - pthread_key_create (&cinelerra_plugin_tls_error, NULL); -} - /* the compare function for the registry tree */ static int cinelerra_plugin_name_cmp (const void* a, const void* b) @@ -121,22 +104,6 @@ cinelerra_plugin_name_cmp (const void* a, const void* b) } -const char* -cinelerra_plugin_error () -{ - pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init); - - const char* err = pthread_getspecific (cinelerra_plugin_tls_error); - pthread_setspecific (cinelerra_plugin_tls_error, CINELERRA_PLUGIN_SUCCESS); - return err; -} - -static void -cinelerra_plugin_error_set (const char* err) -{ - pthread_setspecific (cinelerra_plugin_tls_error, err); -} - int cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path) { @@ -160,7 +127,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path) for (int i = 0; cinelerra_plugin_extensions[i].ext; ++i) { /* path/name.extension */ - int r = snprintf(pathname, 1024, "%s/%s.%s", tok, self->name, cinelerra_plugin_extensions[i].ext); + int r = snprintf(pathname, 1024, CINELERRA_PLUGIN_PREFIX "%s/%s.%s", tok, self->name, cinelerra_plugin_extensions[i].ext); if (r >= 1024) return -1; /*TODO error handling, name too long*/ @@ -170,7 +137,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path) { /* got it */ self->pathname = strdup (pathname); - if (!self->pathname) CINELERRA_DIE; + if (!self->pathname) CINELERRA_DIE("out of memory"); self->type = cinelerra_plugin_extensions[i].type; return 0; } @@ -185,8 +152,6 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re //REQUIRE (min_revision > sizeof(struct cinelerra_interface), "try to use an empty interface eh?"); REQUIRE (interface, "interface name must be given"); - pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init); - pthread_mutex_lock (&cinelerra_plugin_mutex); struct cinelerra_plugin plugin; @@ -195,7 +160,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re plugin.name = name; /* for searching */ found = tsearch (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp); - if (!found) CINELERRA_DIE; + if (!found) CINELERRA_DIE("out of memory"); if (*found == &plugin) { @@ -203,13 +168,13 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re /* now really create new item */ *found = malloc (sizeof (struct cinelerra_plugin)); - if (!*found) CINELERRA_DIE; + if (!*found) CINELERRA_DIE("out of memory"); if (name) /* NULL is main app, no lookup needed */ { /*lookup for $CINELERRA_PLUGIN_PATH*/ (*found)->name = strdup (name); - if (!(*found)->name) CINELERRA_DIE; + if (!(*found)->name) CINELERRA_DIE("out of memory"); if (!cinelerra_plugin_lookup (*found, getenv("CINELERRA_PLUGIN_PATH")) #ifdef CINELERRA_PLUGIN_PATH @@ -218,7 +183,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re #endif ) { - cinelerra_plugin_error_set (CINELERRA_PLUGIN_ENFOUND); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_NFILE); goto elookup; } } @@ -237,7 +202,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re if (!(*found)->handle) { ERROR (cinelerra_plugin, "dlopen failed: %s", dlerror()); - cinelerra_plugin_error_set (CINELERRA_PLUGIN_EDLOPEN); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_DLOPEN); goto edlopen; } @@ -246,7 +211,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re if (init && init()) { ERROR (cinelerra_plugin, "cinelerra_plugin_init failed: %s: %s", name, interface); - cinelerra_plugin_error_set (CINELERRA_PLUGIN_EHOOK); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_HOOK); goto einit; } } @@ -258,7 +223,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re if (!ret) { ERROR (cinelerra_plugin, "plugin %s doesnt provide interface %s", name, interface); - cinelerra_plugin_error_set (CINELERRA_PLUGIN_ENIFACE); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_NIFACE); goto edlsym; } @@ -266,7 +231,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re if (ret->size < min_revision) { ERROR (cinelerra_plugin, "plugin %s provides older interface %s revision than required", name, interface); - cinelerra_plugin_error_set (CINELERRA_PLUGIN_EREVISION); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_REVISION); goto erevision; } @@ -276,7 +241,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re if (ret->open && ret->open()) { ERROR (cinelerra_plugin, "open hook indicated an error"); - cinelerra_plugin_error_set (CINELERRA_PLUGIN_EHOOK); + cinelerra_error_set (CINELERRA_ERROR_PLUGIN_HOOK); goto eopen; } diff --git a/src/lib/plugin.h b/src/lib/plugin.h index 74ab964b3..65618b61d 100644 --- a/src/lib/plugin.h +++ b/src/lib/plugin.h @@ -30,6 +30,8 @@ extern "C" { #include #include +#include "error.h" + NOBUG_DECLARE_FLAG (cinelerra_plugin); /* tool macros*/ @@ -129,30 +131,11 @@ cinelerra_plugin_unload (const char* plugin); void cinelerra_plugin_expire (time_t age); -/** - * Query and reset the error state. - * report last error, reset error state. Errors are thread local. - * Error strings are guaranteed to point to a C string with a unique comparable address. - * Note that the error state gets cleared by calling this function. The application may store it temporary for further handling. - * @return pointer to one of the error C-strings, NULL when no error happened. - */ -const char* -cinelerra_plugin_error (); - -/// success, NULL -extern const char* CINELERRA_PLUGIN_SUCCESS; -/// memory allocation error -extern const char* CINELERRA_PLUGIN_EALLOC; -/// dlopen failed -extern const char* CINELERRA_PLUGIN_EDLOPEN; -/// dlopen failed -extern const char* CINELERRA_PLUGIN_EHOOK; -/// Plugin not found -extern const char* CINELERRA_PLUGIN_ENFOUND; -/// no such interface -extern const char* CINELERRA_PLUGIN_ENIFACE; -/// revision not sufficient -extern const char* CINELERRA_PLUGIN_EREVISION; +CINELERRA_ERROR_DECLARE(PLUGIN_DLOPEN); +CINELERRA_ERROR_DECLARE(PLUGIN_HOOK); +CINELERRA_ERROR_DECLARE(PLUGIN_NFILE); +CINELERRA_ERROR_DECLARE(PLUGIN_NIFACE); +CINELERRA_ERROR_DECLARE(PLUGIN_REVISION); #ifdef __cplusplus } /* extern "C" */ diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 5ca03150a..c549e82fd 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -18,13 +18,14 @@ examples_srcdir = $(top_srcdir)/tests/examples noinst_PROGRAMS += plugin_example -plugin_example_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror -plugin_example_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ +plugin_example_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Werror +plugin_example_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ plugin_example_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl plugin_example_SOURCES = $(examples_srcdir)/plugin_main.c noinst_HEADERS += $(examples_srcdir)/hello_interface.h -#noinst_LTLIBRARIES += example_plugin.la -#example_plugin_la_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ -#example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c +check_LTLIBRARIES = example_plugin.la +example_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ +example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c +example_plugin_la_LDFLAGS = -module diff --git a/tests/examples/plugin_main.c b/tests/examples/plugin_main.c index 427f88655..d48838900 100644 --- a/tests/examples/plugin_main.c +++ b/tests/examples/plugin_main.c @@ -7,6 +7,7 @@ int main(int argc, char** argv) { + NOBUG_INIT; /* we have a plugin 'hello_1' which provides us 2 hello interfaces, one for english and one for german output, open both try them, close them.