preparation for next things, TLD, locking, errors...

This commit is contained in:
Christian Thaeter 2007-07-15 16:56:21 +02:00
parent a06edceb2c
commit b083e8918c
2 changed files with 78 additions and 8 deletions

View file

@ -5,16 +5,42 @@
#include "plugin.h" #include "plugin.h"
/* TODO should be set by the build system to the actual plugin path */
#define CINELERRA_PLUGIN_PATH "~/.cinelerra3/plugins:/usr/local/lib/cinelerra3/plugins"
/* recognized extensions */
#define CINELERRA_PLUGIN_EXT "plugin:so"
/*
For future:
#define CINELERRA_PLUGIN_EXT "plugin:so:cplugin:c"
imagine using C source plugins compiled with libtcc on the fly
*/
NOBUG_DEFINE_FLAG (cinelerra_plugin); NOBUG_DEFINE_FLAG (cinelerra_plugin);
/* errors */
const char* CINELERRA_PLUGIN_SUCCESS = NULL;
const char* CINELERRA_PLUGIN_EALLOC = "Memory allocation failure";
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";
struct cinelerra_plugin struct cinelerra_plugin
{ {
const char* name; /*TODO store full and short name, sort by shortname?*/ /* short name as queried ("effects/audio/normalize") used for sorting/finding */
const char* name;
/* long names as looked up ("/usr/local/lib/cinelerra3/plugins/effects/audio/normalize.so") */
const char* pathname;
/* pointer to the extension part of 'pathname' */
const char* ext;
/* use count for all interfaces of this plugin */ /* use count for all interfaces of this plugin */
unsigned use_count; unsigned use_count;
/* time when the last open or close action happened */
time_t last; time_t last;
/* dlopen handle */ /* dlopen handle */
@ -24,28 +50,62 @@ struct cinelerra_plugin
/* global plugin registry */ /* global plugin registry */
void* cinelerra_plugin_registry = NULL; 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 static int
cmp_plugin_name (const void* a, const void* b) cinelerra_plugin_name_cmp (const void* a, const void* b)
{ {
return strcmp (((struct cinelerra_plugin*) a)->name, ((struct cinelerra_plugin*) b)->name); return strcmp (((struct cinelerra_plugin*) a)->name, ((struct cinelerra_plugin*) b)->name);
} }
const char*
cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* name, const char* path, const char* ext)
{
/*for each in path*/
/*for each extension*/
/*try to find name*/
}
struct cinelerra_interface* struct cinelerra_interface*
cinelerra_interface_open (const char* name, const char* interface, size_t min_revision) cinelerra_interface_open (const char* name, const char* interface, size_t min_revision)
{ {
REQUIRE (min_revision > sizeof(cinelerra_interface), "try to use an empty interface eh?"); REQUIRE (min_revision > sizeof(cinelerra_interface), "try to use an empty interface eh?");
REQUIRE (interface, "interface name must be defined"); REQUIRE (interface, "interface name must be given");
pthread_mutex_lock (&cinelerra_plugin_mutex);
pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init);
struct cinelerra_plugin plugin; struct cinelerra_plugin plugin;
struct cinelerra_plugin** found; struct cinelerra_plugin** found;
// TODO cook somewhere (pluginpath+name+.so) // if (name) (NULL means main app)
/*lookup for $CINELERRA_PLUGIN_PATH*/
/* else lookup for -DCINELERRA_PLUGIN_PATH */
#ifdef CINELERRA_PLUGIN_PATH
#endif
/* else fail */
plugin.name = name; plugin.name = name;
found = tsearch (&plugin, &cinelerra_plugin_registry, cmp_plugin_name); found = tsearch (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
if (!found) if (!found)
return NULL; goto ealloc0;
if (*found == &plugin) if (*found == &plugin)
{ {
@ -107,6 +167,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
(*found)->use_count++; (*found)->use_count++;
ret->use_count++; ret->use_count++;
pthread_mutex_unlock (&cinelerra_plugin_mutex);
return ret; return ret;
/* Error cleanup */ /* Error cleanup */
@ -121,7 +182,9 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
free (*found); free (*found);
ealloc1: ealloc1:
*found = &plugin; *found = &plugin;
tdelete (&plugin, &cinelerra_plugin_registry, cmp_plugin_name); tdelete (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
ealloc0:
pthread_mutex_lock (&cinelerra_plugin_mutex);
return NULL; return NULL;
} }
@ -131,6 +194,8 @@ cinelerra_interface_close (struct cinelerra_interface* self)
if(!self) if(!self)
return; return;
pthread_mutex_lock (&cinelerra_plugin_mutex);
struct cinelerra_plugin* plugin = self->plugin; struct cinelerra_plugin* plugin = self->plugin;
plugin->use_count--; plugin->use_count--;
@ -151,9 +216,10 @@ cinelerra_interface_close (struct cinelerra_interface* self)
destroy(); destroy();
/* and now cleanup */ /* and now cleanup */
tdelete (plugin, &cinelerra_plugin_registry, cmp_plugin_name); tdelete (plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
free ((char*)plugin->name); free ((char*)plugin->name);
dlclose(plugin->handle); dlclose(plugin->handle);
free (plugin); free (plugin);
} }
pthread_mutex_unlock (&cinelerra_plugin_mutex);
} }

View file

@ -119,6 +119,10 @@ cinelerra_plugin_expire (time_t age);
const char* const char*
cinelerra_plugin_error (); cinelerra_plugin_error ();
/// success, NULL
extern const char* CINELERRA_PLUGIN_SUCCESS;
/// memory allocation error
extern const char* CINELERRA_PLUGIN_EALLOC;
/// Plugin not found /// Plugin not found
extern const char* CINELERRA_PLUGIN_ENFOUND; extern const char* CINELERRA_PLUGIN_ENFOUND;
/// no such interface /// no such interface