diff options
Diffstat (limited to 'src/xine-engine/load_plugins.c')
-rw-r--r-- | src/xine-engine/load_plugins.c | 659 |
1 files changed, 345 insertions, 314 deletions
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 71cb19d3b..9eb33f8ed 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2006 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -101,7 +101,7 @@ static const int plugin_iface_versions[] = { SPU_DECODER_IFACE_VERSION, AUDIO_OUT_IFACE_VERSION, VIDEO_OUT_DRIVER_IFACE_VERSION, - POST_PLUGIN_IFACE_VERSION + POST_PLUGIN_IFACE_VERSION }; static void _build_list_typed_plugins(plugin_catalog_t **catalog, xine_sarray_t *type) { @@ -112,7 +112,7 @@ static void _build_list_typed_plugins(plugin_catalog_t **catalog, xine_sarray_t list_size = xine_sarray_size (type); for (list_id = 0, i = 0; list_id < list_size; list_id++) { node = xine_sarray_get(type, list_id); - + /* add only unique ids to the list */ for ( j = 0; j < i; j++ ) { if( !strcmp((*catalog)->ids[j], node->info->id) ) @@ -157,9 +157,9 @@ static int get_decoder_priority(xine_t *this, plugin_node_t *node) { char key[80]; snprintf(key, sizeof(key), "engine.decoder_priorities.%s", node->info->id); - + entry = this->config->lookup_entry(this->config, key); - + if (entry && entry->num_value) /* user given priorities should definitely override defaults, so multiply them */ return entry->num_value * 100; @@ -258,14 +258,14 @@ static plugin_info_t *_get_cached_info (xine_t *this, node->file->filesize == filesize && node->file->filemtime == filemtime && !strcmp( node->file->filename, filename )) { - + return node->info; } - + /* skip previously returned items */ if( node->info == previous_info ) previous_info = NULL; - + } return NULL; } @@ -313,20 +313,19 @@ static void _insert_node (xine_t *this, const input_info_t *input_old; uint32_t *types; char key[80]; - char desc[100]; int i; _x_assert(list); _x_assert(info); if (info->API != api_version) { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: ignoring plugin %s, wrong iface version %d (should be %d)\n"), info->id, info->API, api_version); return; } - entry = xine_xmalloc(sizeof(plugin_node_t)); - entry->info = xine_xmalloc(sizeof(plugin_info_t)); + entry = calloc(1, sizeof(plugin_node_t)); + entry->info = calloc(1, sizeof(plugin_info_t)); *(entry->info) = *info; entry->info->id = strdup(info->id); entry->info->init = info->init; @@ -339,7 +338,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_OUT: vo_old = info->special_info; - vo_new = xine_xmalloc(sizeof(vo_info_t)); + vo_new = calloc(1, sizeof(vo_info_t)); entry->priority = vo_new->priority = vo_old->priority; vo_new->visual_type = vo_old->visual_type; entry->info->special_info = vo_new; @@ -347,7 +346,7 @@ static void _insert_node (xine_t *this, case PLUGIN_AUDIO_OUT: ao_old = info->special_info; - ao_new = xine_xmalloc(sizeof(ao_info_t)); + ao_new = calloc(1, sizeof(ao_info_t)); entry->priority = ao_new->priority = ao_old->priority; entry->info->special_info = ao_new; break; @@ -356,7 +355,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: decoder_old = info->special_info; - decoder_new = xine_xmalloc(sizeof(decoder_info_t)); + decoder_new = calloc(1, sizeof(decoder_info_t)); if (decoder_old == NULL) { if (file) xprintf (this, XINE_VERBOSITY_DEBUG, @@ -368,22 +367,21 @@ static void _insert_node (xine_t *this, info->id); _x_abort(); } - for (i=0; decoder_old->supported_types[i] != 0; ++i); - types = xine_xmalloc((i+1)*sizeof(uint32_t)); - for (i=0; decoder_old->supported_types[i] != 0; ++i){ - types[i] = decoder_old->supported_types[i]; + { + size_t supported_types_size; + for (supported_types_size=0; decoder_old->supported_types[supported_types_size] != 0; ++supported_types_size); + types = calloc((supported_types_size+1), sizeof(uint32_t)); + memcpy(types, decoder_old->supported_types, supported_types_size*sizeof(uint32_t)); + decoder_new->supported_types = types; } - decoder_new->supported_types = types; entry->priority = decoder_new->priority = decoder_old->priority; - + snprintf(key, sizeof(key), "engine.decoder_priorities.%s", info->id); - snprintf(desc, sizeof(desc), _("priority for %s decoder"), info->id); /* write the description on the heap because the config system * does not strdup() it, so we have to provide a different pointer * for each decoder */ for (i = 0; catalog->prio_desc[i]; i++); - catalog->prio_desc[i] = malloc(strlen(desc) + 1); - strcpy(catalog->prio_desc[i], desc); + asprintf(&catalog->prio_desc[i], _("priority for %s decoder"), info->id); this->config->register_num (this->config, key, 0, @@ -399,23 +397,23 @@ static void _insert_node (xine_t *this, entry->info->special_info = decoder_new; break; - + case PLUGIN_POST: post_old = info->special_info; - post_new = xine_xmalloc(sizeof(post_info_t)); + post_new = calloc(1, sizeof(post_info_t)); post_new->type = post_old->type; entry->info->special_info = post_new; break; - + case PLUGIN_DEMUX: demux_old = info->special_info; - demux_new = xine_xmalloc(sizeof(demuxer_info_t)); - + demux_new = calloc(1, sizeof(demuxer_info_t)); + if (demux_old) { entry->priority = demux_new->priority = demux_old->priority; lprintf("demux: %s, priority: %d\n", info->id, entry->priority); } else { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: demuxer plugin %s does not provide a priority," " xine-lib will use the default priority.\n"), info->id); @@ -426,13 +424,13 @@ static void _insert_node (xine_t *this, case PLUGIN_INPUT: input_old = info->special_info; - input_new = xine_xmalloc(sizeof(input_info_t)); - + input_new = calloc(1, sizeof(input_info_t)); + if (input_old) { entry->priority = input_new->priority = input_old->priority; lprintf("input: %s, priority: %d\n", info->id, entry->priority); } else { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: input plugin %s does not provide a priority," " xine-lib will use the default priority.\n"), info->id); @@ -463,12 +461,12 @@ static int _plugin_node_comparator(void *a, void *b) { } } -static plugin_catalog_t *_new_catalog(void){ +static plugin_catalog_t *XINE_MALLOC _new_catalog(void){ plugin_catalog_t *catalog; int i; - catalog = xine_xmalloc(sizeof(plugin_catalog_t)); + catalog = calloc(1, sizeof(plugin_catalog_t)); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { catalog->plugin_lists[i] = xine_sarray_new(0, _plugin_node_comparator); @@ -487,13 +485,13 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin while ( info && info->type != PLUGIN_NONE ) { - if (file) + if (file && file->filename) xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: plugin %s found\n"), file->filename); else xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: static plugin found\n")); - + if (this->plugin_catalog->plugin_count >= PLUGIN_MAX || (this->plugin_catalog->decoder_count >= DECODER_MAX && info->type >= PLUGIN_AUDIO_DECODER && info->type <= PLUGIN_SPU_DECODER)) { @@ -527,7 +525,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin } this->plugin_catalog->plugin_count++; } - + /* get next info */ if( file && !file->lib_handle ) { lprintf("get cached info\n"); @@ -556,25 +554,20 @@ static void collect_plugins(xine_t *this, char *path){ dir = opendir(path); if (dir) { struct dirent *pEntry; - size_t path_len, str_size; - char *str = NULL; - path_len = strlen(path); - str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ - str = malloc(str_size); - xine_fast_memcpy(str, path, path_len); - str[path_len] = '/'; - str[path_len + 1] = '\0'; + size_t path_len = strlen(path); + size_t str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ + char *str = malloc(str_size); + sprintf(str, "%s/", path); while ((pEntry = readdir (dir)) != NULL) { - size_t new_str_size, d_len; void *lib = NULL; plugin_info_t *info = NULL; - + struct stat statbuffer; - d_len = strlen(pEntry->d_name); - new_str_size = path_len + d_len + 2; + size_t d_len = strlen(pEntry->d_name); + size_t new_str_size = path_len + d_len + 2; if (str_size < new_str_size) { str_size = new_str_size + new_str_size / 2; str = realloc(str, str_size); @@ -599,7 +592,7 @@ static void collect_plugins(xine_t *this, char *path){ #if defined(__hpux) if(!strstr(str, ".sl") #elif defined(__CYGWIN__) || defined(WIN32) - if(!strstr(str, ".dll") + if(!strstr(str, ".dll") || strstr(str, ".dll.a") #else if(!strstr(str, ".so") #endif @@ -623,7 +616,7 @@ static void collect_plugins(xine_t *this, char *path){ if(!info && (lib = dlopen (str, RTLD_LAZY | RTLD_GLOBAL)) == NULL) { const char *error = dlerror(); /* too noisy -- but good to catch unresolved references */ - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: cannot open plugin lib %s:\n%s\n"), str, error); } else { @@ -666,14 +659,14 @@ static void collect_plugins(xine_t *this, char *path){ * generic 2nd stage plugin loader */ -static inline int _plugin_info_equal(const plugin_info_t *a, +static inline int _plugin_info_equal(const plugin_info_t *a, const plugin_info_t *b) { - if (a->type != b->type || + if (a->type != b->type || a->API != b->API || strcasecmp(a->id, b->id) || a->version != b->version) return 0; - + switch (a->type & PLUGIN_TYPE_MASK) { case PLUGIN_VIDEO_OUT: /* FIXME: Could special_info be NULL? */ @@ -682,11 +675,11 @@ static inline int _plugin_info_equal(const plugin_info_t *a, ((vo_info_t*)b->special_info)->visual_type); } break; - + default: break; } - + return 1; } @@ -729,7 +722,7 @@ static int _load_plugin_class(xine_t *this, info++; } lprintf("plugin not found\n"); - + } else { xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: Yikes! %s doesn't contain plugin info.\n"), filename); @@ -797,9 +790,9 @@ static void _load_required_plugins(xine_t *this, xine_sarray_t *list) { list_size = xine_sarray_size(list); while (list_id < list_size) { plugin_node_t *node = xine_sarray_get(list, list_id); - + if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class ) { - + lprintf("preload plugin %s from %s\n", node->info->id, node->file->filename); if (! _load_plugin_class (this, node, NULL)) { @@ -838,7 +831,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { const vo_info_t *vo_info; const ao_info_t *ao_info; const post_info_t *post_info; - + int i; int list_id = 0; int list_size; @@ -855,20 +848,20 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { fprintf(fp, "api=%d\n", node->info->API ); fprintf(fp, "id=%s\n", node->info->id ); fprintf(fp, "version=%lu\n", (unsigned long) node->info->version ); - + switch (node->info->type & PLUGIN_TYPE_MASK){ - + case PLUGIN_VIDEO_OUT: vo_info = node->info->special_info; fprintf(fp, "visual_type=%d\n", vo_info->visual_type ); fprintf(fp, "vo_priority=%d\n", vo_info->priority ); break; - + case PLUGIN_AUDIO_OUT: ao_info = node->info->special_info; fprintf(fp, "ao_priority=%d\n", ao_info->priority ); break; - + case PLUGIN_AUDIO_DECODER: case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: @@ -885,7 +878,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { demuxer_info = node->info->special_info; fprintf(fp, "demuxer_priority=%d\n", demuxer_info->priority); break; - + case PLUGIN_INPUT: input_info = node->info->special_info; fprintf(fp, "input_priority=%d\n", input_info->priority); @@ -895,8 +888,8 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { post_info = node->info->special_info; fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); break; - } - + } + fprintf(fp, "\n"); list_id++; } @@ -921,13 +914,13 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { char line[1024]; char *value; int version_ok = 0; - + node = NULL; file = NULL; while (fgets (line, 1023, fp)) { if (line[0] == '#') continue; - + if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) *value = (char) 0; /* eliminate any cr/lf */ @@ -941,11 +934,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( node ) { xine_sarray_add (plugins, node); } - node = xine_xmalloc(sizeof(plugin_node_t)); - file = xine_xmalloc(sizeof(plugin_file_t)); + node = calloc(1, sizeof(plugin_node_t)); + file = calloc(1, sizeof(plugin_file_t)); node->file = file; file->filename = strdup(line+1); - node->info = xine_xmalloc(2*sizeof(plugin_info_t)); + node->info = calloc(2, sizeof(plugin_info_t)); node->info[1].type = PLUGIN_NONE; decoder_info = NULL; vo_info = NULL; @@ -964,7 +957,7 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( i == CACHE_CATALOG_VERSION ) version_ok = 1; else - return; + return; } } else if (node) { if( !strcmp("size",line) ) { @@ -976,42 +969,42 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { } else if( !strcmp("type",line) ) { sscanf(value," %d",&i); node->info->type = i; - + switch (node->info->type & PLUGIN_TYPE_MASK){ - + case PLUGIN_VIDEO_OUT: node->info->special_info = vo_info = - xine_xmalloc(sizeof(vo_info_t)); + calloc(1, sizeof(vo_info_t)); break; - + case PLUGIN_AUDIO_OUT: node->info->special_info = ao_info = - xine_xmalloc(sizeof(ao_info_t)); + calloc(1, sizeof(ao_info_t)); break; - + case PLUGIN_DEMUX: node->info->special_info = demuxer_info = - xine_xmalloc(sizeof(demuxer_info_t)); + calloc(1, sizeof(demuxer_info_t)); break; case PLUGIN_INPUT: node->info->special_info = input_info = - xine_xmalloc(sizeof(input_info_t)); + calloc(1, sizeof(input_info_t)); break; case PLUGIN_AUDIO_DECODER: case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: node->info->special_info = decoder_info = - xine_xmalloc(sizeof(decoder_info_t)); + calloc(1, sizeof(decoder_info_t)); break; - + case PLUGIN_POST: node->info->special_info = post_info = - xine_xmalloc(sizeof(post_info_t)); + calloc(1, sizeof(post_info_t)); break; - } - + } + } else if( !strcmp("api",line) ) { sscanf(value," %d",&i); node->info->API = i; @@ -1025,11 +1018,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { vo_info->visual_type = i; } else if( !strcmp("supported_types",line) && decoder_info ) { char *s; - + for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { s = strchr(s+1, ' '); } - decoder_info->supported_types = xine_xmalloc((i+1)*sizeof(uint32_t)); + decoder_info->supported_types = calloc((i+1), sizeof(uint32_t)); for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { decoder_info->supported_types[i] = lu; s = strchr(s+1, ' '); @@ -1056,7 +1049,7 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { } } } - + if( node ) { xine_sarray_add (plugins, node); } @@ -1069,33 +1062,52 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { static void save_catalog (xine_t *this) { FILE *fp; - char *cachefile, *dirfile; + char *cachefile, *cachefile_new, *dirfile; const char *relname = CACHE_CATALOG_FILE; const char *dirname = CACHE_CATALOG_DIR; - - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); - + + const char *const homedir = xine_get_homedir(); + + asprintf(&cachefile, "%s/%s", homedir, relname); + asprintf(&cachefile_new, "%s.new", cachefile); + /* make sure homedir (~/.xine) exists */ - dirfile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(dirname) + 2); - sprintf(dirfile, "%s/%s", xine_get_homedir(), dirname); + asprintf(&dirfile, "%s/%s", homedir, dirname); mkdir (dirfile, 0755); free (dirfile); - if( (fp = fopen(cachefile,"w")) != NULL ) { + if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; - + fprintf(fp, "# this file is automatically created by xine, do not edit.\n\n"); fprintf(fp, "cache_catalog_version=%d\n\n", CACHE_CATALOG_VERSION); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); } - fclose(fp); + if (fclose(fp)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to save catalogue cache: %s\n"), err); + goto do_unlink; + } + else if (rename (cachefile_new, cachefile)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to replace catalogue cache: %s\n"), err); + do_unlink: + if (unlink (cachefile_new) && errno != ENOENT) + { + err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to remove new catalogue cache: %s\n"), err); + } + } } free(cachefile); + free(cachefile_new); } /* @@ -1104,13 +1116,11 @@ static void save_catalog (xine_t *this) { static void load_cached_catalog (xine_t *this) { FILE *fp; - char *cachefile; + char *cachefile; const char *relname = CACHE_CATALOG_FILE; - - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); - + + asprintf(&cachefile, "%s/%s", xine_get_homedir(), relname); + if( (fp = fopen(cachefile,"r")) != NULL ) { load_plugin_list (fp, this->plugin_catalog->cache_list); fclose(fp); @@ -1119,15 +1129,25 @@ static void load_cached_catalog (xine_t *this) { } +/* helper function for _x_scan_plugins */ +static void push_if_dir (xine_list_t *plugindirs, void *path) +{ + struct stat st; + if (!stat (path, &st) && S_ISDIR (st.st_mode)) + xine_list_push_back (plugindirs, path); + else + free (path); +} + /* * initialize catalog, load all plugins into new catalog */ void _x_scan_plugins (xine_t *this) { - - char *homedir, *plugindir, *pluginpath; - int i,j; - int lenpluginpath; - + + char *homedir, *pluginpath; + xine_list_t *plugindirs = xine_list_new (); + xine_list_iterator_t iter; + lprintf("_x_scan_plugins()\n"); if (this == NULL || this->config == NULL) { @@ -1140,45 +1160,49 @@ void _x_scan_plugins (xine_t *this) { this->plugin_catalog = _new_catalog(); load_cached_catalog (this); - if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL) { - pluginpath = strdup(pluginpath); + if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL && *pluginpath) { + char *p = pluginpath; + while (p && p[0]) + { + size_t len; + char *dir, *q; + + q = p; + p = strchr (p, XINE_PATH_SEPARATOR_CHAR); + if (p) { + p++; + len = p - q; + } else + len = strlen(q); + if (q[0] == '~' && q[1] == '/') + asprintf (&dir, "%s%.*s", homedir, (int)(len - 1), q + 1); + else + dir = strndup (q, len); + push_if_dir (plugindirs, dir); /* store or free it */ + } } else { - const char *str1, *str2; - int len; - - str1 = "~/.xine/plugins"; - str2 = XINE_PLUGINDIR; - len = strlen(str1) + strlen(str2) + 2; - pluginpath = xine_xmalloc(len); - snprintf(pluginpath, len, "%s" XINE_PATH_SEPARATOR_STRING "%s", str1, str2); - } - plugindir = xine_xmalloc(strlen(pluginpath)+strlen(homedir)+2); - j=0; - lenpluginpath = strlen(pluginpath); - for (i=0; i <= lenpluginpath; ++i){ - switch (pluginpath[i]){ - case XINE_PATH_SEPARATOR_CHAR: - case '\0': - plugindir[j] = '\0'; - collect_plugins(this, plugindir); - j = 0; - break; - case '~': - if (j == 0){ - strcpy(plugindir, homedir); - j = strlen(plugindir); - break; - } - default: - plugindir[j++] = pluginpath[i]; + char *dir; + int i; + asprintf (&dir, "%s/.xine/plugins", homedir); + push_if_dir (plugindirs, dir); + for (i = 0; i <= XINE_LT_AGE; ++i) + { + asprintf (&dir, "%s.%d", XINE_PLUGINROOT, XINE_LT_AGE - i); + push_if_dir (plugindirs, dir); } } - free(plugindir); - free(pluginpath); + for (iter = xine_list_front (plugindirs); iter; + iter = xine_list_next (plugindirs, iter)) + { + char *dir = xine_list_get_value (plugindirs, iter); + collect_plugins(this, dir); + free (dir); + } + xine_list_delete (plugindirs); free(homedir); save_catalog (this); - + load_required_plugins (this); map_decoders (this); @@ -1208,7 +1232,7 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) { plugin->node = node; break; } - } + } } pthread_mutex_unlock (&catalog->lock); @@ -1229,6 +1253,26 @@ void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) { } } +static int probe_mime_type (xine_t *self, plugin_node_t *node, const char *mime_type) +{ + /* catalog->lock is expected to be locked */ + if (node->plugin_class || _load_plugin_class(self, node, NULL)) + { + const unsigned int mime_type_len = strlen (mime_type); + demux_class_t *cls = (demux_class_t *)node->plugin_class; + const char *mime = cls->get_mimetypes (cls); + while (mime) + { + while (*mime == ';' || isspace (*mime)) + ++mime; + if (!strncasecmp (mime, mime_type, mime_type_len) && + (!mime[mime_type_len] || mime[mime_type_len] == ':' || mime[mime_type_len] == ';')) + return 1; + mime = strchr (mime, ';'); + } + } + return 0; +} static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2, input_plugin_t *input) { @@ -1251,8 +1295,6 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth while (methods[i] != -1 && !plugin) { int list_id, list_size; - stream->content_detection_method = methods[i]; - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size(catalog->plugin_lists[PLUGIN_DEMUX - 1]); @@ -1264,6 +1306,25 @@ 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)) { + const char *mime_type; + + /* If detecting by MRL, try the MIME type first (but not text/plain)... */ + stream->content_detection_method = METHOD_EXPLICIT; + if (methods[i] == METHOD_BY_EXTENSION && + stream->input_plugin->get_optional_data && + stream->input_plugin->get_optional_data (stream->input_plugin, NULL, INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + stream->input_plugin->get_optional_data (stream->input_plugin, &mime_type, INPUT_OPTIONAL_DATA_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + mime_type && strcasecmp (mime_type, "text/plain") && + probe_mime_type (stream->xine, node, mime_type) && + (plugin = ((demux_class_t *)node->plugin_class)->open_plugin (node->plugin_class, stream, input))) + { + inc_node_ref(node); + plugin->node = node; + break; + } + + /* ... then try the extension */ + stream->content_detection_method = methods[i]; if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1377,7 +1438,7 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha if (strcasecmp(node->info->id, last_demux_name) == 0) { last_demux = node; } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + 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)) { if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { @@ -1485,7 +1546,7 @@ const char *const *xine_get_browsable_input_plugin_ids(xine_t *this) { for (list_id = 0; list_id < list_size; list_id++) { input_class_t *ic; - + node = xine_sarray_get(catalog->plugin_lists[PLUGIN_INPUT - 1], list_id); if (node->plugin_class || _load_plugin_class(this, node, NULL)) { @@ -1544,7 +1605,7 @@ vo_driver_t *_x_load_video_output_plugin(xine_t *this, if (id && !strcasecmp(id, "auto")) id = NULL; - + pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); @@ -1592,7 +1653,7 @@ xine_video_port_t *xine_open_video_driver (xine_t *this, } port = _x_vo_new_port(this, driver, 0); - + return port; } @@ -1631,7 +1692,7 @@ xine_video_port_t *xine_new_framegrab_video_port (xine_t *this) { } port = _x_vo_new_port(this, driver, 1); - + return port; } @@ -1641,7 +1702,7 @@ xine_video_port_t *xine_new_framegrab_video_port (xine_t *this) { const char *const *xine_list_audio_output_plugins (xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_AUDIO_OUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -1651,7 +1712,7 @@ const char *const *xine_list_audio_output_plugins (xine_t *xine) { const char *const *xine_list_video_output_plugins (xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -1659,6 +1720,36 @@ const char *const *xine_list_video_output_plugins (xine_t *xine) { return catalog->ids; } +const char *const *xine_list_video_output_plugins_typed(xine_t *xine, uint64_t typemask) +{ + plugin_catalog_t *catalog = xine->plugin_catalog; + plugin_node_t *node; + int list_id, list_size, i; + + pthread_mutex_lock (&catalog->lock); + + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); + + for (list_id = i = 0; list_id < list_size; list_id++) + { + node = xine_sarray_get (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1], list_id); + if (typemask & (1ULL << ((vo_info_t *)node->info->special_info)->visual_type)) + { + const char *id = node->info->id; + int j = i; + while (--j >= 0) + if (!strcmp (catalog->ids[j], id)) + goto ignore; /* already listed */ + catalog->ids[i++] = id; + } + ignore: ; + } + catalog->ids[i] = NULL; + + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; +} + static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, void *data) { @@ -1721,7 +1812,7 @@ xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id, if (id && !strcasecmp(id, "auto") ) id = NULL; - + pthread_mutex_lock (&catalog->lock); driver = NULL; @@ -1747,13 +1838,13 @@ xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id, } pthread_mutex_unlock (&catalog->lock); - + if (!driver) { if (id) xprintf (this, XINE_VERBOSITY_LOG, _("load_plugins: failed to load audio output plugin <%s>\n"), id); else - xprintf (this, XINE_VERBOSITY_LOG, + xprintf (this, XINE_VERBOSITY_LOG, _("load_plugins: audio output auto-probing didn't find any usable audio driver.\n")); return NULL; } @@ -1811,7 +1902,7 @@ char **xine_get_autoplay_mrls (xine_t *this, const char *plugin_id, if (node->plugin_class || _load_plugin_class (this, node, NULL)) { ic = (input_class_t *) node->plugin_class; - + if (!ic->get_autoplay_list) return NULL; @@ -1845,7 +1936,7 @@ xine_mrl_t **xine_get_browse_mrls (xine_t *this, const char *plugin_id, if (node->plugin_class || _load_plugin_class (this, node, NULL)) { ic = (input_class_t *) node->plugin_class; - + if (!ic->get_dir) return NULL; @@ -1877,7 +1968,7 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) { /* remove non working plugin from catalog */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: plugin %s failed to init its class.\n", node->info->id); for (j = i + 1; j < PLUGINS_PER_TYPE; j++) catalog->video_decoder_map[stream_type][j - 1] = @@ -1893,9 +1984,9 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ inc_node_ref(node); vd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for video streamtype %02x.\n", + "load_plugins: plugin %s will be used for video streamtype %02x.\n", node->info->id, stream_type); - + break; } else { /* remove non working plugin from catalog */ @@ -1948,7 +2039,7 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) { /* remove non working plugin from catalog */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: plugin %s failed to init its class.\n", node->info->id); for (j = i + 1; j < PLUGINS_PER_TYPE; j++) catalog->audio_decoder_map[stream_type][j - 1] = @@ -1964,7 +2055,7 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ inc_node_ref(node); ad->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for audio streamtype %02x.\n", + "load_plugins: plugin %s will be used for audio streamtype %02x.\n", node->info->id, stream_type); break; } else { @@ -2004,11 +2095,11 @@ int _x_decoder_available (xine_t *xine, uint32_t buftype) if ( (buftype & 0xFF000000) == BUF_VIDEO_BASE ) { if( catalog->video_decoder_map[stream_type][0] ) return 1; - } else + } else if ( (buftype & 0xFF000000) == BUF_AUDIO_BASE ) { if( catalog->audio_decoder_map[stream_type][0] ) return 1; - } else + } else if ( (buftype & 0xFF000000) == BUF_SPU_BASE ) { if( catalog->spu_decoder_map[stream_type][0] ) return 1; @@ -2035,7 +2126,7 @@ static void _display_file_plugin_list (xine_list_t *list, plugin_file_t *file) { #endif static void _unload_unref_plugins(xine_t *this, xine_sarray_t *list) { - + plugin_node_t *node; int list_id, list_size; @@ -2073,7 +2164,7 @@ void xine_plugins_garbage_collector(xine_t *self) { pthread_mutex_lock (&catalog->lock); for(i = 0; i < PLUGIN_TYPE_MAX; i++) { _unload_unref_plugins(self, self->plugin_catalog->plugin_lists[i]); - } + } #if 0 { @@ -2135,7 +2226,7 @@ spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) { inc_node_ref(node); sd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for spu streamtype %02x.\n", + "load_plugins: plugin %s will be used for spu streamtype %02x.\n", node->info->id, stream_type); break; } else { @@ -2169,7 +2260,7 @@ void _x_free_spu_decoder (xine_stream_t *stream, spu_decoder_t *sd) { const char *const *xine_list_demuxer_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_DEMUX - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2179,7 +2270,7 @@ const char *const *xine_list_demuxer_plugins(xine_t *xine) { const char *const *xine_list_input_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_INPUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2189,7 +2280,7 @@ const char *const *xine_list_input_plugins(xine_t *xine) { const char *const *xine_list_spu_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_SPU_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2199,7 +2290,7 @@ const char *const *xine_list_spu_plugins(xine_t *xine) { const char *const *xine_list_audio_decoder_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_AUDIO_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2209,7 +2300,7 @@ const char *const *xine_list_audio_decoder_plugins(xine_t *xine) { const char *const *xine_list_video_decoder_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_VIDEO_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2219,7 +2310,7 @@ const char *const *xine_list_video_decoder_plugins(xine_t *xine) { const char *const *xine_list_post_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_POST - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2232,7 +2323,7 @@ const char *const *xine_list_post_plugins_typed(xine_t *xine, int type) { plugin_node_t *node; int i; int list_id, list_size; - + pthread_mutex_lock (&catalog->lock); i = 0; @@ -2287,25 +2378,25 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, plugin_node_t *node; post_plugin_t *post = NULL; int list_id, list_size; - + if( !name ) return NULL; - + pthread_mutex_lock(&catalog->lock); - + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_POST - 1]); for (list_id = 0; list_id < list_size; list_id++) { node = xine_sarray_get (catalog->plugin_lists[PLUGIN_POST - 1], list_id); - + if (strcmp(node->info->id, name) == 0) { - + 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); break; } - + post = ((post_class_t *)node->plugin_class)->open_plugin(node->plugin_class, inputs, audio_target, video_target); @@ -2314,12 +2405,12 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, xine_post_out_t *output; xine_list_iterator_t ite; int i; - + post->running_ticket = xine->port_ticket; post->xine = xine; post->node = node; inc_node_ref(node); - + /* init the lists of announced connections */ i = 0; ite = xine_list_front(post->input); @@ -2337,7 +2428,7 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, ite = xine_list_next (post->input, ite); } post->input_ids[i] = NULL; - + i = 0; ite = xine_list_front (post->output); while (ite) { @@ -2354,10 +2445,10 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, ite = xine_list_next (post->output, ite); } post->output_ids[i] = NULL; - + /* copy the post plugin type to the public part */ post->xine_post.type = ((post_info_t *)node->info->special_info)->type; - + break; } else { xprintf(xine, XINE_VERBOSITY_DEBUG, @@ -2366,9 +2457,9 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, } } } - + pthread_mutex_unlock(&catalog->lock); - + if(post) return &post->xine_post; else { @@ -2384,73 +2475,67 @@ void xine_post_dispose(xine_t *xine, xine_post_t *post_gen) { * their disposal if they are still in use => post.c handles the counting for us */ } +/** + * @brief Concantenates an array of strings into a single + * string separated with a given string. + * + * @param strings Array of strings to concatenate. + * @param count Number of elements in the @p strings array. + * @param joining String to use to join the various strings together. + * @param final_length The pre-calculated final length of the string. + */ +static char *_x_concatenate_with_string(char const **strings, size_t count, char *joining, size_t final_length) { + size_t i; + char *const result = malloc(final_length+1); /* Better be safe */ + char *str = result; + + for(i = 0; i < count; i++, strings++) { + if ( *strings ) { + int offset = snprintf(str, final_length, "%s%s", *strings, joining); + str += offset; + final_length -= offset; + } + } + + return result; +} + /* get a list of file extensions for file types supported by xine - * the list is separated by spaces + * the list is separated by spaces * * the pointer returned can be free()ed when no longer used */ char *xine_get_file_extensions (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); - /* calc length of output */ + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **extensions = calloc(list_size, sizeof(char*)); - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *exts; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - if((exts = cls->get_extensions(cls)) && *exts) - len += strlen(exts) + 1; + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (extensions[list_id] = cls->get_extensions(cls)) != NULL ) + len += strlen(extensions[list_id]) +1; } } - /* create output */ - str = malloc (len); /* '\0' space is already counted in the previous loop */ - pos = 0; + /* create output string */ + char *const result = _x_concatenate_with_string(extensions, list_size, " ", len); + free(extensions); - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *e; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { + /* Drop the last whitespace */ + result[len-1] = '\0'; - cls = (demux_class_t *)node->plugin_class; - - if((e = cls->get_extensions (cls)) && *e) { - l = strlen(e); - memcpy (&str[pos], e, l); - - pos += l; - - /* Don't add ' ' char at the end of str */ - if((pos + 1) < len) { - str[pos] = ' '; - pos++; - } - } - } - } - - str[pos] = 0; - pthread_mutex_unlock (&catalog->lock); - return str; + return result; } /* get a list of mime types supported by xine @@ -2459,65 +2544,34 @@ char *xine_get_file_extensions (xine_t *self) { char *xine_get_mime_types (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); /* calc length of output */ - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **mimetypes = calloc(list_size, sizeof(char*)); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); 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); + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (mimetypes[list_id] = cls->get_mimetypes(cls)) != NULL ) + len += strlen(mimetypes[list_id]); } } - /* create output */ - - str = malloc (len+1); - pos = 0; - - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; + /* create output string */ + char *const result = _x_concatenate_with_string(mimetypes, list_size, "", len); + free(mimetypes); - s = cls->get_mimetypes (cls); - if (s) { - l = strlen(s); - memcpy (&str[pos], s, l); - - pos += l; - } - } - } - - str[pos] = 0; - pthread_mutex_unlock (&catalog->lock); - return str; + return result; } @@ -2530,47 +2584,24 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { plugin_catalog_t *catalog = self->plugin_catalog; plugin_node_t *node; char *id = NULL; - char *mime_arg, *mime_demux; - char *s; - const char *mt; int list_id, list_size; - /* create a copy and convert to lower case */ - mime_arg = strdup(mime_type); - for(s=mime_arg; *s; s++) - *s = tolower(*s); - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; (list_id < list_size) && !id; list_id++) { - demux_class_t *cls; node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - mt = cls->get_mimetypes (cls); - if (mt) { - mime_demux = strdup(mt); - - for(s=mime_demux; *s; s++) - *s = tolower(*s); - - if( strstr(mime_demux, mime_arg) ) - id = strdup(node->info->id); - - free(mime_demux); - } + if (probe_mime_type (self, node, mime_type)) + { + free (id); + id = strdup(node->info->id); } } pthread_mutex_unlock (&catalog->lock); - free(mime_arg); - return id; } @@ -2582,7 +2613,7 @@ static void dispose_plugin_list (xine_sarray_t *list) { int list_id, list_size; if (list) { - + list_size = xine_sarray_size (list); for (list_id = 0; list_id < list_size; list_id++) { @@ -2603,12 +2634,12 @@ static void dispose_plugin_list (xine_sarray_t *list) { decoder_info = (decoder_info_t *)node->info->special_info; free (decoder_info->supported_types); - + default: free ((void *)node->info->special_info); break; } - + /* free info structure and string copies */ free (node->info->id); free (node->info); |