summaryrefslogtreecommitdiff
path: root/src/xine-engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine')
-rw-r--r--src/xine-engine/Makefile.am2
-rw-r--r--src/xine-engine/audio_out.c11
-rw-r--r--src/xine-engine/buffer_types.c47
-rw-r--r--src/xine-engine/configfile.c358
-rw-r--r--src/xine-engine/load_plugins.c268
-rw-r--r--src/xine-engine/xine.c21
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, ""))