diff options
Diffstat (limited to 'src/xine-engine/configfile.c')
-rw-r--r-- | src/xine-engine/configfile.c | 376 |
1 files changed, 358 insertions, 18 deletions
diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index cc53e646c..b334dfaa5 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -32,7 +32,13 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "configfile.h" +#include <xine/configfile.h> +#include "bswap.h" +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <base64.h> +#else +# include <libavutil/base64.h> +#endif #define LOG_MODULE "configfile" #define LOG_VERBOSE @@ -40,8 +46,8 @@ #define LOG */ -#include "xineutils.h" -#include "xine_internal.h" +#include <xine/xineutils.h> +#include <xine/xine_internal.h> static const xine_config_entry_translation_t *config_entry_translation_user = NULL; static const xine_config_entry_translation_t config_entry_translation[] = { @@ -183,8 +189,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" }, @@ -208,7 +212,7 @@ static const xine_config_entry_translation_t config_entry_translation[] = { static int config_section_enum(const char *sect) { - static char *known_section[] = { + static const char *const known_section[] = { "gui", "ui", "audio", @@ -461,6 +465,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, @@ -494,6 +500,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; } @@ -1211,6 +1225,328 @@ 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 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 */ + /* We're going to encode total_len bytes in base64 + * libavutil's base64 encoding functions want the size to + * be at least len * 4 / 3 + 12, so let's use that! + */ + output = malloc(total_len * 4 / 3 + 12); + av_base64_encode(output, total_len * 4 / 3 + 12, buffer, total_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; + size_t output_len; + int value_count = 0; + int i; + + output_len = strlen(value) * 3 / 4 + 1; + output = malloc(output_len); + av_base64_decode(output, 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 = calloc (value_count + 1, sizeof(void*)); + 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) { @@ -1237,18 +1573,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; } |