summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine.h.in4
-rw-r--r--src/dxr3/dxr3_mpeg_encoders.c4
-rw-r--r--src/xine-engine/input_cache.c4
-rw-r--r--src/xine-engine/input_rip.c4
-rw-r--r--src/xine-engine/load_plugins.c773
-rw-r--r--src/xine-engine/plugin_catalog.h16
-rw-r--r--src/xine-engine/xine.c11
-rw-r--r--src/xine-engine/xine_internal.h4
8 files changed, 528 insertions, 292 deletions
diff --git a/include/xine.h.in b/include/xine.h.in
index 098ab59a6..44a6b6969 100644
--- a/include/xine.h.in
+++ b/include/xine.h.in
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.h.in,v 1.138 2005/02/02 23:11:40 dsalt Exp $
+ * $Id: xine.h.in,v 1.139 2005/02/09 20:03:18 tmattern Exp $
*
* public xine-lib (libxine) interface and documentation
*
@@ -1027,6 +1027,8 @@ const char *const *xine_list_spu_plugins(xine_t *self);
const char *const *xine_list_audio_decoder_plugins(xine_t *self);
const char *const *xine_list_video_decoder_plugins(xine_t *self);
+/* unload unused plugins */
+void xine_plugins_garbage_collector(xine_t *self);
/*********************************************************************
* visual specific gui <-> xine engine communication *
diff --git a/src/dxr3/dxr3_mpeg_encoders.c b/src/dxr3/dxr3_mpeg_encoders.c
index 87328ac33..85089567f 100644
--- a/src/dxr3/dxr3_mpeg_encoders.c
+++ b/src/dxr3/dxr3_mpeg_encoders.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_mpeg_encoders.c,v 1.22 2004/12/16 13:31:40 mroi Exp $
+ * $Id: dxr3_mpeg_encoders.c,v 1.23 2005/02/09 20:03:22 tmattern Exp $
*/
/* mpeg encoders for the dxr3 video out plugin.
@@ -547,7 +547,7 @@ int dxr3_lavc_init(dxr3_driver_t *drv, plugin_node_t *node)
int (*init)(dxr3_driver_t *);
int result;
- ffmpeg = dlopen(node->filename, RTLD_LAZY);
+ ffmpeg = dlopen(node->file->filename, RTLD_LAZY);
if (!ffmpeg) return 0;
init = dlsym(ffmpeg, "dxr3_encoder_init");
diff --git a/src/xine-engine/input_cache.c b/src/xine-engine/input_cache.c
index 9fd1abe39..4a3e309c3 100644
--- a/src/xine-engine/input_cache.c
+++ b/src/xine-engine/input_cache.c
@@ -22,7 +22,7 @@
* The goal of this input plugin is to reduce
* the number of calls to the real input plugin.
*
- * $Id: input_cache.c,v 1.5 2004/12/13 18:19:48 miguelfreitas Exp $
+ * $Id: input_cache.c,v 1.6 2005/02/09 20:03:19 tmattern Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -306,7 +306,7 @@ static void cache_plugin_dispose(input_plugin_t *this_gen) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
LOG_MODULE": seek_calls: %d, main input seek calls: %d\n", this->seek_call, this->main_seek_call);
- this->main_input_plugin->dispose(this->main_input_plugin);
+ _x_free_input_plugin(this->stream, this->main_input_plugin);
free(this);
}
diff --git a/src/xine-engine/input_rip.c b/src/xine-engine/input_rip.c
index 510861d7b..6837eb5cf 100644
--- a/src/xine-engine/input_rip.c
+++ b/src/xine-engine/input_rip.c
@@ -29,7 +29,7 @@
* - it's possible speeder saving streams in the xine without playing:
* xine stream_mrl#save:file.raw\;noaudio\;novideo
*
- * $Id: input_rip.c,v 1.28 2005/02/03 07:19:07 valtri Exp $
+ * $Id: input_rip.c,v 1.29 2005/02/09 20:03:20 tmattern Exp $
*/
/* TODO:
@@ -490,7 +490,7 @@ static void rip_plugin_dispose(input_plugin_t *this_gen) {
lprintf("rip_plugin_dispose\n");
- this->main_input_plugin->dispose(this->main_input_plugin);
+ _x_free_input_plugin(this->stream, this->main_input_plugin);
fclose(this->file);
if (this->preview) free(this->preview);
free(this);
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index 5dc3631a2..61195980e 100644
--- a/src/xine-engine/load_plugins.c
+++ b/src/xine-engine/load_plugins.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: load_plugins.c,v 1.194 2005/02/02 23:11:40 dsalt Exp $
+ * $Id: load_plugins.c,v 1.195 2005/02/09 20:03:20 tmattern Exp $
*
*
* Load input/demux/audio_out/video_out/codec plugins
@@ -104,6 +104,30 @@ static void _build_list_typed_plugins(plugin_catalog_t **catalog, xine_list_t *t
(*catalog)->ids[i] = NULL;
}
+static void inc_file_ref(plugin_file_t *file) {
+ _x_assert(file);
+ file->ref++;
+}
+
+static void dec_file_ref(plugin_file_t *file) {
+ _x_assert(file);
+
+ file->ref--;
+ lprintf("file %s referenced %d time(s)\n", file->filename, file->ref);
+}
+
+static void inc_node_ref(plugin_node_t *node) {
+ _x_assert(node);
+ node->ref++;
+}
+
+static void dec_node_ref(plugin_node_t *node) {
+ _x_assert(node);
+
+ node->ref--;
+ lprintf("node %s referenced %d time(s)\n", node->info->id, node->ref);
+}
+
/*
* plugin list/catalog management functions
*
@@ -238,7 +262,7 @@ static void map_decoders (xine_t *this) {
/* find the right place based on the priority */
for (pos = 0; pos < PLUGINS_PER_TYPE; pos++)
if (!catalog->spu_decoder_map[streamtype][pos] ||
- priority > get_decoder_priority(this, catalog->spu_decoder_map[streamtype][pos]))
+ get_decoder_priority(this, catalog->spu_decoder_map[streamtype][pos]) <= priority)
break;
/* shift the decoder list for this type by one to make room for new decoder */
@@ -271,10 +295,10 @@ static plugin_info_t *_get_cached_plugin ( xine_list_t *list,
node = xine_list_first_content (list);
while (node) {
- if( !strcmp( node->filename, filename ) &&
- node->filesize == statbuffer->st_size &&
- node->filemtime == statbuffer->st_mtime &&
- !previous_info ) {
+ if( !previous_info &&
+ node->file->filesize == statbuffer->st_size &&
+ node->file->filemtime == statbuffer->st_mtime &&
+ !strcmp( node->file->filename, filename )) {
return node->info;
}
@@ -289,11 +313,31 @@ static plugin_info_t *_get_cached_plugin ( xine_list_t *list,
}
-static void _insert_plugin (xine_t *this,
- xine_list_t *list,
- char *filename, struct stat *statbuffer,
- plugin_info_t *info,
- int api_version){
+static plugin_file_t *_insert_file (xine_t *this,
+ xine_list_t *list,
+ char *filename, struct stat *statbuffer,
+ void *lib) {
+ plugin_file_t *entry;
+
+ /* create the file entry */
+ entry = malloc(sizeof(plugin_file_t));
+ entry->filename = strdup(filename);
+ entry->filesize = statbuffer->st_size;
+ entry->filemtime = statbuffer->st_mtime;
+ entry->lib_handle = lib;
+ entry->ref = 0;
+ entry->no_unload = 0;
+
+ xine_list_append_content (list, entry);
+ return entry;
+}
+
+
+static void _insert_node (xine_t *this,
+ xine_list_t *list,
+ plugin_file_t *file,
+ plugin_info_t *info,
+ int api_version){
plugin_catalog_t *catalog = this->plugin_catalog;
plugin_node_t *entry;
@@ -309,6 +353,10 @@ static void _insert_plugin (xine_t *this,
char desc[100];
int i;
+ _x_assert(this);
+ _x_assert(list);
+ _x_assert(file);
+ _x_assert(info);
if (info->API != api_version) {
xprintf(this, XINE_VERBOSITY_LOG,
_("load_plugins: ignoring plugin %s, wrong iface version %d (should be %d)\n"),
@@ -317,14 +365,12 @@ static void _insert_plugin (xine_t *this,
}
entry = xine_xmalloc(sizeof(plugin_node_t));
- entry->filename = strdup(filename);
- entry->filesize = statbuffer->st_size;
- entry->filemtime = statbuffer->st_mtime;
entry->info = xine_xmalloc(sizeof(plugin_info_t));
*(entry->info) = *info;
entry->info->id = strdup(info->id);
entry->info->init = NULL;
entry->plugin_class = NULL;
+ entry->file = file;
entry->ref = 0;
switch (info->type & PLUGIN_TYPE_MASK){
@@ -351,7 +397,8 @@ static void _insert_plugin (xine_t *this,
decoder_new = xine_xmalloc(sizeof(decoder_info_t));
if (decoder_old == NULL) {
xprintf (this, XINE_VERBOSITY_DEBUG,
- "load_plugins: plugin %s from %s is broken: special_info = NULL\n", info->id, entry->filename);
+ "load_plugins: plugin %s from %s is broken: special_info = NULL\n",
+ info->id, entry->file->filename);
_x_abort();
}
for (i=0; decoder_old->supported_types[i] != 0; ++i);
@@ -428,6 +475,10 @@ static void _insert_plugin (xine_t *this,
break;
}
+ if (info->type & PLUGIN_NO_UNLOAD) {
+ entry->file->no_unload = 1;
+ }
+
xine_list_append_priority_content (list, entry, priority);
}
@@ -447,6 +498,7 @@ static plugin_catalog_t *_new_catalog(void){
catalog->post = xine_list_new();
catalog->cache = xine_list_new();
+ catalog->file = xine_list_new();
pthread_mutex_init (&catalog->lock, NULL);
return catalog;
@@ -467,16 +519,30 @@ static void collect_plugins(xine_t *this, char *path){
if (dir) {
int plugin_count = 0, decoder_count = 0;
struct dirent *pEntry;
+ int path_len;
+ char *str = NULL;
+
+ path_len = strlen(path);
+ str = malloc(path_len * 2 + 2); /* +2 for '/' and '\0' */
+ xine_fast_memcpy(str, path, path_len);
+ str[path_len] = '/';
+ str[path_len + 1] = '\0';
while ((pEntry = readdir (dir)) != NULL) {
- char *str;
+ size_t str_size = 0;
+ size_t new_str_size;
void *lib;
plugin_info_t *info;
struct stat statbuffer;
- str = xine_xmalloc(strlen(path) + strlen(pEntry->d_name) + 2);
- sprintf (str, "%s/%s", path, pEntry->d_name);
+ new_str_size = path_len + pEntry->d_reclen + 2;
+ if (str_size < new_str_size) {
+ str_size = new_str_size + new_str_size / 2;
+ str = realloc(str, str_size);
+ }
+
+ xine_fast_memcpy(&str[path_len + 1], pEntry->d_name, pEntry->d_reclen + 1);
if (stat(str, &statbuffer)) {
xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: unable to stat %s\n"), str);
@@ -507,6 +573,8 @@ static void collect_plugins(xine_t *this, char *path){
plugin_name = str;
lib = NULL;
+
+ /* get the first plugin_info_t */
info = _get_cached_plugin ( this->plugin_catalog->cache,
str, &statbuffer, NULL);
#ifdef LOG
@@ -523,10 +591,12 @@ static void collect_plugins(xine_t *this, char *path){
_("load_plugins: cannot open plugin lib %s:\n%s\n"), str, error);
} else {
- int do_not_unload = 0;
if (info || (info = dlsym(lib, "xine_plugin_info"))) {
+ plugin_file_t *file;
+ file = _insert_file(this, this->plugin_catalog->file, str, &statbuffer, lib);
+
while ( info && info->type != PLUGIN_NONE ){
xine_log (this, XINE_LOG_PLUGIN,
@@ -540,47 +610,39 @@ static void collect_plugins(xine_t *this, char *path){
} else {
switch (info->type & PLUGIN_TYPE_MASK){
case PLUGIN_INPUT:
- _insert_plugin (this, this->plugin_catalog->input, str,
- &statbuffer, info,
- INPUT_PLUGIN_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->input, file, info,
+ INPUT_PLUGIN_IFACE_VERSION);
break;
case PLUGIN_DEMUX:
- _insert_plugin (this, this->plugin_catalog->demux, str,
- &statbuffer, info,
- DEMUXER_PLUGIN_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->demux, file, info,
+ DEMUXER_PLUGIN_IFACE_VERSION);
break;
case PLUGIN_AUDIO_DECODER:
- _insert_plugin (this, this->plugin_catalog->audio, str,
- &statbuffer, info,
- AUDIO_DECODER_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->audio, file, info,
+ AUDIO_DECODER_IFACE_VERSION);
decoder_count++;
break;
case PLUGIN_VIDEO_DECODER:
- _insert_plugin (this, this->plugin_catalog->video, str,
- &statbuffer, info,
- VIDEO_DECODER_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->video, file, info,
+ VIDEO_DECODER_IFACE_VERSION);
decoder_count++;
break;
case PLUGIN_SPU_DECODER:
- _insert_plugin (this, this->plugin_catalog->spu, str,
- &statbuffer, info,
- SPU_DECODER_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->spu, file, info,
+ SPU_DECODER_IFACE_VERSION);
decoder_count++;
break;
case PLUGIN_AUDIO_OUT:
- _insert_plugin (this, this->plugin_catalog->aout, str,
- &statbuffer, info,
- AUDIO_OUT_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->aout, file, info,
+ AUDIO_OUT_IFACE_VERSION);
break;
case PLUGIN_VIDEO_OUT:
- _insert_plugin (this, this->plugin_catalog->vout, str,
- &statbuffer, info,
- VIDEO_OUT_DRIVER_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->vout, file, info,
+ VIDEO_OUT_DRIVER_IFACE_VERSION);
break;
case PLUGIN_POST:
- _insert_plugin (this, this->plugin_catalog->post, str,
- &statbuffer, info,
- POST_PLUGIN_IFACE_VERSION);
+ _insert_node (this, this->plugin_catalog->post, file, info,
+ POST_PLUGIN_IFACE_VERSION);
break;
default:
xine_log (this, XINE_LOG_PLUGIN,
@@ -592,10 +654,8 @@ static void collect_plugins(xine_t *this, char *path){
/* get next info either from lib or cache */
if( lib ) {
- do_not_unload = (do_not_unload || (info->type & PLUGIN_NO_UNLOAD));
info++;
- }
- else {
+ } else {
info = _get_cached_plugin ( this->plugin_catalog->cache,
str, &statbuffer, info);
}
@@ -607,8 +667,6 @@ static void collect_plugins(xine_t *this, char *path){
xine_log (this, XINE_LOG_PLUGIN,
_("load_plugins: can't get plugin info from %s:\n%s\n"), str, error);
}
- if( lib && !do_not_unload )
- dlclose(lib);
}
break;
case S_IFDIR:
@@ -619,8 +677,8 @@ static void collect_plugins(xine_t *this, char *path){
}
} /* switch */
} /* if (stat(...)) */
- free(str);
} /* while */
+ free(str);
closedir (dir);
} /* if (dir) */
else {
@@ -634,42 +692,92 @@ static void collect_plugins(xine_t *this, char *path){
* generic 2nd stage plugin loader
*/
-static void *_load_plugin_class(xine_t *this,
- char *filename, plugin_info_t *target,
- void *data) {
+static int _load_plugin_class(xine_t *this,
+ plugin_node_t *node,
+ void *data) {
+ char *filename = node->file->filename;
+ plugin_info_t *target = node->info;
void *lib;
+ plugin_info_t *info;
- if((lib = dlopen (filename, RTLD_LAZY | RTLD_GLOBAL)) == NULL) {
- const char *error = dlerror();
- xine_log (this, XINE_LOG_PLUGIN,
- _("load_plugins: cannot (stage 2) open plugin lib %s:\n%s\n"), filename, error);
+ /* load the dynamic library if needed */
+ if (!node->file->lib_handle) {
+ lprintf("dlopen %s\n", filename);
+ if ((lib = dlopen (filename, RTLD_LAZY | RTLD_GLOBAL)) == NULL) {
+ const char *error = dlerror();
+ xine_log (this, XINE_LOG_PLUGIN,
+ _("load_plugins: cannot (stage 2) open plugin lib %s:\n%s\n"), filename, error);
+ return 0;
+ } else {
+ node->file->lib_handle = lib;
+ }
} else {
+ lprintf("%s already loaded\n", filename);
+ }
- plugin_info_t *info;
+ if ((info = dlsym(node->file->lib_handle, "xine_plugin_info"))) {
+ /* TODO: use sigsegv handler */
+ while (info->type != PLUGIN_NONE){
+ if (info->type == target->type
+ && info->API == target->API
+ && !strcasecmp(info->id, target->id)
+ && info->version == target->version){
+ inc_file_ref(node->file);
+ node->plugin_class = info->init(this, data);
+ return 1;
+ }
+ info++;
+ }
+ lprintf("plugin not found\n");
+
+ } else {
+ xine_log (this, XINE_LOG_PLUGIN,
+ _("load_plugins: Yikes! %s doesn't contain plugin info.\n"), filename);
+ }
+
+ return 0; /* something failed if we came here... */
+}
- if ((info = dlsym(lib, "xine_plugin_info"))) {
- /* TODO: use sigsegv handler */
- while (info->type != PLUGIN_NONE){
- if (info->type == target->type
- && info->API == target->API
- && !strcasecmp(info->id, target->id)
- && info->version == target->version){
+static void _dispose_plugin_class(plugin_node_t *node) {
- return info->init(this, data);
- }
- info++;
- }
+ _x_assert(node);
+ if (node->plugin_class) {
+ void *cls = node->plugin_class;
- } else {
- xine_log (this, XINE_LOG_PLUGIN,
- _("load_plugins: Yikes! %s doesn't contain plugin info.\n"), filename);
+ _x_assert(node->info);
+ /* dispose of plugin class */
+ switch (node->info->type & PLUGIN_TYPE_MASK) {
+ case PLUGIN_INPUT:
+ ((input_class_t *)cls)->dispose ((input_class_t *)cls);
+ break;
+ case PLUGIN_DEMUX:
+ ((demux_class_t *)cls)->dispose ((demux_class_t *)cls);
+ break;
+ case PLUGIN_SPU_DECODER:
+ ((spu_decoder_class_t *)cls)->dispose ((spu_decoder_class_t *)cls);
+ break;
+ case PLUGIN_AUDIO_DECODER:
+ ((audio_decoder_class_t *)cls)->dispose ((audio_decoder_class_t *)cls);
+ break;
+ case PLUGIN_VIDEO_DECODER:
+ ((video_decoder_class_t *)cls)->dispose ((video_decoder_class_t *)cls);
+ break;
+ case PLUGIN_AUDIO_OUT:
+ ((audio_driver_class_t *)cls)->dispose ((audio_driver_class_t *)cls);
+ break;
+ case PLUGIN_VIDEO_OUT:
+ ((video_driver_class_t *)cls)->dispose ((video_driver_class_t *)cls);
+ break;
+ case PLUGIN_POST:
+ ((post_class_t *)cls)->dispose ((post_class_t *)cls);
+ break;
}
+ node->plugin_class = NULL;
+ dec_file_ref(node->file);
}
-
- return NULL; /* something failed if we came here... */
}
/*
@@ -679,26 +787,16 @@ static void *_load_plugin_class(xine_t *this,
static void _load_required_plugins(xine_t *this, xine_list_t *list) {
plugin_node_t *node;
- int load;
node = xine_list_first_content (list);
while (node) {
- if( (node->info->type & PLUGIN_TYPE_MASK) == PLUGIN_INPUT ||
- (node->info->type & PLUGIN_TYPE_MASK) == PLUGIN_DEMUX ||
- (node->info->type & PLUGIN_MUST_PRELOAD) )
- load = 1;
- else
- load = 0;
-
- if( load && !node->plugin_class ) {
+ if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class ) {
- lprintf("preload plugin %s from %s\n", node->info->id, node->filename);
+ lprintf("preload plugin %s from %s\n", node->info->id, node->file->filename);
- node->plugin_class = _load_plugin_class (this, node->filename, node->info, NULL);
-
- /* in case of failure remove from list */
- if( !node->plugin_class ) {
+ if (! _load_plugin_class (this, node, NULL)) {
+ /* in case of failure remove from list */
xine_list_delete_current (list);
node = list->cur ? list->cur->content : NULL;
@@ -730,6 +828,7 @@ static void load_required_plugins(xine_t *this) {
static void save_plugin_list(FILE *fp, xine_list_t *plugins) {
plugin_node_t *node;
+ plugin_file_t *file;
decoder_info_t *decoder_info;
vo_info_t *vo_info;
ao_info_t *ao_info;
@@ -740,9 +839,10 @@ static void save_plugin_list(FILE *fp, xine_list_t *plugins) {
node = xine_list_first_content (plugins);
while (node) {
- fprintf(fp, "[%s]\n", node->filename );
- fprintf(fp, "size=%llu\n", (uint64_t) node->filesize );
- fprintf(fp, "mtime=%llu\n", (uint64_t) node->filemtime );
+ file = node->file;
+ fprintf(fp, "[%s]\n", file->filename );
+ fprintf(fp, "size=%llu\n", (uint64_t) file->filesize );
+ fprintf(fp, "mtime=%llu\n", (uint64_t) file->filemtime );
fprintf(fp, "type=%d\n", node->info->type );
fprintf(fp, "api=%d\n", node->info->API );
fprintf(fp, "id=%s\n", node->info->id );
@@ -790,6 +890,7 @@ static void save_plugin_list(FILE *fp, xine_list_t *plugins) {
static void load_plugin_list(FILE *fp, xine_list_t *plugins) {
plugin_node_t *node;
+ plugin_file_t *file;
decoder_info_t *decoder_info = NULL;
vo_info_t *vo_info = NULL;
ao_info_t *ao_info = NULL;
@@ -802,6 +903,7 @@ static void load_plugin_list(FILE *fp, xine_list_t *plugins) {
int version_ok = 0;
node = NULL;
+ file = NULL;
while (fgets (line, 1023, fp)) {
if (line[0] == '#')
continue;
@@ -809,15 +911,20 @@ static void load_plugin_list(FILE *fp, xine_list_t *plugins) {
if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) )
*value = (char) 0; /* eliminate any cr/lf */
+ if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) )
+ *value = (char) 0; /* eliminate any cr/lf */
+
if (line[0] == '[' && version_ok) {
if((value = strchr (line, ']')))
*value = (char) 0;
-
+
if( node ) {
xine_list_append_content (plugins, node);
}
node = xine_xmalloc(sizeof(plugin_node_t));
- node->filename = strdup(line+1);
+ file = xine_xmalloc(sizeof(plugin_file_t));
+ node->file = file;
+ file->filename = strdup(line+1);
node->info = xine_xmalloc(2*sizeof(plugin_info_t));
node->info[1].type = PLUGIN_NONE;
decoder_info = NULL;
@@ -842,10 +949,10 @@ static void load_plugin_list(FILE *fp, xine_list_t *plugins) {
} else if (node) {
if( !strcmp("size",line) ) {
sscanf(value," %llu",&llu);
- node->filesize = (off_t) llu;
+ file->filesize = (off_t) llu;
} else if( !strcmp("mtime",line) ) {
sscanf(value," %llu",&llu);
- node->filemtime = (time_t) llu;
+ file->filemtime = (time_t) llu;
} else if( !strcmp("type",line) ) {
sscanf(value," %d",&i);
node->info->type = i;
@@ -1061,7 +1168,11 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) {
while (node) {
input_plugin_t *plugin;
+ if (!node->plugin_class && !_load_plugin_class(xine, node, NULL))
+ return NULL;
if ((plugin = ((input_class_t *)node->plugin_class)->get_instance(node->plugin_class, stream, mrl))) {
+ inc_node_ref(node);
+ plugin->node = node;
pthread_mutex_unlock (&catalog->lock);
return plugin;
}
@@ -1074,6 +1185,20 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) {
return NULL;
}
+
+void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) {
+ plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node = input->node;
+
+ input->dispose(input);
+ if (node) {
+ pthread_mutex_lock(&catalog->lock);
+ dec_node_ref(node);
+ pthread_mutex_unlock(&catalog->lock);
+ }
+}
+
+
static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2,
input_plugin_t *input) {
@@ -1106,7 +1231,12 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth
xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: probing demux '%s'\n", node->info->id);
+ if (!node->plugin_class && !_load_plugin_class(stream->xine, node, NULL))
+ return NULL;
+
if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) {
+ inc_node_ref(node);
+ plugin->node = node;
pthread_mutex_unlock (&catalog->lock);
return plugin;
}
@@ -1159,7 +1289,12 @@ demux_plugin_t *_x_find_demux_plugin_by_name(xine_stream_t *stream, const char *
while (node) {
if (strcasecmp(node->info->id, name) == 0) {
+ if (!node->plugin_class && !_load_plugin_class(stream->xine, node, NULL))
+ return NULL;
+
if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) {
+ inc_node_ref(node);
+ plugin->node = node;
pthread_mutex_unlock (&catalog->lock);
return plugin;
}
@@ -1213,12 +1348,14 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha
} else {
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugin: probing '%s' (method %d)...\n", node->info->id, stream->content_detection_method );
-
+ if (!node->plugin_class && !_load_plugin_class(xine, node, NULL))
+ return NULL;
+
if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) {
xprintf (stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: using demuxer '%s' (instead of '%s')\n", node->info->id, last_demux_name);
-
-
+ inc_node_ref(node);
+ plugin->node = node;
pthread_mutex_unlock (&catalog->lock);
return plugin;
}
@@ -1237,8 +1374,13 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha
stream->content_detection_method = METHOD_BY_CONTENT;
+ if (!last_demux->plugin_class && !_load_plugin_class(xine, last_demux, NULL))
+ return NULL;
+
if ((plugin = ((demux_class_t *)last_demux->plugin_class)->open_plugin(last_demux->plugin_class, stream, input))) {
xprintf (stream->xine, XINE_VERBOSITY_LOG, _("load_plugins: using demuxer '%s'\n"), last_demux_name);
+ inc_node_ref(last_demux);
+ plugin->node = last_demux;
return plugin;
}
@@ -1246,6 +1388,19 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha
}
+void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) {
+ plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node = demux->node;
+
+ demux->dispose(demux);
+ if (node) {
+ pthread_mutex_lock(&catalog->lock);
+ dec_node_ref(node);
+ pthread_mutex_unlock(&catalog->lock);
+ }
+}
+
+
const char *const *xine_get_autoplay_input_plugin_ids(xine_t *this) {
plugin_catalog_t *catalog;
@@ -1256,25 +1411,25 @@ const char *const *xine_get_autoplay_input_plugin_ids(xine_t *this) {
pthread_mutex_lock (&catalog->lock);
catalog->ids[0] = NULL;
-
- for (node = xine_list_first_content (catalog->input); node;
- node = xine_list_next_content (catalog->input)) {
+ node = xine_list_first_content (catalog->input);
+ while (node) {
input_class_t *ic;
- ic = (input_class_t *) node->plugin_class;
- if (ic->get_autoplay_list) {
- int i = 0, j;
+ if (node->plugin_class || _load_plugin_class(this, node, NULL)) {
+
+ ic = (input_class_t *) node->plugin_class;
+ if (ic->get_autoplay_list) {
+ int i = 0, j;
- while (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) < 0)
- i++;
- if (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) == 0)
- /* do not list plugins twice */
- continue;
- for (j = PLUGIN_MAX - 1; j > i; j--)
- catalog->ids[j] = catalog->ids[j - 1];
+ while (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) < 0)
+ i++;
+ for (j = PLUGIN_MAX - 1; j > i; j--)
+ catalog->ids[j] = catalog->ids[j - 1];
- catalog->ids[i] = node->info->id;
+ catalog->ids[i] = node->info->id;
+ }
}
+ node = xine_list_next_content (catalog->input);
}
pthread_mutex_unlock (&catalog->lock);
@@ -1293,25 +1448,25 @@ const char *const *xine_get_browsable_input_plugin_ids(xine_t *this) {
pthread_mutex_lock (&catalog->lock);
catalog->ids[0] = NULL;
-
- for (node = xine_list_first_content (catalog->input); node;
- node = xine_list_next_content (catalog->input)) {
+ node = xine_list_first_content (catalog->input);
+ while (node) {
input_class_t *ic;
+
+ if (node->plugin_class || _load_plugin_class(this, node, NULL)) {
- ic = (input_class_t *) node->plugin_class;
- if (ic->get_dir) {
- int i = 0, j;
+ ic = (input_class_t *) node->plugin_class;
+ if (ic->get_dir) {
+ int i = 0, j;
- while (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) < 0)
- i++;
- if (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) == 0)
- /* do not list plugins twice */
- continue;
- for (j = PLUGIN_MAX - 1; j > i; j--)
- catalog->ids[j] = catalog->ids[j - 1];
+ while (catalog->ids[i] && strcmp(catalog->ids[i], node->info->id) < 0)
+ i++;
+ for (j = PLUGIN_MAX - 1; j > i; j--)
+ catalog->ids[j] = catalog->ids[j - 1];
- catalog->ids[i] = node->info->id;
+ catalog->ids[i] = node->info->id;
+ }
}
+ node = xine_list_next_content (catalog->input);
}
pthread_mutex_unlock (&catalog->lock);
@@ -1328,23 +1483,14 @@ static vo_driver_t *_load_video_driver (xine_t *this, plugin_node_t *node,
vo_driver_t *driver;
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class (this, node->filename, node->info, data);
-
- if (!node->plugin_class)
+ if (!node->plugin_class && !_load_plugin_class (this, node, data))
return NULL;
driver = ((video_driver_class_t *)node->plugin_class)->open_plugin(node->plugin_class, data);
if (driver) {
+ inc_node_ref(node);
driver->node = node;
- node->ref ++;
- } else {
-
- /* FIXME
- if (!node->ref)
- unload class
- */
}
return driver;
@@ -1378,7 +1524,7 @@ xine_video_port_t *xine_open_video_driver (xine_t *this,
break;
}
- } else if( vo_info->priority >= 0 ) {
+ } else {
driver = _load_video_driver (this, node, visual);
@@ -1470,25 +1616,14 @@ static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node,
ao_driver_t *driver;
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class (this, node->filename, node->info, data);
-
- if (!node->plugin_class) {
- lprintf ("failed to load plugin class %s\n", node->info->id);
+ if (!node->plugin_class && !_load_plugin_class (this, node, data))
return NULL;
- }
driver = ((audio_driver_class_t *)node->plugin_class)->open_plugin(node->plugin_class, data);
if (driver) {
+ inc_node_ref(node);
driver->node = node;
- node->ref ++;
- } else {
-
- /* FIXME
- if (!node->ref)
- unload class
- */
}
return driver;
@@ -1523,7 +1658,6 @@ xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id,
} else if( ao_info->priority >= 0 ) {
driver = _load_audio_driver (this, node, data);
if (driver) {
-
break;
}
}
@@ -1563,6 +1697,7 @@ void xine_close_audio_driver (xine_t *this, xine_audio_port_t *ao_port) {
ao_port->exit(ao_port);
}
+
void xine_close_video_driver (xine_t *this, xine_video_port_t *vo_port) {
if( vo_port )
@@ -1587,13 +1722,17 @@ char **xine_get_autoplay_mrls (xine_t *this, const char *plugin_id,
while (node) {
if (!strcasecmp (node->info->id, plugin_id)) {
+ input_class_t *ic;
- input_class_t *ic = (input_class_t *) node->plugin_class;
+ if (node->plugin_class || _load_plugin_class (this, node, NULL)) {
- if (!ic->get_autoplay_list)
- return NULL;
+ ic = (input_class_t *) node->plugin_class;
+
+ if (!ic->get_autoplay_list)
+ return NULL;
- return ic->get_autoplay_list (ic, num_mrls);
+ return ic->get_autoplay_list (ic, num_mrls);
+ }
}
node = xine_list_next_content (catalog->input);
}
@@ -1615,13 +1754,17 @@ xine_mrl_t **xine_get_browse_mrls (xine_t *this, const char *plugin_id,
while (node) {
if (!strcasecmp (node->info->id, plugin_id)) {
+ input_class_t *ic;
- input_class_t *ic = (input_class_t *) node->plugin_class;
+ if (node->plugin_class || _load_plugin_class (this, node, NULL)) {
- if (!ic->get_dir)
- return NULL;
+ ic = (input_class_t *) node->plugin_class;
+
+ if (!ic->get_dir)
+ return NULL;
- return ic->get_dir (ic, start_mrl, num_mrls);
+ return ic->get_dir (ic, start_mrl, num_mrls);
+ }
}
node = xine_list_next_content (catalog->input);
}
@@ -1649,11 +1792,7 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ
return NULL;
}
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class (stream->xine, node->filename,
- node->info, NULL);
-
- if (!node->plugin_class) {
+ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) {
/* remove non working plugin from catalog */
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s failed to init its class.\n", node->info->id);
@@ -1668,8 +1807,8 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ
vd = ((video_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream);
if (vd) {
+ inc_node_ref(node);
vd->node = node;
- node->ref ++;
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s will be used for video streamtype %02x.\n",
node->info->id, stream_type);
@@ -1698,10 +1837,11 @@ void _x_free_video_decoder (xine_stream_t *stream, video_decoder_t *vd) {
vd->dispose (vd);
- pthread_mutex_lock (&catalog->lock);
- node->ref--;
- /* FIXME: unload plugin if no-longer used */
- pthread_mutex_unlock (&catalog->lock);
+ if (node) {
+ pthread_mutex_lock (&catalog->lock);
+ dec_node_ref(node);
+ pthread_mutex_unlock (&catalog->lock);
+ }
}
@@ -1726,11 +1866,7 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ
return NULL;
}
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class (stream->xine, node->filename,
- node->info, NULL);
-
- if (!node->plugin_class) {
+ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) {
/* remove non working plugin from catalog */
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s failed to init its class.\n", node->info->id);
@@ -1745,8 +1881,8 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ
ad = ((audio_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream);
if (ad) {
+ inc_node_ref(node);
ad->node = node;
- node->ref ++;
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s will be used for audio streamtype %02x.\n",
node->info->id, stream_type);
@@ -1774,13 +1910,95 @@ void _x_free_audio_decoder (xine_stream_t *stream, audio_decoder_t *ad) {
ad->dispose (ad);
- pthread_mutex_lock (&catalog->lock);
- node->ref--;
- /* FIXME: unload plugin if no-longer used */
- pthread_mutex_unlock (&catalog->lock);
+ if (node) {
+ pthread_mutex_lock (&catalog->lock);
+ dec_node_ref(node);
+ pthread_mutex_unlock (&catalog->lock);
+ }
}
+#ifdef LOG
+static void _display_file_plugin_list (xine_list_t *list, plugin_file_t *file) {
+ plugin_node_t *node;
+
+ node = xine_list_first_content(list);
+ while (node) {
+ if ((node->file == file) && (node->ref)) {
+ printf(" plugin: %s, class: %p , %d instance(s)\n",
+ node->info->id, node->plugin_class, node->ref);
+ }
+ node = xine_list_next_content(list);
+ }
+}
+#endif
+
+static void _unload_unref_plugins(xine_t *this, xine_list_t *list) {
+
+ plugin_node_t *node;
+
+ node = xine_list_first_content(list);
+ while (node) {
+ if (node->ref == 0) {
+ plugin_file_t *file = node->file;
+
+ /* no plugin of this class is instancied */
+ _dispose_plugin_class(node);
+
+ /* check file references */
+ if (file && !file->ref && file->lib_handle && !file->no_unload) {
+ /* unload this file */
+ lprintf("unloading plugin %s\n", file->filename);
+ if (dlclose(file->lib_handle)) {
+ const char *error = dlerror();
+
+ xine_log (this, XINE_LOG_PLUGIN,
+ _("load_plugins: cannot unload plugin lib %s:\n%s\n"), file->filename, error);
+ }
+ file->lib_handle = NULL;
+ }
+ }
+ node = xine_list_next_content(list);
+ }
+}
+
+void xine_plugins_garbage_collector(xine_t *self) {
+
+ _unload_unref_plugins(self, self->plugin_catalog->input);
+ _unload_unref_plugins(self, self->plugin_catalog->demux);
+ _unload_unref_plugins(self, self->plugin_catalog->spu);
+ _unload_unref_plugins(self, self->plugin_catalog->audio);
+ _unload_unref_plugins(self, self->plugin_catalog->video);
+ _unload_unref_plugins(self, self->plugin_catalog->aout);
+ _unload_unref_plugins(self, self->plugin_catalog->vout);
+ _unload_unref_plugins(self, self->plugin_catalog->post);
+
+#ifdef LOG
+ {
+ plugin_file_t *file;
+
+ printf("\nPlugin summary after garbage collection : \n");
+ file = xine_list_first_content(self->plugin_catalog->file);
+ while (file) {
+ if (file->ref) {
+ printf("\n file %s referenced %d time(s)\n", file->filename, file->ref);
+
+ _display_file_plugin_list (self->plugin_catalog->input, file);
+ _display_file_plugin_list (self->plugin_catalog->demux, file);
+ _display_file_plugin_list (self->plugin_catalog->spu, file);
+ _display_file_plugin_list (self->plugin_catalog->audio, file);
+ _display_file_plugin_list (self->plugin_catalog->video, file);
+ _display_file_plugin_list (self->plugin_catalog->aout, file);
+ _display_file_plugin_list (self->plugin_catalog->vout, file);
+ _display_file_plugin_list (self->plugin_catalog->post, file);
+ }
+ file = xine_list_next_content(self->plugin_catalog->file);
+ }
+ printf("End of plugin summary\n\n");
+ }
+#endif
+}
+
spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) {
plugin_node_t *node;
@@ -1801,11 +2019,7 @@ spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) {
return NULL;
}
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class (stream->xine, node->filename,
- node->info, NULL);
-
- if (!node->plugin_class) {
+ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) {
/* remove non working plugin from catalog */
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s failed to init its class.\n", node->info->id);
@@ -1820,8 +2034,8 @@ spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) {
sd = ((spu_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream);
if (sd) {
+ inc_node_ref(node);
sd->node = node;
- node->ref ++;
xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
"load_plugins: plugin %s will be used for spu streamtype %02x.\n",
node->info->id, stream_type);
@@ -1849,10 +2063,11 @@ void _x_free_spu_decoder (xine_stream_t *stream, spu_decoder_t *sd) {
sd->dispose (sd);
- pthread_mutex_lock (&catalog->lock);
- node->ref--;
- /* FIXME: unload plugin if no-longer used */
- pthread_mutex_unlock (&catalog->lock);
+ if (node) {
+ pthread_mutex_lock (&catalog->lock);
+ dec_node_ref(node);
+ pthread_mutex_unlock (&catalog->lock);
+ }
}
const char *const *xine_list_demuxer_plugins(xine_t *xine) {
@@ -1937,19 +2152,22 @@ const char *const *xine_list_post_plugins_typed(xine_t *xine, int type) {
#define GET_PLUGIN_DESC(NAME,TYPE,CATITEM) \
const char *xine_get_##NAME##_plugin_description (xine_t *this, const char *plugin_id) { \
- plugin_catalog_t *catalog = this->plugin_catalog; \
+ plugin_catalog_t *catalog = this->plugin_catalog; \
plugin_node_t *node = xine_list_first_content (catalog->CATITEM); \
- while (node) { \
- if (!strcasecmp (node->info->id, plugin_id)) { \
- TYPE##_class_t *ic = (TYPE##_class_t *) node->plugin_class; \
- if (!ic) \
- ic = node->plugin_class = \
- _load_plugin_class (this, node->filename, node->info, NULL); \
- return ic->get_description(ic); \
- } \
- node = xine_list_next_content (catalog->CATITEM); \
- } \
- return NULL; \
+ while (node) { \
+ if (!strcasecmp (node->info->id, plugin_id)) { \
+ TYPE##_class_t *ic = (TYPE##_class_t *) node->plugin_class; \
+ if (!ic) { \
+ if (_load_plugin_class (this, node, NULL)) \
+ ic = node->plugin_class; \
+ else \
+ return NULL; \
+ } \
+ return ic->get_description(ic); \
+ } \
+ node = xine_list_next_content (catalog->CATITEM); \
+ } \
+ return NULL; \
}
GET_PLUGIN_DESC (input, input, input)
@@ -1978,10 +2196,7 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs,
if (strcmp(node->info->id, name) == 0) {
post_plugin_t *post;
- if (!node->plugin_class)
- node->plugin_class = _load_plugin_class(xine, node->filename,
- node->info, NULL);
- if (!node->plugin_class) {
+ if (!node->plugin_class && !_load_plugin_class(xine, node, NULL)) {
xprintf(xine, XINE_VERBOSITY_DEBUG,
"load_plugins: requested post plugin %s failed to load\n", name);
pthread_mutex_unlock(&catalog->lock);
@@ -1999,7 +2214,7 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs,
post->running_ticket = xine->port_ticket;
post->xine = xine;
post->node = node;
- node->ref++;
+ inc_node_ref(node);
pthread_mutex_unlock(&catalog->lock);
/* init the lists of announced connections */
@@ -2079,12 +2294,16 @@ char *xine_get_file_extensions (xine_t *self) {
len = 0;
node = xine_list_first_content (catalog->demux);
while (node) {
- demux_class_t *cls = (demux_class_t *)node->plugin_class;
+ demux_class_t *cls;
char *exts;
- if((exts = cls->get_extensions(cls)) && strlen(exts))
- len += strlen(exts) + 1;
+ if (node->plugin_class || _load_plugin_class(self, node, NULL)) {
+
+ cls = (demux_class_t *)node->plugin_class;
+ if((exts = cls->get_extensions(cls)) && strlen(exts))
+ len += strlen(exts) + 1;
+ }
node = xine_list_next_content (catalog->demux);
}
@@ -2094,24 +2313,27 @@ char *xine_get_file_extensions (xine_t *self) {
node = xine_list_first_content (catalog->demux);
while (node) {
- demux_class_t *cls = (demux_class_t *)node->plugin_class;
+ demux_class_t *cls;
char *e;
int l;
- if((e = cls->get_extensions (cls)) && strlen(e)) {
- l = strlen(e);
- memcpy (&str[pos], e, l);
+ if (node->plugin_class || _load_plugin_class(self, node, NULL)) {
+
+ cls = (demux_class_t *)node->plugin_class;
+
+ if((e = cls->get_extensions (cls)) && strlen(e)) {
+ l = strlen(e);
+ memcpy (&str[pos], e, l);
- pos += l;
+ pos += l;
- /* Don't add ' ' char at the end of str */
- if((pos + 1) < len) {
- str[pos] = ' ';
- pos++;
+ /* Don't add ' ' char at the end of str */
+ if((pos + 1) < len) {
+ str[pos] = ' ';
+ pos++;
+ }
}
-
}
-
node = xine_list_next_content (catalog->demux);
}
@@ -2138,13 +2360,17 @@ char *xine_get_mime_types (xine_t *self) {
len = 0; node = xine_list_first_content (catalog->demux);
while (node) {
- demux_class_t *cls = (demux_class_t *)node->plugin_class;
+ demux_class_t *cls;
char *s;
- s = cls->get_mimetypes (cls);
- if (s)
- len += strlen(s);
+ if (node->plugin_class || _load_plugin_class(self, node, NULL)) {
+
+ cls = (demux_class_t *)node->plugin_class;
+ s = cls->get_mimetypes (cls);
+ if (s)
+ len += strlen(s);
+ }
node = xine_list_next_content (catalog->demux);
}
@@ -2155,16 +2381,21 @@ char *xine_get_mime_types (xine_t *self) {
node = xine_list_first_content (catalog->demux);
while (node) {
- demux_class_t *cls = (demux_class_t *)node->plugin_class;
+ demux_class_t *cls;
char *s;
int l;
- s = cls->get_mimetypes (cls);
- if (s) {
- l = strlen(s);
- memcpy (&str[pos], s, l);
+ if (node->plugin_class || _load_plugin_class(self, node, NULL)) {
+
+ cls = (demux_class_t *)node->plugin_class;
+
+ s = cls->get_mimetypes (cls);
+ if (s) {
+ l = strlen(s);
+ memcpy (&str[pos], s, l);
- pos += l;
+ pos += l;
+ }
}
node = xine_list_next_content (catalog->demux);
}
@@ -2198,19 +2429,24 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) {
node = xine_list_first_content (catalog->demux);
while (node && !id) {
- demux_class_t *cls = (demux_class_t *)node->plugin_class;
+ demux_class_t *cls;
+
+ if (node->plugin_class || _load_plugin_class(self, node, NULL)) {
+
+ cls = (demux_class_t *)node->plugin_class;
- s = cls->get_mimetypes (cls);
- if (s) {
- mime_demux = strdup(s);
+ s = cls->get_mimetypes (cls);
+ if (s) {
+ mime_demux = strdup(s);
- for(s=mime_demux; *s; s++)
- *s = tolower(*s);
+ for(s=mime_demux; *s; s++)
+ *s = tolower(*s);
- if( strstr(mime_demux, mime_arg) )
- id = strdup(node->info->id);
+ if( strstr(mime_demux, mime_arg) )
+ id = strdup(node->info->id);
- free(mime_demux);
+ free(mime_demux);
+ }
}
node = xine_list_next_content (catalog->demux);
}
@@ -2232,38 +2468,15 @@ static void dispose_plugin_list (xine_list_t *list) {
node = xine_list_first_content (list);
while (node) {
- if (node->plugin_class) {
- void *cls = node->plugin_class;
-
- /* dispose of plugin class */
- switch (node->info->type & PLUGIN_TYPE_MASK) {
- case PLUGIN_INPUT:
- ((input_class_t *)cls)->dispose ((input_class_t *)cls);
- break;
- case PLUGIN_DEMUX:
- ((demux_class_t *)cls)->dispose ((demux_class_t *)cls);
- break;
- case PLUGIN_SPU_DECODER:
- ((spu_decoder_class_t *)cls)->dispose ((spu_decoder_class_t *)cls);
- break;
- case PLUGIN_AUDIO_DECODER:
- ((audio_decoder_class_t *)cls)->dispose ((audio_decoder_class_t *)cls);
- break;
- case PLUGIN_VIDEO_DECODER:
- ((video_decoder_class_t *)cls)->dispose ((video_decoder_class_t *)cls);
- break;
- case PLUGIN_AUDIO_OUT:
- ((audio_driver_class_t *)cls)->dispose ((audio_driver_class_t *)cls);
- break;
- case PLUGIN_VIDEO_OUT:
- ((video_driver_class_t *)cls)->dispose ((video_driver_class_t *)cls);
- break;
- case PLUGIN_POST:
- ((post_class_t *)cls)->dispose ((post_class_t *)cls);
- break;
- }
+
+ if (node->ref == 0)
+ _dispose_plugin_class(node);
+ else {
+ lprintf("node \"%s\" still referenced %d time(s)\n", node->info->id, node->ref);
+ node = xine_list_next_content (list);
+ continue;
}
-
+
/* free special info */
switch (node->info->type & PLUGIN_TYPE_MASK) {
case PLUGIN_SPU_DECODER:
@@ -2281,7 +2494,6 @@ static void dispose_plugin_list (xine_list_t *list) {
/* free info structure and string copies */
free (node->info->id);
free (node->info);
- free (node->filename);
free (node);
node = xine_list_next_content (list);
@@ -2291,6 +2503,19 @@ static void dispose_plugin_list (xine_list_t *list) {
}
+static void dispose_plugin_file_list (xine_list_t *list) {
+ plugin_file_t *file;
+
+ file = xine_list_first_content (list);
+ while (file) {
+ free (file->filename);
+ free (file);
+ file = xine_list_next_content (list);
+ }
+ xine_list_free(list);
+}
+
+
/*
* dispose all currently loaded plugins (shutdown)
*/
@@ -2299,7 +2524,7 @@ void _x_dispose_plugins (xine_t *this) {
if(this->plugin_catalog) {
int i;
-
+
dispose_plugin_list (this->plugin_catalog->input);
dispose_plugin_list (this->plugin_catalog->demux);
dispose_plugin_list (this->plugin_catalog->spu);
@@ -2308,9 +2533,9 @@ void _x_dispose_plugins (xine_t *this) {
dispose_plugin_list (this->plugin_catalog->aout);
dispose_plugin_list (this->plugin_catalog->vout);
dispose_plugin_list (this->plugin_catalog->post);
-
dispose_plugin_list (this->plugin_catalog->cache);
-
+ dispose_plugin_file_list (this->plugin_catalog->file);
+
for (i = 0; this->plugin_catalog->prio_desc[i]; i++)
free(this->plugin_catalog->prio_desc[i]);
diff --git a/src/xine-engine/plugin_catalog.h b/src/xine-engine/plugin_catalog.h
index 5cc716a95..e57410f13 100644
--- a/src/xine-engine/plugin_catalog.h
+++ b/src/xine-engine/plugin_catalog.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: plugin_catalog.h,v 1.16 2004/06/23 19:45:54 mroi Exp $
+ * $Id: plugin_catalog.h,v 1.17 2005/02/09 20:03:21 tmattern Exp $
*
* xine-internal header: Definitions for plugin lists
*
@@ -46,11 +46,18 @@
typedef struct {
char *filename;
- plugin_info_t *info;
- void *plugin_class;
- int ref; /* count instances created of this plugin */
off_t filesize;
time_t filemtime;
+ int ref; /* count number of classes */
+ void *lib_handle;
+ int no_unload; /* set if the file can't be unloaded */
+} plugin_file_t ;
+
+typedef struct {
+ plugin_file_t *file;
+ plugin_info_t *info;
+ void *plugin_class;
+ int ref; /* count intances of plugins */
} plugin_node_t ;
struct plugin_catalog_s {
@@ -64,6 +71,7 @@ struct plugin_catalog_s {
xine_list_t *post;
xine_list_t *cache;
+ xine_list_t *file;
plugin_node_t *audio_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE];
plugin_node_t *video_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE];
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index fc744bcfd..49ee8788e 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.c,v 1.308 2005/01/21 18:47:54 hadess Exp $
+ * $Id: xine.c,v 1.309 2005/02/09 20:03:21 tmattern Exp $
*/
/*
@@ -359,9 +359,8 @@ static void close_internal (xine_stream_t *stream) {
stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
stream->ignore_speed_change = 0;
- lprintf ("disposing demux\n");
if (stream->demux_plugin) {
- stream->demux_plugin->dispose (stream->demux_plugin);
+ _x_free_demux_plugin(stream, stream->demux_plugin);
stream->demux_plugin = NULL;
}
@@ -370,7 +369,7 @@ static void close_internal (xine_stream_t *stream) {
*/
if (stream->input_plugin) {
- stream->input_plugin->dispose(stream->input_plugin);
+ _x_free_input_plugin(stream, stream->input_plugin);
stream->input_plugin = NULL;
}
@@ -1042,12 +1041,12 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
if (stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_OK) {
xine_log (stream->xine, XINE_LOG_MSG, _("xine: demuxer failed to start\n"));
- stream->demux_plugin->dispose (stream->demux_plugin);
+ _x_free_demux_plugin(stream, stream->demux_plugin);
stream->demux_plugin = NULL;
xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "demux disposed\n");
- stream->input_plugin->dispose (stream->input_plugin);
+ _x_free_input_plugin(stream, stream->input_plugin);
stream->input_plugin = NULL;
stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 0193428ba..2c511d127 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_internal.h,v 1.163 2004/12/19 20:24:31 miguelfreitas Exp $
+ * $Id: xine_internal.h,v 1.164 2005/02/09 20:03:21 tmattern Exp $
*
*/
@@ -361,6 +361,8 @@ demux_plugin_t *_x_find_demux_plugin_by_name (xine_stream_t *stream, const char
demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input);
input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename);
input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size);
+void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input);
+void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux);
/* create decoder fifos and threads */