diff options
Diffstat (limited to 'src/xine-engine')
-rw-r--r-- | src/xine-engine/Makefile.am | 2 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 11 | ||||
-rw-r--r-- | src/xine-engine/buffer_types.c | 47 | ||||
-rw-r--r-- | src/xine-engine/configfile.c | 358 | ||||
-rw-r--r-- | src/xine-engine/load_plugins.c | 268 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 21 |
6 files changed, 601 insertions, 106 deletions
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index e4c57710a..dcecbfcab 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -35,7 +35,7 @@ libxine_la_LIBADD = $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) $(ZLIB_LIBS) $(LIBXINEPOSIX) $(RT_LIBS) $(NET_LIBS) $(XDG_BASEDIR_LIBS) \ $(AVUTIL_LIBS) -libxine_la_LDFLAGS = $(AM_LDFLAGS) $(def_ldflags) \ +libxine_la_LDFLAGS = $(AM_LDFLAGS) $(def_ldflags) $(GCSECTIONS) \ -version-info $(XINE_LT_CURRENT):$(XINE_LT_REVISION):$(XINE_LT_AGE) $(XINEUTILS_LIB): diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 5162c1883..855051582 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -291,6 +291,7 @@ struct audio_fifo_s { int num_buffers; }; +static int ao_get_property (xine_audio_port_t *this_gen, int property); static int ao_set_property (xine_audio_port_t *this_gen, int property, int value); static audio_fifo_t *fifo_new (xine_t *xine) { @@ -1614,13 +1615,17 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n"); if (this->audio_loop_running) { + /* make sure there are no more buffers on queue */ if (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && !this->slow_fast_audio)) { - /* discard buffers, otherwise we'll wait forever */ + int discard = ao_get_property(this_gen, AO_PROP_DISCARD_BUFFERS); + /* discard buffers while waiting, otherwise we'll wait forever */ ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, 1); + fifo_wait_empty(this->out_fifo); + ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, discard); } - /* make sure there are no more buffers on queue */ - fifo_wait_empty(this->out_fifo); + else + fifo_wait_empty(this->out_fifo); } pthread_mutex_lock( &this->driver_lock ); diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index 08ff194fa..b0e01db31 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -33,6 +33,8 @@ #include <stdlib.h> #include <inttypes.h> #include <xine/buffer.h> +#include <xine/xineutils.h> +#include <xine/xine_internal.h> #include "bswap.h" typedef struct video_db_s { @@ -771,6 +773,14 @@ static const video_db_t video_db[] = { BUF_VIDEO_KMVC, "Karl Morton's Video Codec" }, +{ + { + ME_FOURCC('V','M','n','c'), + 0 + }, + BUF_VIDEO_VMNC, + "VMware Screen Codec" +}, { { 0 }, 0, "last entry" } }; @@ -1201,6 +1211,43 @@ int i; return ""; } + +static void code_to_text (char ascii[5], uint32_t code) +{ + int i; + for (i = 0; i < 4; ++i) + { + int byte = code & 0xFF; + ascii[i] = (byte < ' ') ? ' ' : (byte >= 0x7F) ? '.' : (char) byte; + code >>= 8; + } +} + +void _x_report_video_fourcc (xine_t *xine, const char *module, uint32_t code) +{ + if (code) + { + char ascii[5]; + code_to_text (ascii, code); + xprintf (xine, XINE_VERBOSITY_LOG, + _("%s: unknown video FourCC code %#x \"%s\"\n"), + module, code, ascii); + } +} + +void _x_report_audio_format_tag (xine_t *xine, const char *module, uint32_t code) +{ + if (code) + { + char ascii[5]; + code_to_text (ascii, code); + xprintf (xine, XINE_VERBOSITY_LOG, + _("%s: unknown audio format tag code %#x \"%s\"\n"), + module, code, ascii); + } +} + + void _x_bmiheader_le2me( xine_bmiheader *bih ) { /* OBS: fourcc must be read using machine endianness * so don't play with biCompression here! diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index 3e3c0f7b5..37a4e38ad 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -32,6 +32,8 @@ #include <string.h> #include <unistd.h> #include <xine/configfile.h> +#include "bswap.h" +#include "base64.h" #define LOG_MODULE "configfile" #define LOG_VERBOSE @@ -182,8 +184,6 @@ static const xine_config_entry_translation_t config_entry_translation[] = { { "video.pgx64_overlay_mode", "" }, { "video.pgx64_saturation", "video.output.pgx64_saturation" }, { "video.sdl_hw_accel", "video.device.sdl_hw_accel" }, - { "video.syncfb_default_repeat", "video.device.syncfb_default_repeat" }, - { "video.syncfb_device", "video.device.syncfb_device" }, { "video.unichrome_cpu_save", "video.device.unichrome_cpu_save" }, { "video.vertical_position", "video.output.vertical_position" }, { "video.vidix_blue_intensity", "video.output.vidix_blue_intensity" }, @@ -455,6 +455,8 @@ static void config_reset_value(cfg_entry_t *entry) { entry->num_value = 0; } +static void config_shallow_copy(xine_cfg_entry_t *dest, cfg_entry_t *src); + static cfg_entry_t *config_register_key (config_values_t *this, const char *key, int exp_level, @@ -488,6 +490,14 @@ static cfg_entry_t *config_register_key (config_values_t *this, entry->callback_data = cb_data; } + /* we created a new entry, call the callback */ + if (this->new_entry_cb) { + xine_cfg_entry_t cb_entry; + + config_shallow_copy(&cb_entry, entry); + this->new_entry_cb(this->new_entry_cbdata, &cb_entry); + } + return entry; } @@ -1195,6 +1205,322 @@ static void config_unregister_cb (config_values_t *this, const char *key) { } } +static void config_set_new_entry_callback (config_values_t *this, xine_config_cb_t new_entry_cb, void* cbdata) { + pthread_mutex_lock(&this->config_lock); + this->new_entry_cb = new_entry_cb; + this->new_entry_cbdata = cbdata; + pthread_mutex_unlock(&this->config_lock); +} + +static void config_unset_new_entry_callback (config_values_t *this) { + pthread_mutex_lock(&this->config_lock); + this->new_entry_cb = NULL; + this->new_entry_cbdata = NULL; + pthread_mutex_unlock(&this->config_lock); +} + +static int put_int(uint8_t *buffer, int pos, int value) { + int32_t value_int32 = (int32_t)value; + + buffer[pos] = value_int32 & 0xFF; + buffer[pos + 1] = (value_int32 >> 8) & 0xFF; + buffer[pos + 2] = (value_int32 >> 16) & 0xFF; + buffer[pos + 3] = (value_int32 >> 24) & 0xFF; + + return 4; +} + +static int put_string(uint8_t *buffer, int pos, const char *value, int value_len) { + pos += put_int(buffer, pos, value_len); + memcpy(&buffer[pos], value, value_len); + + return 4 + value_len; +} + +static char* config_get_serialized_entry (config_values_t *this, const char *key) { + char *output = NULL; + cfg_entry_t *entry, *prev; + + pthread_mutex_lock(&this->config_lock); + config_lookup_entry_int(this, key, &entry, &prev); + + if (entry) { + /* now serialize this stuff + fields to serialize : + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key; + char *str_default; + char *description; + char *help; + char **enum_values; + */ + + int key_len = 0; + int str_default_len = 0; + int description_len = 0; + int help_len = 0; + unsigned long output_len; + unsigned long total_len; + int value_count; + int value_len[10]; + int pos = 0; + int i; + + if (entry->key) + key_len = strlen(entry->key); + if (entry->str_default) + str_default_len = strlen(entry->str_default); + if (entry->description) + description_len = strlen(entry->description); + if (entry->help) + help_len = strlen(entry->help); + + /* integers */ + /* value: 4 bytes */ + total_len = 6 * sizeof(int32_t); + + /* strings (size + char buffer) + * length: 4 bytes + * buffer: length bytes + */ + total_len += sizeof(int32_t) + key_len; + total_len += sizeof(int32_t) + str_default_len; + total_len += sizeof(int32_t) + description_len; + total_len += sizeof(int32_t) + help_len; + + /* enum values... + * value count: 4 bytes + * for each value: + * length: 4 bytes + * buffer: length bytes + */ + value_count = 0; + total_len += sizeof(int32_t); /* value count */ + + char **cur_value = entry->enum_values; + if (cur_value) { + while (*cur_value && (value_count < (sizeof(value_len) / sizeof(int) ))) { + value_len[value_count] = strlen(*cur_value); + total_len += sizeof(int32_t) + value_len[value_count]; + value_count++; + cur_value++; + } + } + + /* Now we have the length needed to serialize the entry and the length of each string */ + uint8_t *buffer = malloc (total_len); + if (!buffer) return NULL; + + /* Let's go */ + + /* the integers */ + pos += put_int(buffer, pos, entry->type); + pos += put_int(buffer, pos, entry->range_min); + pos += put_int(buffer, pos, entry->range_max); + pos += put_int(buffer, pos, entry->exp_level); + pos += put_int(buffer, pos, entry->num_default); + pos += put_int(buffer, pos, entry->num_value); + + /* the strings */ + pos += put_string(buffer, pos, entry->key, key_len); + pos += put_string(buffer, pos, entry->str_default, str_default_len); + pos += put_string(buffer, pos, entry->description, description_len); + pos += put_string(buffer, pos, entry->help, help_len); + + /* the enum stuff */ + pos += put_int(buffer, pos, value_count); + cur_value = entry->enum_values; + + for (i = 0; i < value_count; i++) { + pos += put_string(buffer, pos, *cur_value, value_len[i]); + cur_value++; + } + + /* and now the output encoding */ + output = _x_base64_encode (buffer, total_len, &output_len); + + free(buffer); + } + pthread_mutex_unlock(&this->config_lock); + + return output; + +} + +static int get_int(uint8_t *buffer, int buffer_size, int pos, int *value) { + int32_t value_int32; + + if ((pos + sizeof(int32_t)) > buffer_size) + return 0; + + value_int32 = _X_LE_32(&buffer[pos]); + *value = (int)value_int32; + return sizeof(int32_t); +} + +static int get_string(uint8_t *buffer, int buffer_size, int pos, char **value) { + int len; + int bytes = get_int(buffer, buffer_size, pos, &len); + *value = NULL; + + if (!bytes || (len < 0) || (len > 1024*64)) + return 0; + + char *str = malloc(len + 1); + pos += bytes; + memcpy(str, &buffer[pos], len); + str[len] = 0; + + *value = str; + return bytes + len; +} + +static char* config_register_serialized_entry (config_values_t *this, const char *value) { + /* + fields serialized : + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key; + char *str_default; + char *description; + char *help; + char **enum_values; + */ + int type; + int range_min; + int range_max; + int exp_level; + int num_default; + int num_value; + char *key = NULL; + char *str_default = NULL; + char *description = NULL; + char *help = NULL; + char **enum_values = NULL; + + int bytes; + int pos; + void *output = NULL; + unsigned long output_len; + int value_count = 0; + int i; + + output = _x_base64_decode (value, strlen(value), &output_len); + + pos = 0; + pos += bytes = get_int(output, output_len, pos, &type); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &range_min); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &range_max); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &exp_level); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &num_default); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &num_value); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &key); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &str_default); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &description); + if (!bytes) goto exit; + + pos += bytes = get_string(output, output_len, pos, &help); + if (!bytes) goto exit; + + pos += bytes = get_int(output, output_len, pos, &value_count); + if (!bytes) goto exit; + if ((value_count < 0) || (value_count > 256)) goto exit; + + enum_values = malloc (sizeof(void*) * value_count + 1); + for (i = 0; i < value_count; i++) { + pos += bytes = get_string(output, output_len, pos, &enum_values[i]); + if (!bytes) goto exit; + } + enum_values[value_count] = NULL; + +#ifdef LOG + printf("config entry deserialization:\n"); + printf(" key : %s\n", key); + printf(" type : %d\n", type); + printf(" exp_level : %d\n", exp_level); + printf(" num_default: %d\n", num_default); + printf(" num_value : %d\n", num_value); + printf(" str_default: %s\n", str_default); + printf(" range_min : %d\n", range_min); + printf(" range_max : %d\n", range_max); + printf(" description: %s\n", description); + printf(" help : %s\n", help); + printf(" enum : %d values\n", value_count); + + for (i = 0; i < value_count; i++) { + printf(" enum[%2d]: %s\n", i, enum_values[i]); + } + printf("\n"); +#endif + + switch (type) { + case XINE_CONFIG_TYPE_STRING: + switch (num_value) { + case 0: + this->register_string(this, key, str_default, description, help, exp_level, NULL, NULL); + break; + default: + this->register_filename(this, key, str_default, num_value, description, help, exp_level, NULL, NULL); + break; + } + break; + case XINE_CONFIG_TYPE_RANGE: + this->register_range(this, key, num_default, range_min, range_max, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_ENUM: + this->register_enum(this, key, num_default, enum_values, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_NUM: + this->register_num(this, key, num_default, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_BOOL: + this->register_bool(this, key, num_default, description, help, exp_level, NULL, NULL); + break; + case XINE_CONFIG_TYPE_UNKNOWN: + break; + } + +exit: + /* cleanup */ + free(str_default); + free(description); + free(help); + free(output); + + if (enum_values) { + for (i = 0; i < value_count; i++) { + free(enum_values[i]); + } + free(enum_values); + } + + return key; +} config_values_t *_x_config_init (void) { @@ -1221,18 +1547,22 @@ config_values_t *_x_config_init (void) { pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&this->config_lock, &attr); - this->register_string = config_register_string; - this->register_filename = config_register_filename; - this->register_range = config_register_range; - this->register_enum = config_register_enum; - this->register_num = config_register_num; - this->register_bool = config_register_bool; - this->update_num = config_update_num; - this->update_string = config_update_string; - this->parse_enum = config_parse_enum; - this->lookup_entry = config_lookup_entry; - this->unregister_callback = config_unregister_cb; - this->dispose = config_dispose; + this->register_string = config_register_string; + this->register_filename = config_register_filename; + this->register_range = config_register_range; + this->register_enum = config_register_enum; + this->register_num = config_register_num; + this->register_bool = config_register_bool; + this->register_serialized_entry = config_register_serialized_entry; + this->update_num = config_update_num; + this->update_string = config_update_string; + this->parse_enum = config_parse_enum; + this->lookup_entry = config_lookup_entry; + this->unregister_callback = config_unregister_cb; + this->dispose = config_dispose; + this->set_new_entry_callback = config_set_new_entry_callback; + this->unset_new_entry_callback = config_unset_new_entry_callback; + this->get_serialized_entry = config_get_serialized_entry; return this; } diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index b179a135d..8e4a10a60 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -49,6 +49,7 @@ /* #define LOG +#define DEBUG */ #define XINE_ENABLE_EXPERIMENTAL_FEATURES 1 @@ -65,6 +66,8 @@ #include <xine/xineutils.h> #include <xine/compat.h> +#define LINE_MAX_LENGTH (1024 * 32) /* 32 KiB */ + #if 0 static char *plugin_name; @@ -96,7 +99,7 @@ static void remove_segv_handler(void){ #endif #endif /* 0 */ -#define CACHE_CATALOG_VERSION 2 +#define CACHE_CATALOG_VERSION 3 static const int plugin_iface_versions[] = { INPUT_PLUGIN_IFACE_VERSION, @@ -250,26 +253,26 @@ static void _decoder_priority_cb(void *data, xine_cfg_entry_t *cfg) { map_decoders((xine_t *)data); } -static plugin_info_t *_get_cached_info (xine_t *this, +static plugin_node_t *_get_cached_node (xine_t *this, char *filename, off_t filesize, time_t filemtime, - plugin_info_t *previous_info) { + plugin_node_t *previous_node) { xine_sarray_t *list = this->plugin_catalog->cache_list; int list_id, list_size; list_size = xine_sarray_size (list); for (list_id = 0; list_id < list_size; list_id++) { plugin_node_t *node = xine_sarray_get (list, list_id); - if( !previous_info && + if( !previous_node && node->file->filesize == filesize && node->file->filemtime == filemtime && !strcmp( node->file->filename, filename )) { - return node->info; + return node; } /* skip previously returned items */ - if( node->info == previous_info ) - previous_info = NULL; + if( node == previous_node ) + previous_node = NULL; } return NULL; @@ -299,6 +302,7 @@ static plugin_file_t *_insert_file (xine_t *this, static void _insert_node (xine_t *this, xine_sarray_t *list, plugin_file_t *file, + plugin_node_t *node_cache, plugin_info_t *info, int api_version){ @@ -338,6 +342,7 @@ static void _insert_node (xine_t *this, entry->file = file; entry->ref = 0; entry->priority = 0; /* default priority */ + entry->config_entry_list = (node_cache) ? node_cache->config_entry_list : NULL; switch (info->type & PLUGIN_TYPE_MASK){ @@ -480,7 +485,8 @@ static plugin_catalog_t *_new_catalog(void){ return catalog; } -static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin_info_t *info) { +static void _register_plugins_internal(xine_t *this, plugin_file_t *file, + plugin_node_t *node_cache, plugin_info_t *info) { _x_assert(this); _x_assert(info); @@ -506,7 +512,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin int plugin_type = info->type & PLUGIN_TYPE_MASK; if ((plugin_type > 0) && (plugin_type <= PLUGIN_TYPE_MAX)) { - _insert_node (this, this->plugin_catalog->plugin_lists[plugin_type - 1], file, info, + _insert_node (this, this->plugin_catalog->plugin_lists[plugin_type - 1], file, node_cache, info, plugin_iface_versions[plugin_type - 1]); if ((plugin_type == PLUGIN_AUDIO_DECODER) || @@ -530,7 +536,8 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin /* get next info */ if( file && !file->lib_handle ) { lprintf("get cached info\n"); - info = _get_cached_info (this, file->filename, file->filesize, file->filemtime, info); + node_cache = _get_cached_node (this, file->filename, file->filesize, file->filemtime, node_cache); + info = (node_cache) ? node_cache->info : NULL; } else { info++; } @@ -538,7 +545,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin } void xine_register_plugins(xine_t *self, plugin_info_t *info) { - _register_plugins_internal(self, NULL, info); + _register_plugins_internal(self, NULL, NULL, info); } /* @@ -569,6 +576,7 @@ static void collect_plugins(xine_t *this, char *path){ size_t new_str_size, d_len; void *lib = NULL; plugin_info_t *info = NULL; + plugin_node_t *node = NULL; struct stat statbuffer; @@ -611,7 +619,8 @@ static void collect_plugins(xine_t *this, char *path){ lib = NULL; /* get the first plugin_info_t */ - info = _get_cached_info (this, str, statbuffer.st_size, statbuffer.st_mtime, NULL); + node = _get_cached_node (this, str, statbuffer.st_size, statbuffer.st_mtime, NULL); + info = (node) ? node->info : NULL; #ifdef LOG if( info ) printf("load_plugins: using cached %s\n", str); @@ -632,7 +641,7 @@ static void collect_plugins(xine_t *this, char *path){ file = _insert_file(this, this->plugin_catalog->file_list, str, &statbuffer, lib); - _register_plugins_internal(this, file, info); + _register_plugins_internal(this, file, node, info); } else { const char *error = dlerror(); @@ -689,6 +698,25 @@ static inline int _plugin_info_equal(const plugin_info_t *a, return 1; } +static void _attach_entry_to_node (plugin_node_t *node, char *key) { + + if (!node->config_entry_list) { + node->config_entry_list = xine_list_new(); + } + + xine_list_push_back(node->config_entry_list, key); +} + +/* + * This callback is called by the config entry system when a plugin register a + * new config entry. + */ +static void _new_entry_cb (void *user_data, xine_cfg_entry_t *entry) { + plugin_node_t *node = (plugin_node_t *)user_data; + + _attach_entry_to_node(node, strdup(entry->key)); +} + static int _load_plugin_class(xine_t *this, plugin_node_t *node, void *data) { @@ -716,9 +744,17 @@ static int _load_plugin_class(xine_t *this, if ((info = dlsym(node->file->lib_handle, "xine_plugin_info"))) { /* TODO: use sigsegv handler */ - while (info->type != PLUGIN_NONE){ - if (_plugin_info_equal(info, target)){ - if ((node->plugin_class = info->init(this, data))) { + while (info->type != PLUGIN_NONE) { + if (_plugin_info_equal(info, target)) { + config_values_t *config = this->config; + + /* the callback is called for each entry registered by this plugin */ + lprintf("plugin init %s\n", node->info->id); + config->set_new_entry_callback(config, _new_entry_cb, node); + node->plugin_class = info->init(this, data); + config->unset_new_entry_callback(config); + + if (node->plugin_class) { inc_file_ref(node->file); return 1; } else { @@ -797,8 +833,12 @@ static void _load_required_plugins(xine_t *this, xine_sarray_t *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 ) { - + /* + * preload plugins if not cached + */ + if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class && + node->file->lib_handle ) { + lprintf("preload plugin %s from %s\n", node->info->id, node->file->filename); if (! _load_plugin_class (this, node, NULL)) { @@ -827,7 +867,7 @@ static void load_required_plugins(xine_t *this) { /* * save plugin list information to file (cached catalog) */ -static void save_plugin_list(FILE *fp, xine_sarray_t *list) { +static void save_plugin_list(xine_t *this, FILE *fp, xine_sarray_t *list) { const plugin_node_t *node; const plugin_file_t *file; @@ -837,7 +877,6 @@ 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; @@ -854,9 +893,9 @@ 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 ); @@ -884,7 +923,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); @@ -892,10 +931,27 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { case PLUGIN_POST: post_info = node->info->special_info; - fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); - break; - } - + fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); + break; + } + + /* config entries */ + if (node->config_entry_list) { + xine_list_iterator_t ite = xine_list_front(node->config_entry_list); + while (ite) { + char *key = xine_list_get_value(node->config_entry_list, ite); + + /* now serialize the config key */ + char *key_value = this->config->get_serialized_entry(this->config, key); + + lprintf(" config key: %s, serialization: %d bytes\n", key, strlen(key_value)); + fprintf(fp, "config_key=%s\n", key_value); + + free (key_value); + ite = xine_list_next(node->config_entry_list, ite); + } + } + fprintf(fp, "\n"); list_id++; } @@ -904,7 +960,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { /* * load plugin list information from file (cached catalog) */ -static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { +static void load_plugin_list(xine_t *this, FILE *fp, xine_sarray_t *plugins) { plugin_node_t *node; plugin_file_t *file; @@ -917,20 +973,29 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { int i; uint64_t llu; unsigned long lu; - char line[1024]; + char *line; char *value; + size_t line_len; int version_ok = 0; + line = malloc(LINE_MAX_LENGTH); + if (!line) + return; + node = NULL; file = NULL; - while (fgets (line, 1023, fp)) { + while (fgets (line, LINE_MAX_LENGTH, fp)) { if (line[0] == '#') continue; - - if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) - *value = (char) 0; /* eliminate any cr/lf */ + line_len = strlen(line); + if (line_len < 3) + continue; + + value = &line[line_len - 1]; + if( (*value == '\r') || (*value == '\n') ) + *value-- = (char) 0; /* eliminate any cr/lf */ - if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) + if( (*value == '\r') || (*value == '\n') ) *value = (char) 0; /* eliminate any cr/lf */ if (line[0] == '[' && version_ok) { @@ -1005,11 +1070,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { xine_xmalloc(sizeof(decoder_info_t)); break; - case PLUGIN_POST: - node->info->special_info = post_info = - xine_xmalloc(sizeof(post_info_t)); - break; - } + case PLUGIN_POST: + node->info->special_info = post_info = + xine_xmalloc(sizeof(post_info_t)); + break; + } } else if( !strcmp("api",line) ) { sscanf(value," %d",&i); @@ -1050,8 +1115,18 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { sscanf(value," %d",&i); input_info->priority = i; } else if( !strcmp("post_type",line) && post_info ) { - sscanf(value," %lu",&lu); - post_info->type = lu; + sscanf(value," %lu",&lu); + post_info->type = lu; + } else if( !strcmp("config_key",line) ) { + char* cfg_key; + + cfg_key = this->config->register_serialized_entry(this->config, value); + if (cfg_key) { + /* this node is a cached node */ + _attach_entry_to_node(node, cfg_key); + } else { + lprintf("failed to deserialize config entry key\n"); + } } } } @@ -1060,6 +1135,8 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( node ) { xine_sarray_add (plugins, node); } + + free (line); } /** @@ -1132,7 +1209,7 @@ static void save_catalog (xine_t *this) { 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]); + save_plugin_list (this, fp, this->plugin_catalog->plugin_lists[i]); } fclose(fp); } @@ -1149,21 +1226,31 @@ static void load_cached_catalog (xine_t *this) { /* It can't return NULL without creating directories */ if( (fp = fopen(cachefile,"r")) != NULL ) { - load_plugin_list (fp, this->plugin_catalog->cache_list); + load_plugin_list (this, fp, this->plugin_catalog->cache_list); fclose(fp); } free(cachefile); } +/* 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"); @@ -1175,48 +1262,44 @@ void _x_scan_plugins (xine_t *this) { homedir = strdup(xine_get_homedir()); this->plugin_catalog = _new_catalog(); - load_cached_catalog (this); - - if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL) { - pluginpath = strdup(pluginpath); + XINE_PROFILE(load_cached_catalog (this)); + + if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL && *pluginpath) { + char *p = pluginpath - 1; + while (p[1]) + { + char *dir, *q = p; + p = strchr (p + 1, XINE_PATH_SEPARATOR_CHAR); + if (q[0] == '~' && q[1] == '/') + asprintf (&dir, "%s%.*s", homedir, (int)(p - q - 1), q + 1); + else + dir = strndup (q, p - q); + 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); + + XINE_PROFILE(save_catalog (this)); map_decoders (this); } @@ -2604,7 +2687,7 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { } -static void dispose_plugin_list (xine_sarray_t *list) { +static void dispose_plugin_list (xine_sarray_t *list, int is_cache) { plugin_node_t *node; decoder_info_t *decoder_info; @@ -2641,6 +2724,19 @@ static void dispose_plugin_list (xine_sarray_t *list) { /* free info structure and string copies */ free (node->info->id); free (node->info); + + /* don't free the entry list if the node is cache */ + if (!is_cache) { + if (node->config_entry_list) { + xine_list_iterator_t ite = xine_list_front (node->config_entry_list); + while (ite) { + char *key = xine_list_get_value (node->config_entry_list, ite); + free (key); + ite = xine_list_next (node->config_entry_list, ite); + } + xine_list_delete(node->config_entry_list); + } + } free (node); } xine_sarray_delete(list); @@ -2673,10 +2769,10 @@ void _x_dispose_plugins (xine_t *this) { int i; for (i = 0; i < PLUGIN_TYPE_MAX; i++) { - dispose_plugin_list (this->plugin_catalog->plugin_lists[i]); + dispose_plugin_list (this->plugin_catalog->plugin_lists[i], 0); } - dispose_plugin_list (this->plugin_catalog->cache_list); + dispose_plugin_list (this->plugin_catalog->cache_list, 1); dispose_plugin_file_list (this->plugin_catalog->file_list); for (i = 0; this->plugin_catalog->prio_desc[i]; i++) diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 3da311dfc..c6dc8a2ce 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -52,6 +52,7 @@ #define LOG_VERBOSE /* #define LOG +#define DEBUG */ #define XINE_ENABLE_EXPERIMENTAL_FEATURES @@ -822,6 +823,19 @@ void _x_flush_events_queues (xine_stream_t *stream) { pthread_mutex_unlock (&stream->event_queues_lock); } +static inline int _x_path_looks_like_mrl (const char *path) +{ + if ((*path & 0xDF) < 'A' || (*path & 0xDF) > 'Z') + return 0; + + for (++path; *path; ++path) + if ((*path != '-' && *path < '0') || (*path > '9' && *path < 'A') || + (*path > 'Z' && *path < 'a') || *path > 'z') + break; + + return path[0] == ':' && path[1] == '/'; +} + static int open_internal (xine_stream_t *stream, const char *mrl) { const char *stream_setup = NULL; @@ -960,6 +974,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) { memcpy(filename, tmp, strlen(tmp)); filename[strlen(tmp)] = '\0'; } + _x_mrl_unescape(filename); xine_log(stream->xine, XINE_LOG_MSG, _("xine: join rip input plugin\n")); input_saver = _x_rip_plugin_get_instance (stream, filename); @@ -1134,7 +1149,9 @@ static int open_internal (xine_stream_t *stream, const char *mrl) { memcpy(subtitle_mrl, tmp, strlen(tmp)); subtitle_mrl[strlen(tmp)] = '\0'; } - _x_mrl_unescape(subtitle_mrl); + /* unescape for xine_open() if the MRL looks like a raw pathname */ + if (!_x_path_looks_like_mrl(subtitle_mrl)) + _x_mrl_unescape(subtitle_mrl); stream->slave = xine_stream_new (stream->xine, NULL, stream->video_out ); stream->slave_affection = XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP; if( xine_open( stream->slave, subtitle_mrl ) ) { @@ -1683,7 +1700,7 @@ void xine_init (xine_t *this) { /* * plugins */ - _x_scan_plugins(this); + XINE_PROFILE(_x_scan_plugins(this)); #ifdef HAVE_SETLOCALE if (!setlocale(LC_CTYPE, "")) |