preparation for next things, TLD, locking, errors...
This commit is contained in:
parent
a06edceb2c
commit
b083e8918c
2 changed files with 78 additions and 8 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue