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"
/* 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);
/* 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
{
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 */
unsigned use_count;
/* time when the last open or close action happened */
time_t last;
/* dlopen handle */
@ -24,28 +50,62 @@ struct cinelerra_plugin
/* global plugin registry */
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
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);
}
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*
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 (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** 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;
found = tsearch (&plugin, &cinelerra_plugin_registry, cmp_plugin_name);
found = tsearch (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
if (!found)
return NULL;
goto ealloc0;
if (*found == &plugin)
{
@ -107,6 +167,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
(*found)->use_count++;
ret->use_count++;
pthread_mutex_unlock (&cinelerra_plugin_mutex);
return ret;
/* Error cleanup */
@ -121,7 +182,9 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
free (*found);
ealloc1:
*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;
}
@ -131,6 +194,8 @@ cinelerra_interface_close (struct cinelerra_interface* self)
if(!self)
return;
pthread_mutex_lock (&cinelerra_plugin_mutex);
struct cinelerra_plugin* plugin = self->plugin;
plugin->use_count--;
@ -151,9 +216,10 @@ cinelerra_interface_close (struct cinelerra_interface* self)
destroy();
/* and now cleanup */
tdelete (plugin, &cinelerra_plugin_registry, cmp_plugin_name);
tdelete (plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
free ((char*)plugin->name);
dlclose(plugin->handle);
free (plugin);
}
pthread_mutex_unlock (&cinelerra_plugin_mutex);
}

View file

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