From 68761b9f3158dda6345060b4cb91cf77cb4fa52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Wed, 4 Apr 2007 22:44:16 +0200 Subject: Rename xine_decoder.c to xine_cmml_decoder.c. Use xineplug_LTLIBRARIES. --HG-- rename : src/libspucmml/xine_decoder.c => src/libspucmml/xine_cmml_decoder.c --- src/libspucmml/Makefile.am | 8 +- src/libspucmml/xine_cmml_decoder.c | 552 +++++++++++++++++++++++++++++++++++++ src/libspucmml/xine_decoder.c | 552 ------------------------------------- 3 files changed, 555 insertions(+), 557 deletions(-) create mode 100644 src/libspucmml/xine_cmml_decoder.c delete mode 100644 src/libspucmml/xine_decoder.c (limited to 'src') diff --git a/src/libspucmml/Makefile.am b/src/libspucmml/Makefile.am index cf9095399..ac2970482 100644 --- a/src/libspucmml/Makefile.am +++ b/src/libspucmml/Makefile.am @@ -1,10 +1,8 @@ include $(top_srcdir)/misc/Makefile.common -libdir = $(XINE_PLUGINDIR) +xineplug_LTLIBRARIES = xineplug_decode_spucmml.la -lib_LTLIBRARIES = xineplug_decode_spucmml.la - -xineplug_decode_spucmml_la_SOURCES = xine_decoder.c +xineplug_decode_spucmml_la_SOURCES = xine_cmml_decoder.c xineplug_decode_spucmml_la_LIBADD = $(XINE_LIB) xineplug_decode_spucmml_la_CFLAGS = $(VISIBILITY_FLAG) -xineplug_decode_spucmml_la_LDFLAGS = -avoid-version -module +xineplug_decode_spucmml_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libspucmml/xine_cmml_decoder.c b/src/libspucmml/xine_cmml_decoder.c new file mode 100644 index 000000000..13cb6c066 --- /dev/null +++ b/src/libspucmml/xine_cmml_decoder.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2000-2003 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_decoder.c,v 1.8 2006/07/10 22:08:30 dgp85 Exp $ + * + */ + +#define LOG_MODULE "libspucmml" +#define LOG_VERBOSE +/* +#define LOG +*/ +#define LOG_OSD 0 +#define LOG_SCHEDULING 0 +#define LOG_WIDTH 0 + +#define SUB_BUFSIZE 1024 +#define SUB_MAX_TEXT 5 + +#include "xine_internal.h" + +typedef enum { + SUBTITLE_SIZE_SMALL = 0, + SUBTITLE_SIZE_NORMAL, + SUBTITLE_SIZE_LARGE, + + SUBTITLE_SIZE_NUM /* number of values in enum */ +} subtitle_size; + + +typedef struct spucmml_class_s { + spu_decoder_class_t class; + char *src_encoding; /* encoding of subtitle file */ + xine_t *xine; + +} spucmml_class_t; + + +typedef struct cmml_anchor_s { + char *text; + char *href; +} cmml_anchor_t; + + +typedef struct spucmml_decoder_s { + spu_decoder_t spu_decoder; + + spucmml_class_t *class; + xine_stream_t *stream; + + xine_event_queue_t *event_queue; + + int lines; + char text[SUB_MAX_TEXT][SUB_BUFSIZE]; + + int cached_width; /* frame width */ + int cached_height; /* frame height */ + int64_t cached_img_duration; + int font_size; + int line_height; + int master_started; + int slave_started; + + char *font; /* subtitle font */ + subtitle_size subtitle_size; /* size of subtitles */ + int vertical_offset; + + osd_object_t *osd; + + cmml_anchor_t current_anchor; +} spucmml_decoder_t; + + +static void video_frame_format_change_callback (void *user_data, const xine_event_t *event); + + +static void update_font_size (spucmml_decoder_t *this) { + static int sizes[SUBTITLE_SIZE_NUM][4] = { + { 16, 16, 16, 20 }, /* SUBTITLE_SIZE_SMALL */ + { 16, 16, 20, 24 }, /* SUBTITLE_SIZE_NORMAL */ + { 16, 20, 24, 32 }, /* SUBTITLE_SIZE_LARGE */ + }; + + int *vec = sizes[this->subtitle_size]; + int y; + + if( this->cached_width >= 512 ) + this->font_size = vec[3]; + else if( this->cached_width >= 384 ) + this->font_size = vec[2]; + else if( this->cached_width >= 320 ) + this->font_size = vec[1]; + else + this->font_size = vec[0]; + + this->line_height = this->font_size + 10; + + y = this->cached_height - (SUB_MAX_TEXT * this->line_height) - 5; + + if(((y - this->vertical_offset) >= 0) && ((y - this->vertical_offset) <= this->cached_height)) + y -= this->vertical_offset; + + /* TODO: we should move this stuff below into another function */ + + if (this->osd) + this->stream->osd_renderer->free_object (this->osd); + + llprintf (LOG_OSD, + "pre new_object: osd=%p, osd_renderer=%p, width=%d, height=%d\n", + this->osd, + this->stream->osd_renderer, + this->cached_width, + SUB_MAX_TEXT * this->line_height); + + this->osd = this->stream->osd_renderer->new_object (this->stream->osd_renderer, + this->cached_width, SUB_MAX_TEXT * this->line_height); + + llprintf (LOG_OSD, "post new_object: osd is %p\n", this->osd); + + if(this->stream->osd_renderer) { + this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); + this->stream->osd_renderer->set_position (this->osd, 0, y); + } +} + +static int get_width(spucmml_decoder_t *this, char* text) { + size_t i=0; + int width=0,w,dummy; + char letter[2]={0, 0}; + + while (i<=strlen(text)) { + switch (text[i]) { + case '<': + if (!strncmp("", text+i, 3)) { + /*Do somethink to enable BOLD typeface*/ + i=i+3; + break; + } else if (!strncmp("", text+i, 3)) { + /*Do somethink to disable BOLD typeface*/ + i=i+4; + break; + } else if (!strncmp("", text+i, 3)) { + /*Do somethink to enable italics typeface*/ + i=i+3; + break; + } else if (!strncmp("", text+i, 3)) { + /*Do somethink to disable italics typeface*/ + i=i+4; + break; + } else if (!strncmp("", text+i, 3)) { + /*Do somethink to disable typing + fixme - no teststreams*/ + i=i+6; + break; + } else if (!strncmp("", text+i, 3)) { + /*Do somethink to enable typing + fixme - no teststreams*/ + i=i+7; + break; + } + default: + letter[0]=text[i]; + this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); + width=width+w; + i++; + } + } + + llprintf(LOG_WIDTH, "get_width returning width of %d\n", width); + + return width; +} + +static void render_line(spucmml_decoder_t *this, int x, int y, char* text) { + size_t i=0; + int w,dummy; + char letter[2]={0,0}; + + while (i<=strlen(text)) { + letter[0]=text[i]; + this->stream->osd_renderer->render_text(this->osd, x, y, letter, OSD_TEXT1); + this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); + x=x+w; + i++; + } +} + +static void draw_subtitle(spucmml_decoder_t *this, int64_t sub_start) { + + int line, y; + int font_size; + + this->stream->osd_renderer->filled_rect (this->osd, 0, 0, + this->cached_width-1, this->line_height * SUB_MAX_TEXT - 1, 0); + + y = (SUB_MAX_TEXT - this->lines) * this->line_height; + font_size = this->font_size; + this->stream->osd_renderer->set_encoding(this->osd, this->class->src_encoding); + + for (line=0; linelines; line++) { + int w,x; + while(1) { + w=get_width( this, this->text[line]); + x = (this->cached_width - w) / 2; + + if( w > this->cached_width && font_size > 16 ) { + font_size -= 4; + this->stream->osd_renderer->set_font (this->osd, this->font, font_size); + } else { + break; + } + } + render_line(this, x, y + line*this->line_height, this->text[line]); + } + + if( font_size != this->font_size ) + this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); + + + this->stream->osd_renderer->set_text_palette (this->osd, -1, OSD_TEXT1); + this->stream->osd_renderer->show (this->osd, sub_start); + + llprintf (LOG_SCHEDULING, + "spucmml: scheduling subtitle >%s< at %"PRId64", current time is %"PRId64"\n", + this->text[0], sub_start, + this->stream->xine->clock->get_current_time (this->stream->xine->clock)); +} + +static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { + + spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; + char *str; + + xml_node_t *packet_xml_root; + char * anchor_text = NULL; + + lprintf("CMML packet seen\n"); + + str = (char *) buf->content; + + /* parse the CMML */ + + xml_parser_init (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree(&packet_xml_root) != XML_PARSER_OK) { + lprintf ("warning: invalid XML packet detected in CMML track\n"); + return; + } + + if (strcasecmp(packet_xml_root->name, "head") == 0) { + /* found a ... packet: need to parse the title */ + + xml_node_t *title_node; + + /* iterate through children trying to find the title node */ + + for (title_node = packet_xml_root->child; title_node != NULL; title_node = title_node->next) { + + if (strcasecmp (title_node->name, "title") == 0) { + /* found a title node */ + + xine_event_t uevent; + char *title; + int title_len; + + title = title_node->data; + + if (title) + { + xine_ui_data_t data; + /* found a non-empty title */ + lprintf ("found title: \"%s\"\n", title); + + /* set xine meta-info */ + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, strdup(title)); + + /* and push out a new event signifying the title update on the event + * queue */ + title_len = strlen(title) + 1; + memcpy(data.str, title, title_len); + data.str_len = title_len; + + uevent.type = XINE_EVENT_UI_SET_TITLE; + uevent.stream = this->stream; + uevent.data = &data; + uevent.data_length = sizeof(data); + xine_event_send(this->stream, &uevent); + } + } + } + } else if (strcasecmp(packet_xml_root->name, "clip") == 0) { + /* found a ... packet: search for the in it */ + xml_node_t *clip_node; + + /* iterate through each tag contained in the tag to look for */ + + for (clip_node = packet_xml_root->child; clip_node != NULL; clip_node = clip_node->next) { + + if (strcasecmp (clip_node->name, "a") == 0) { + xml_property_t *href_property; + + /* found the tag: grab its value and its href property */ + + if (clip_node->data) + anchor_text = strdup (clip_node->data); + + for (href_property = clip_node->props; href_property != NULL; href_property = href_property->next) { + if (strcasecmp (href_property->name, "href") == 0) { + /* found the href property */ + char *href = href_property->value; + + if (href) { + lprintf ("found href: \"%s\"\n", href); + this->current_anchor.href = strdup(href); + } + } + } + } + } + } + + /* finish here if we don't have to process any anchor text */ + if (!anchor_text) + return; + + /* how many lines does the anchor text take up? */ + this->lines=0; + { + int i = 0; + while (*anchor_text) { + if (*anchor_text == '\r' || *anchor_text == '\n') { + if (i) { + /* match a newline and there are chars on the current line ... */ + this->text[ this->lines ][i] = '\0'; + this->lines++; + i = 0; + } + } else { + /* found a normal (non-line-ending) character */ + this->text[ this->lines ][i] = *anchor_text; + if (itext[ this->lines ][i] = '\0'; + this->lines++; + } + } + + /* initialize decoder if needed */ + if( !this->cached_width || !this->cached_height || !this->cached_img_duration || !this->osd ) { + if( this->stream->video_out->status(this->stream->video_out, NULL, + &this->cached_width, &this->cached_height, &this->cached_img_duration )) { + if( this->cached_width && this->cached_height && this->cached_img_duration ) { + lprintf("this->stream->osd_renderer is %p\n", this->stream->osd_renderer); + } + } + } + + update_font_size (this); + + if( this->osd ) { + draw_subtitle(this, buf->pts); + return; + } else { + lprintf ("libspucmml: no osd\n"); + } + + return; +} + +static void video_frame_format_change_callback (void *user_data, const xine_event_t *event) +{ + /* this doesn't do anything for now: it's a start at attempting to display + * CMML clips which occur at 0 seconds into the track. see + * + * http://marc.theaimsgroup.com/?l=xine-devel&m=109202443013890&w=2 + * + * for a description of the problem. */ + + switch (event->type) { + case XINE_EVENT_FRAME_FORMAT_CHANGE: + lprintf("video_frame_format_change_callback called!\n"); + break; + default: + lprintf("video_frame_format_change_callback called with unknown event %d\n", event->type); + break; + } +} + +static void spudec_reset (spu_decoder_t *this_gen) { + spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; + + this->cached_width = this->cached_height = 0; +} + +static void spudec_discontinuity (spu_decoder_t *this_gen) { + /* do nothing */ +} + +static void spudec_dispose (spu_decoder_t *this_gen) { + spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; + + if (this->event_queue) + xine_event_dispose_queue (this->event_queue); + + if (this->osd) { + this->stream->osd_renderer->free_object (this->osd); + this->osd = NULL; + } + free(this); +} + +static void update_vertical_offset(void *this_gen, xine_cfg_entry_t *entry) +{ + spucmml_decoder_t *this = (spucmml_decoder_t *)this_gen; + + this->vertical_offset = entry->num_value; + update_font_size(this); +} + +static void update_osd_font(void *this_gen, xine_cfg_entry_t *entry) +{ + spucmml_decoder_t *this = (spucmml_decoder_t *)this_gen; + + this->font = entry->str_value; + + if( this->stream->osd_renderer ) + this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); +} + +static spu_decoder_t *spucmml_class_open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) { + + spucmml_class_t *class = (spucmml_class_t *)class_gen; + spucmml_decoder_t *this ; + + this = (spucmml_decoder_t *) xine_xmalloc (sizeof (spucmml_decoder_t)); + + this->spu_decoder.decode_data = spudec_decode_data; + this->spu_decoder.reset = spudec_reset; + this->spu_decoder.discontinuity = spudec_discontinuity; + this->spu_decoder.dispose = spudec_dispose; + this->spu_decoder.get_interact_info = NULL; + this->spu_decoder.set_button = NULL; + this->spu_decoder.dispose = spudec_dispose; + + this->class = class; + this->stream = stream; + + this->event_queue = xine_event_new_queue (this->stream); + xine_event_create_listener_thread (this->event_queue, + video_frame_format_change_callback, + this); + + this->font_size = 24; + this->subtitle_size = 1; + + this->font = class->xine->config->register_string(class->xine->config, + "subtitles.separate.font", + "sans", + _("font for external subtitles"), + NULL, 0, update_osd_font, this); + + this->vertical_offset = class->xine->config->register_num(class->xine->config, + "subtitles.separate.vertical_offset", + 0, + _("subtitle vertical offset (relative window size)"), + NULL, 0, update_vertical_offset, this); + + this->current_anchor.href = NULL; + + lprintf ("video_out is at %p\n", this->stream->video_out); + + return (spu_decoder_t *) this; +} + +static void spucmml_class_dispose (spu_decoder_class_t *this) { + free (this); +} + +static char *spucmml_class_get_identifier (spu_decoder_class_t *this) { + return "spucmml"; +} + +static char *spucmml_class_get_description (spu_decoder_class_t *this) { + return "CMML subtitle decoder plugin"; +} + +static void update_src_encoding(void *this_gen, xine_cfg_entry_t *entry) +{ + spucmml_class_t *this = (spucmml_class_t *)this_gen; + + this->src_encoding = entry->str_value; + printf("libspucmml: spu_src_encoding = %s\n", this->src_encoding ); +} + +static void *init_spu_decoder_plugin (xine_t *xine, void *data) { + + spucmml_class_t *this ; + + this = (spucmml_class_t *) xine_xmalloc (sizeof (spucmml_class_t)); + + this->class.open_plugin = spucmml_class_open_plugin; + this->class.get_identifier = spucmml_class_get_identifier; + this->class.get_description = spucmml_class_get_description; + this->class.dispose = spucmml_class_dispose; + + this->xine = xine; + + this->src_encoding = xine->config->register_string(xine->config, + "subtitles.separate.src_encoding", + "iso-8859-1", + _("encoding of subtitles"), + NULL, 10, update_src_encoding, this); + + return &this->class; +} + + +/* plugin catalog information */ +static uint32_t supported_types[] = { BUF_SPU_CMML, 0 }; + +static const decoder_info_t spudec_info = { + supported_types, /* supported types */ + 1 /* priority */ +}; + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_SPU_DECODER, 16, "spucmml", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + diff --git a/src/libspucmml/xine_decoder.c b/src/libspucmml/xine_decoder.c deleted file mode 100644 index 13cb6c066..000000000 --- a/src/libspucmml/xine_decoder.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * $Id: xine_decoder.c,v 1.8 2006/07/10 22:08:30 dgp85 Exp $ - * - */ - -#define LOG_MODULE "libspucmml" -#define LOG_VERBOSE -/* -#define LOG -*/ -#define LOG_OSD 0 -#define LOG_SCHEDULING 0 -#define LOG_WIDTH 0 - -#define SUB_BUFSIZE 1024 -#define SUB_MAX_TEXT 5 - -#include "xine_internal.h" - -typedef enum { - SUBTITLE_SIZE_SMALL = 0, - SUBTITLE_SIZE_NORMAL, - SUBTITLE_SIZE_LARGE, - - SUBTITLE_SIZE_NUM /* number of values in enum */ -} subtitle_size; - - -typedef struct spucmml_class_s { - spu_decoder_class_t class; - char *src_encoding; /* encoding of subtitle file */ - xine_t *xine; - -} spucmml_class_t; - - -typedef struct cmml_anchor_s { - char *text; - char *href; -} cmml_anchor_t; - - -typedef struct spucmml_decoder_s { - spu_decoder_t spu_decoder; - - spucmml_class_t *class; - xine_stream_t *stream; - - xine_event_queue_t *event_queue; - - int lines; - char text[SUB_MAX_TEXT][SUB_BUFSIZE]; - - int cached_width; /* frame width */ - int cached_height; /* frame height */ - int64_t cached_img_duration; - int font_size; - int line_height; - int master_started; - int slave_started; - - char *font; /* subtitle font */ - subtitle_size subtitle_size; /* size of subtitles */ - int vertical_offset; - - osd_object_t *osd; - - cmml_anchor_t current_anchor; -} spucmml_decoder_t; - - -static void video_frame_format_change_callback (void *user_data, const xine_event_t *event); - - -static void update_font_size (spucmml_decoder_t *this) { - static int sizes[SUBTITLE_SIZE_NUM][4] = { - { 16, 16, 16, 20 }, /* SUBTITLE_SIZE_SMALL */ - { 16, 16, 20, 24 }, /* SUBTITLE_SIZE_NORMAL */ - { 16, 20, 24, 32 }, /* SUBTITLE_SIZE_LARGE */ - }; - - int *vec = sizes[this->subtitle_size]; - int y; - - if( this->cached_width >= 512 ) - this->font_size = vec[3]; - else if( this->cached_width >= 384 ) - this->font_size = vec[2]; - else if( this->cached_width >= 320 ) - this->font_size = vec[1]; - else - this->font_size = vec[0]; - - this->line_height = this->font_size + 10; - - y = this->cached_height - (SUB_MAX_TEXT * this->line_height) - 5; - - if(((y - this->vertical_offset) >= 0) && ((y - this->vertical_offset) <= this->cached_height)) - y -= this->vertical_offset; - - /* TODO: we should move this stuff below into another function */ - - if (this->osd) - this->stream->osd_renderer->free_object (this->osd); - - llprintf (LOG_OSD, - "pre new_object: osd=%p, osd_renderer=%p, width=%d, height=%d\n", - this->osd, - this->stream->osd_renderer, - this->cached_width, - SUB_MAX_TEXT * this->line_height); - - this->osd = this->stream->osd_renderer->new_object (this->stream->osd_renderer, - this->cached_width, SUB_MAX_TEXT * this->line_height); - - llprintf (LOG_OSD, "post new_object: osd is %p\n", this->osd); - - if(this->stream->osd_renderer) { - this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); - this->stream->osd_renderer->set_position (this->osd, 0, y); - } -} - -static int get_width(spucmml_decoder_t *this, char* text) { - size_t i=0; - int width=0,w,dummy; - char letter[2]={0, 0}; - - while (i<=strlen(text)) { - switch (text[i]) { - case '<': - if (!strncmp("", text+i, 3)) { - /*Do somethink to enable BOLD typeface*/ - i=i+3; - break; - } else if (!strncmp("", text+i, 3)) { - /*Do somethink to disable BOLD typeface*/ - i=i+4; - break; - } else if (!strncmp("", text+i, 3)) { - /*Do somethink to enable italics typeface*/ - i=i+3; - break; - } else if (!strncmp("", text+i, 3)) { - /*Do somethink to disable italics typeface*/ - i=i+4; - break; - } else if (!strncmp("", text+i, 3)) { - /*Do somethink to disable typing - fixme - no teststreams*/ - i=i+6; - break; - } else if (!strncmp("", text+i, 3)) { - /*Do somethink to enable typing - fixme - no teststreams*/ - i=i+7; - break; - } - default: - letter[0]=text[i]; - this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); - width=width+w; - i++; - } - } - - llprintf(LOG_WIDTH, "get_width returning width of %d\n", width); - - return width; -} - -static void render_line(spucmml_decoder_t *this, int x, int y, char* text) { - size_t i=0; - int w,dummy; - char letter[2]={0,0}; - - while (i<=strlen(text)) { - letter[0]=text[i]; - this->stream->osd_renderer->render_text(this->osd, x, y, letter, OSD_TEXT1); - this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); - x=x+w; - i++; - } -} - -static void draw_subtitle(spucmml_decoder_t *this, int64_t sub_start) { - - int line, y; - int font_size; - - this->stream->osd_renderer->filled_rect (this->osd, 0, 0, - this->cached_width-1, this->line_height * SUB_MAX_TEXT - 1, 0); - - y = (SUB_MAX_TEXT - this->lines) * this->line_height; - font_size = this->font_size; - this->stream->osd_renderer->set_encoding(this->osd, this->class->src_encoding); - - for (line=0; linelines; line++) { - int w,x; - while(1) { - w=get_width( this, this->text[line]); - x = (this->cached_width - w) / 2; - - if( w > this->cached_width && font_size > 16 ) { - font_size -= 4; - this->stream->osd_renderer->set_font (this->osd, this->font, font_size); - } else { - break; - } - } - render_line(this, x, y + line*this->line_height, this->text[line]); - } - - if( font_size != this->font_size ) - this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); - - - this->stream->osd_renderer->set_text_palette (this->osd, -1, OSD_TEXT1); - this->stream->osd_renderer->show (this->osd, sub_start); - - llprintf (LOG_SCHEDULING, - "spucmml: scheduling subtitle >%s< at %"PRId64", current time is %"PRId64"\n", - this->text[0], sub_start, - this->stream->xine->clock->get_current_time (this->stream->xine->clock)); -} - -static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { - - spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; - char *str; - - xml_node_t *packet_xml_root; - char * anchor_text = NULL; - - lprintf("CMML packet seen\n"); - - str = (char *) buf->content; - - /* parse the CMML */ - - xml_parser_init (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); - if (xml_parser_build_tree(&packet_xml_root) != XML_PARSER_OK) { - lprintf ("warning: invalid XML packet detected in CMML track\n"); - return; - } - - if (strcasecmp(packet_xml_root->name, "head") == 0) { - /* found a ... packet: need to parse the title */ - - xml_node_t *title_node; - - /* iterate through children trying to find the title node */ - - for (title_node = packet_xml_root->child; title_node != NULL; title_node = title_node->next) { - - if (strcasecmp (title_node->name, "title") == 0) { - /* found a title node */ - - xine_event_t uevent; - char *title; - int title_len; - - title = title_node->data; - - if (title) - { - xine_ui_data_t data; - /* found a non-empty title */ - lprintf ("found title: \"%s\"\n", title); - - /* set xine meta-info */ - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, strdup(title)); - - /* and push out a new event signifying the title update on the event - * queue */ - title_len = strlen(title) + 1; - memcpy(data.str, title, title_len); - data.str_len = title_len; - - uevent.type = XINE_EVENT_UI_SET_TITLE; - uevent.stream = this->stream; - uevent.data = &data; - uevent.data_length = sizeof(data); - xine_event_send(this->stream, &uevent); - } - } - } - } else if (strcasecmp(packet_xml_root->name, "clip") == 0) { - /* found a ... packet: search for the in it */ - xml_node_t *clip_node; - - /* iterate through each tag contained in the tag to look for */ - - for (clip_node = packet_xml_root->child; clip_node != NULL; clip_node = clip_node->next) { - - if (strcasecmp (clip_node->name, "a") == 0) { - xml_property_t *href_property; - - /* found the tag: grab its value and its href property */ - - if (clip_node->data) - anchor_text = strdup (clip_node->data); - - for (href_property = clip_node->props; href_property != NULL; href_property = href_property->next) { - if (strcasecmp (href_property->name, "href") == 0) { - /* found the href property */ - char *href = href_property->value; - - if (href) { - lprintf ("found href: \"%s\"\n", href); - this->current_anchor.href = strdup(href); - } - } - } - } - } - } - - /* finish here if we don't have to process any anchor text */ - if (!anchor_text) - return; - - /* how many lines does the anchor text take up? */ - this->lines=0; - { - int i = 0; - while (*anchor_text) { - if (*anchor_text == '\r' || *anchor_text == '\n') { - if (i) { - /* match a newline and there are chars on the current line ... */ - this->text[ this->lines ][i] = '\0'; - this->lines++; - i = 0; - } - } else { - /* found a normal (non-line-ending) character */ - this->text[ this->lines ][i] = *anchor_text; - if (itext[ this->lines ][i] = '\0'; - this->lines++; - } - } - - /* initialize decoder if needed */ - if( !this->cached_width || !this->cached_height || !this->cached_img_duration || !this->osd ) { - if( this->stream->video_out->status(this->stream->video_out, NULL, - &this->cached_width, &this->cached_height, &this->cached_img_duration )) { - if( this->cached_width && this->cached_height && this->cached_img_duration ) { - lprintf("this->stream->osd_renderer is %p\n", this->stream->osd_renderer); - } - } - } - - update_font_size (this); - - if( this->osd ) { - draw_subtitle(this, buf->pts); - return; - } else { - lprintf ("libspucmml: no osd\n"); - } - - return; -} - -static void video_frame_format_change_callback (void *user_data, const xine_event_t *event) -{ - /* this doesn't do anything for now: it's a start at attempting to display - * CMML clips which occur at 0 seconds into the track. see - * - * http://marc.theaimsgroup.com/?l=xine-devel&m=109202443013890&w=2 - * - * for a description of the problem. */ - - switch (event->type) { - case XINE_EVENT_FRAME_FORMAT_CHANGE: - lprintf("video_frame_format_change_callback called!\n"); - break; - default: - lprintf("video_frame_format_change_callback called with unknown event %d\n", event->type); - break; - } -} - -static void spudec_reset (spu_decoder_t *this_gen) { - spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; - - this->cached_width = this->cached_height = 0; -} - -static void spudec_discontinuity (spu_decoder_t *this_gen) { - /* do nothing */ -} - -static void spudec_dispose (spu_decoder_t *this_gen) { - spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; - - if (this->event_queue) - xine_event_dispose_queue (this->event_queue); - - if (this->osd) { - this->stream->osd_renderer->free_object (this->osd); - this->osd = NULL; - } - free(this); -} - -static void update_vertical_offset(void *this_gen, xine_cfg_entry_t *entry) -{ - spucmml_decoder_t *this = (spucmml_decoder_t *)this_gen; - - this->vertical_offset = entry->num_value; - update_font_size(this); -} - -static void update_osd_font(void *this_gen, xine_cfg_entry_t *entry) -{ - spucmml_decoder_t *this = (spucmml_decoder_t *)this_gen; - - this->font = entry->str_value; - - if( this->stream->osd_renderer ) - this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); -} - -static spu_decoder_t *spucmml_class_open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) { - - spucmml_class_t *class = (spucmml_class_t *)class_gen; - spucmml_decoder_t *this ; - - this = (spucmml_decoder_t *) xine_xmalloc (sizeof (spucmml_decoder_t)); - - this->spu_decoder.decode_data = spudec_decode_data; - this->spu_decoder.reset = spudec_reset; - this->spu_decoder.discontinuity = spudec_discontinuity; - this->spu_decoder.dispose = spudec_dispose; - this->spu_decoder.get_interact_info = NULL; - this->spu_decoder.set_button = NULL; - this->spu_decoder.dispose = spudec_dispose; - - this->class = class; - this->stream = stream; - - this->event_queue = xine_event_new_queue (this->stream); - xine_event_create_listener_thread (this->event_queue, - video_frame_format_change_callback, - this); - - this->font_size = 24; - this->subtitle_size = 1; - - this->font = class->xine->config->register_string(class->xine->config, - "subtitles.separate.font", - "sans", - _("font for external subtitles"), - NULL, 0, update_osd_font, this); - - this->vertical_offset = class->xine->config->register_num(class->xine->config, - "subtitles.separate.vertical_offset", - 0, - _("subtitle vertical offset (relative window size)"), - NULL, 0, update_vertical_offset, this); - - this->current_anchor.href = NULL; - - lprintf ("video_out is at %p\n", this->stream->video_out); - - return (spu_decoder_t *) this; -} - -static void spucmml_class_dispose (spu_decoder_class_t *this) { - free (this); -} - -static char *spucmml_class_get_identifier (spu_decoder_class_t *this) { - return "spucmml"; -} - -static char *spucmml_class_get_description (spu_decoder_class_t *this) { - return "CMML subtitle decoder plugin"; -} - -static void update_src_encoding(void *this_gen, xine_cfg_entry_t *entry) -{ - spucmml_class_t *this = (spucmml_class_t *)this_gen; - - this->src_encoding = entry->str_value; - printf("libspucmml: spu_src_encoding = %s\n", this->src_encoding ); -} - -static void *init_spu_decoder_plugin (xine_t *xine, void *data) { - - spucmml_class_t *this ; - - this = (spucmml_class_t *) xine_xmalloc (sizeof (spucmml_class_t)); - - this->class.open_plugin = spucmml_class_open_plugin; - this->class.get_identifier = spucmml_class_get_identifier; - this->class.get_description = spucmml_class_get_description; - this->class.dispose = spucmml_class_dispose; - - this->xine = xine; - - this->src_encoding = xine->config->register_string(xine->config, - "subtitles.separate.src_encoding", - "iso-8859-1", - _("encoding of subtitles"), - NULL, 10, update_src_encoding, this); - - return &this->class; -} - - -/* plugin catalog information */ -static uint32_t supported_types[] = { BUF_SPU_CMML, 0 }; - -static const decoder_info_t spudec_info = { - supported_types, /* supported types */ - 1 /* priority */ -}; - -const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_SPU_DECODER, 16, "spucmml", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; - -- cgit v1.2.3