diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | mplayer.c | 4 | ||||
-rw-r--r-- | sub/subassconvert.c | 502 | ||||
-rw-r--r-- | sub/subassconvert.h | 27 | ||||
-rw-r--r-- | subreader.c | 152 | ||||
-rw-r--r-- | subreader.h | 4 |
6 files changed, 669 insertions, 21 deletions
@@ -517,6 +517,7 @@ SRCS_COMMON = asxparser.c \ stream/stream_null.c \ stream/url.c \ sub/dec_sub.c \ + sub/subassconvert.c \ $(SRCS_COMMON-yes) @@ -1105,7 +1105,7 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr asst = ass_read_stream(ass_library, filename, 0); #endif if (!asst) { - subd = sub_read_file(filename, fps); + subd = sub_read_file(filename, fps, &mpctx->opts); if (subd) { asst = ass_read_subdata(ass_library, subd, fps); if (asst) { @@ -1116,7 +1116,7 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr } } else #endif - subd = sub_read_file(filename, fps); + subd = sub_read_file(filename, fps, &mpctx->opts); if (!asst && !subd) { diff --git a/sub/subassconvert.c b/sub/subassconvert.c new file mode 100644 index 0000000000..773cb7f4d7 --- /dev/null +++ b/sub/subassconvert.c @@ -0,0 +1,502 @@ +/* + * Subtitles converter to SSA/ASS in order to allow special formatting + * + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> + +#include "mp_msg.h" +#include "subassconvert.h" +#include "bstr.h" +#include "libavutil/common.h" + +struct line { + char *buf; + int bufsize; + int len; +}; + +#ifdef __GNUC__ +static void append_text(struct line *dst, char *fmt, ...) __attribute__ ((format(printf, 2, 3))); +#endif + +static void append_text(struct line *dst, char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + int ret = vsnprintf(dst->buf + dst->len, dst->bufsize - dst->len, fmt, va); + if (ret < 0) + goto out; + dst->len += ret; + if (dst->len > dst->bufsize) + dst->len = dst->bufsize; + out: + va_end(va); +} + +static int indexof(const char *s, int c) +{ + char *f = strchr(s, c); + return f ? (f - s) : -1; +} + + + +/* + * SubRip + * + * Support basic tags (italic, bold, underline, strike-through) + * and font tag with size, color and face attributes. + * + */ + +struct font_tag { + int size; + uint32_t color; + struct bstr face; + bool has_size : 1; + bool has_color : 1; + bool has_face : 1; +}; + +static const struct tag_conv { + char *from; + char *to; +} subrip_basic_tags[] = { + {"<i>", "{\\i1}"}, {"</i>", "{\\i0}"}, + {"<b>", "{\\b1}"}, {"</b>", "{\\b0}"}, + {"<u>", "{\\u1}"}, {"</u>", "{\\u0}"}, + {"<s>", "{\\s1}"}, {"</s>", "{\\s0}"}, + {"{", "\\{"}, {"}", "\\}"}, + {"\n", "\\N"} +}; + +static const struct { + char *s; + uint32_t v; +} subrip_web_colors[] = { + /* 16 named HTML colors in BGR format */ + {"red", 0x0000ff}, {"blue", 0xff0000}, {"lime", 0x00ff00}, + {"aqua", 0xffff00}, {"purple", 0x800080}, {"yellow", 0x00ffff}, + {"fuchsia", 0xff00ff}, {"white", 0xffffff}, {"gray", 0x808080}, + {"maroon", 0x000080}, {"olive", 0x008080}, {"black", 0x000000}, + {"silver", 0xc0c0c0}, {"teal", 0x808000}, {"green", 0x008000}, + {"navy", 0x800000} +}; + +#define SUBRIP_MAX_STACKED_FONT_TAGS 16 + +void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size) +{ + /* line is not const to avoid warnings with strtol, etc. + * orig content won't be changed */ + char *line = (char *)orig; + struct line new_line = { + .buf = dest, + .bufsize = dest_buffer_size, + }; + struct font_tag font_stack[SUBRIP_MAX_STACKED_FONT_TAGS + 1]; + font_stack[0] = (struct font_tag){0}; // type with all defaults + int sp = 0; + + while (*line && new_line.len < new_line.bufsize - 1) { + char *orig_line = line; + + for (int i = 0; i < FF_ARRAY_ELEMS(subrip_basic_tags); i++) { + const struct tag_conv *tag = &subrip_basic_tags[i]; + int from_len = strlen(tag->from); + if (strncmp(line, tag->from, from_len) == 0) { + append_text(&new_line, "%s", tag->to); + line += from_len; + } + } + + if (strncmp(line, "</font>", 7) == 0) { + /* Closing font tag */ + line += 7; + + if (sp > 0) { + struct font_tag *tag = &font_stack[sp]; + struct font_tag *last_tag = &tag[-1]; + sp--; + + if (tag->has_size) { + if (!last_tag->has_size) + append_text(&new_line, "{\\fs}"); + else if (last_tag->size != tag->size) + append_text(&new_line, "{\\fs%d}", last_tag->size); + } + + if (tag->has_color) { + if (!last_tag->has_color) + append_text(&new_line, "{\\c}"); + else if (last_tag->color != tag->color) + append_text(&new_line, "{\\c&H%06X&}", last_tag->color); + } + + if (tag->has_face) { + if (!last_tag->has_face) + append_text(&new_line, "{\\fn}"); + else if (bstrcmp(last_tag->face, tag->face) != 0) + append_text(&new_line, "{\\fn%.*s}", + BSTR_P(last_tag->face)); + } + } + } else if (strncmp(line, "<font ", 6) == 0 + && sp + 1 < FF_ARRAY_ELEMS(font_stack)) { + /* Opening font tag */ + char *potential_font_tag_start = line; + int len_backup = new_line.len; + struct font_tag *tag = &font_stack[sp + 1]; + bool has_valid_attr = false; + + *tag = tag[-1]; // keep values from previous tag + line += 6; + + while (*line && *line != '>') { + if (strncmp(line, "size=\"", 6) == 0) { + line += 6; + tag->size = strtol(line, &line, 10); + if (*line != '"') + break; + append_text(&new_line, "{\\fs%d}", tag->size); + tag->has_size = true; + has_valid_attr = true; + } else if (strncmp(line, "color=\"", 7) == 0) { + line += 7; + if (*line == '#') { + // #RRGGBB format + line++; + tag->color = strtol(line, &line, 16) & 0x00ffffff; + if (*line != '"') + break; + tag->color = ((tag->color & 0xff) << 16) + | (tag->color & 0xff00) + | ((tag->color & 0xff0000) >> 16); + } else { + // Standard web colors + int len = indexof(line, '"'); + if (len <= 0) + break; + for (int i = 0; i < FF_ARRAY_ELEMS(subrip_web_colors); i++) { + char *color = subrip_web_colors[i].s; + if (strlen(color) == len + && strncasecmp(line, color, len) == 0) { + tag->color = subrip_web_colors[i].v; + goto foundcolor; + } + } + + /* We didn't find any matching color */ + mp_tmsg(MSGT_SUBREADER, MSGL_WARN, + "SubRip: unknown font color in subtitle: %s\n", orig); + append_text(&new_line, "{\\c}"); + line += len + 1; + continue; + + foundcolor: + line += len; + } + append_text(&new_line, "{\\c&H%06X&}", tag->color); + tag->has_color = true; + has_valid_attr = true; + } else if (strncmp(line, "face=\"", 6) == 0) { + /* Font face attribute */ + line += 6; + int len = indexof(line, '"'); + if (len <= 0) + break; + tag->face.start = line; + tag->face.len = len; + line += len; + append_text(&new_line, "{\\fn%.*s}", BSTR_P(tag->face)); + tag->has_face = true; + has_valid_attr = true; + } + line++; + } + + if (!has_valid_attr || *line != '>') { /* Not valid font tag */ + line = potential_font_tag_start; + new_line.len = len_backup; + } else { + sp++; + line++; + } + } + + /* Tag conversion code didn't match */ + if (line == orig_line) + new_line.buf[new_line.len++] = *line++; + } + new_line.buf[new_line.len] = 0; +} + + +/* + * MicroDVD + * + * Based on the specifications found here: + * https://trac.videolan.org/vlc/ticket/1825#comment:6 + */ + +struct microdvd_tag { + char key; + int persistent; + uint32_t data1; + uint32_t data2; + struct bstr data_string; +}; + +#define MICRODVD_PERSISTENT_OFF 0 +#define MICRODVD_PERSISTENT_ON 1 +#define MICRODVD_PERSISTENT_OPENED 2 + +// Color, Font, Size, cHarset, stYle, Position, cOordinate +#define MICRODVD_TAGS "cfshyYpo" + +static void microdvd_set_tag(struct microdvd_tag *tags, struct microdvd_tag tag) +{ + int tag_index = indexof(MICRODVD_TAGS, tag.key); + + if (tag_index < 0) + return; + memcpy(&tags[tag_index], &tag, sizeof(tag)); +} + +// italic, bold, underline, strike-through +#define MICRODVD_STYLES "ibus" + +static char *microdvd_load_tags(struct microdvd_tag *tags, char *s) +{ + while (*s == '{') { + char *start = s; + char tag_char = *(s + 1); + struct microdvd_tag tag = {0}; + + if (!tag_char || *(s + 2) != ':') + break; + s += 3; + + switch (tag_char) { + + /* Style */ + case 'Y': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'y': + while (*s && *s != '}') { + int style_index = indexof(MICRODVD_STYLES, *s); + + if (style_index >= 0) + tag.data1 |= (1 << style_index); + s++; + } + if (*s != '}') + break; + /* We must distinguish persistent and non-persistent styles + * to handle this kind of style tags: {y:ib}{Y:us} */ + tag.key = tag_char; + break; + + /* Color */ + case 'C': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'c': + tag.data1 = strtol(s, &s, 16) & 0x00ffffff; + if (*s != '}') + break; + tag.key = 'c'; + break; + + /* Font name */ + case 'F': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'f': + { + int len = indexof(s, '}'); + if (len < 0) + break; + tag.data_string.start = s; + tag.data_string.len = len; + s += len; + tag.key = 'f'; + break; + } + + /* Font size */ + case 'S': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 's': + tag.data1 = strtol(s, &s, 10); + if (*s != '}') + break; + tag.key = 's'; + break; + + /* Charset */ + case 'H': + { + //TODO: not yet handled, just parsed. + int len = indexof(s, '}'); + if (len < 0) + break; + tag.data_string.start = s; + tag.data_string.len = len; + s += len; + tag.key = 'h'; + break; + } + + /* Position */ + case 'P': + tag.persistent = MICRODVD_PERSISTENT_ON; + tag.data1 = (*s++ == '1'); + if (*s != '}') + break; + tag.key = 'p'; + break; + + /* Coordinates */ + case 'o': + tag.persistent = MICRODVD_PERSISTENT_ON; + tag.data1 = strtol(s, &s, 10); + if (*s != ',') + break; + s++; + tag.data2 = strtol(s, &s, 10); + if (*s != '}') + break; + tag.key = 'o'; + break; + + default: /* Unknown tag, we consider it to be text */ + break; + } + + if (tag.key == 0) + return start; + + microdvd_set_tag(tags, tag); + s++; + } + return s; +} + +static void microdvd_open_tags(struct line *new_line, struct microdvd_tag *tags) +{ + for (int i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) { + if (tags[i].persistent == MICRODVD_PERSISTENT_OPENED) + continue; + switch (tags[i].key) { + case 'Y': + case 'y': + for (int sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) + if (tags[i].data1 & (1 << sidx)) + append_text(new_line, "{\\%c1}", MICRODVD_STYLES[sidx]); + break; + + case 'c': + append_text(new_line, "{\\c&H%06X&}", tags[i].data1); + break; + + case 'f': + append_text(new_line, "{\\fn%.*s}", BSTR_P(tags[i].data_string)); + break; + + case 's': + append_text(new_line, "{\\fs%d}", tags[i].data1); + break; + + case 'p': + if (tags[i].data1 == 0) + append_text(new_line, "{\\an8}"); + break; + + case 'o': + append_text(new_line, "{\\pos(%d,%d)}", + tags[i].data1, tags[i].data2); + break; + } + if (tags[i].persistent == MICRODVD_PERSISTENT_ON) + tags[i].persistent = MICRODVD_PERSISTENT_OPENED; + } +} + +static void microdvd_close_no_persistent_tags(struct line *new_line, + struct microdvd_tag *tags) +{ + int i; + + for (i = sizeof(MICRODVD_TAGS) - 2; i; i--) { + if (tags[i].persistent != MICRODVD_PERSISTENT_OFF) + continue; + switch (tags[i].key) { + + case 'y': + for (int sidx = sizeof(MICRODVD_STYLES) - 2; sidx >= 0; sidx--) + if (tags[i].data1 & (1 << sidx)) + append_text(new_line, "{\\%c0}", MICRODVD_STYLES[sidx]); + break; + + case 'c': + append_text(new_line, "{\\c}"); + break; + + case 'f': + append_text(new_line, "{\\fn}"); + break; + + case 's': + append_text(new_line, "{\\fs}"); + break; + } + tags[i].key = 0; + } +} + +void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size) +{ + /* line is not const to avoid warnings with strtol, etc. + * orig content won't be changed */ + char *line = (char *)orig; + struct line new_line = { + .buf = dest, + .bufsize = dest_buffer_size, + }; + struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; + + while (*line) { + line = microdvd_load_tags(tags, line); + microdvd_open_tags(&new_line, tags); + + while (*line && *line != '|') + new_line.buf[new_line.len++] = *line++; + + if (*line == '|') { + microdvd_close_no_persistent_tags(&new_line, tags); + append_text(&new_line, "\\N"); + line++; + } + } + new_line.buf[new_line.len] = 0; +} diff --git a/sub/subassconvert.h b/sub/subassconvert.h new file mode 100644 index 0000000000..e6a4425198 --- /dev/null +++ b/sub/subassconvert.h @@ -0,0 +1,27 @@ +/* + * Header for subtitles converter to SSA/ASS + * + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPLAYER_SUBASSCONVERT_H +#define MPLAYER_SUBASSCONVERT_H + +void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size); +void subassconvert_microdvd(const char *orig, char *dest, int dest_buffer_size); + +#endif diff --git a/subreader.c b/subreader.c index c9b3261c0e..10794b2ff5 100644 --- a/subreader.c +++ b/subreader.c @@ -33,6 +33,8 @@ #include "mp_msg.h" #include "subreader.h" #include "mpcommon.h" +#include "sub/subassconvert.h" +#include "options.h" #include "stream/stream.h" #include "libavutil/common.h" #include "libavutil/avstring.h" @@ -54,6 +56,12 @@ int flip_hebrew = 1; ///flip subtitles using fribidi int fribidi_flip_commas = 0; ///flip comma when fribidi is used #endif +// Parameter struct for the format-specific readline functions +struct readline_args { + int utf16; + struct MPOpts *opts; +}; + /* Maximal length of line of a subtitle */ #define LINE_LEN 1000 static float mpsub_position=0; @@ -119,7 +127,10 @@ static void sami_add_line(subtitle *current, char *buffer, char **pos) { *pos = buffer; } -static subtitle *sub_read_line_sami(stream_t* st, subtitle *current, int utf16) { +static subtitle *sub_read_line_sami(stream_t* st, subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; static char line[LINE_LEN+1]; static char *s = NULL, *slacktime_s; char text[LINE_LEN+1], *p=NULL, *q; @@ -278,7 +289,10 @@ static char *sub_readtext(char *source, char **dest) { else return NULL; // last text field } -static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; char line2[LINE_LEN+1]; char *p, *next; @@ -293,7 +307,11 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf1 "{%ld}{%ld}%[^\r\n]", &(current->start), &(current->end), line2) < 3)); - p=line2; + if (args->opts->ass_enabled) { + subassconvert_microdvd(line2, line, LINE_LEN + 1); + p = line; + } else + p = line2; next=p, i=0; while ((next =sub_readtext (next, &(current->text[i])))) { @@ -306,7 +324,10 @@ static subtitle *sub_read_line_microdvd(stream_t *st,subtitle *current, int utf1 return current; } -static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; char line2[LINE_LEN+1]; char *p, *next; @@ -332,7 +353,10 @@ static subtitle *sub_read_line_mpl2(stream_t *st,subtitle *current, int utf16) { return current; } -static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, int utf16) { +static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; int a1,a2,a3,a4,b1,b2,b3,b4; char *p=NULL, *q=NULL; @@ -362,12 +386,75 @@ static subtitle *sub_read_line_subrip(stream_t* st, subtitle *current, int utf16 return current; } -static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_ass_read_line_subviewer(stream_t *st, subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; + int a1, a2, a3, a4, b1, b2, b3, b4, j = 0; + + while (!current->text[0]) { + char line[LINE_LEN + 1], full_line[LINE_LEN + 1], sep; + int i; + + /* Parse SubRip header */ + if (!stream_read_line(st, line, LINE_LEN, utf16)) + return NULL; + if (sscanf(line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d", + &a1, &a2, &a3, &sep, &a4, &b1, &b2, &b3, &sep, &b4) < 10) + continue; + + current->start = a1 * 360000 + a2 * 6000 + a3 * 100 + a4 / 10; + current->end = b1 * 360000 + b2 * 6000 + b3 * 100 + b4 / 10; + + /* Concat lines */ + full_line[0] = 0; + for (i = 0; i < SUB_MAX_TEXT; i++) { + int blank = 1, len = 0; + char *p; + + if (!stream_read_line(st, line, LINE_LEN, utf16)) + break; + + for (p = line; *p != '\n' && *p != '\r' && *p; p++, len++) + if (*p != ' ' && *p != '\t') + blank = 0; + + if (blank) + break; + + *p = 0; + + if (!(j + 1 + len < sizeof(full_line) - 1)) + break; + + if (j != 0) + full_line[j++] = '\n'; + strcpy(&full_line[j], line); + j += len; + } + + /* Use the ASS/SSA converter to transform the whole lines */ + if (full_line[0]) { + char converted_line[LINE_LEN + 1]; + subassconvert_subrip(full_line, converted_line, LINE_LEN + 1); + current->text[0] = strdup(converted_line); + current->lines = 1; + } + } + return current; +} + +static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; int a1,a2,a3,a4,b1,b2,b3,b4; char *p=NULL; int i,len; + if (args->opts->ass_enabled) + return sub_ass_read_line_subviewer(st, current, args); while (!current->text[0]) { if (!stream_read_line (st, line, LINE_LEN, utf16)) return NULL; if ((len=sscanf (line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d",&a1,&a2,&a3,(char *)&i,&a4,&b1,&b2,&b3,(char *)&i,&b4)) < 10) @@ -414,7 +501,10 @@ static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf return current; } -static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; int a1,a2,a3,a4; char *p=NULL; @@ -447,7 +537,10 @@ static subtitle *sub_read_line_subviewer2(stream_t *st,subtitle *current, int ut } -static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; int a1,a2,a3; char *p=NULL, *next,separator; @@ -493,7 +586,11 @@ static subtitle *sub_read_line_vplayer(stream_t *st,subtitle *current, int utf16 return current; } -static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; + //TODO: This format uses quite rich (sub/super)set of xhtml // I couldn't check it since DTD is not included. // WARNING: full XML parses can be required for proper parsing @@ -543,7 +640,9 @@ static subtitle *sub_read_line_rt(stream_t *st,subtitle *current, int utf16) { return current; } -static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, + struct readline_args *args) +{ /* * Sub Station Alpha v4 (and v2?) scripts have 9 commas before subtitle * other Sub Station Alpha scripts have only 8 commas before subtitle @@ -553,6 +652,7 @@ static subtitle *sub_read_line_ssa(stream_t *st,subtitle *current, int utf16) { * http://www.scriptclub.org is a good place to find more examples * http://www.eswat.demon.co.uk is where the SSA specs can be found */ + int utf16 = args->utf16; int comma; static int max_comma = 32; /* let's use 32 for the case that the */ /* amount of commas increase with newer SSA versions */ @@ -645,7 +745,10 @@ static void sub_pp_ssa(subtitle *sub) { * * by set, based on code by szabi (dunnowhat sub format ;-) */ -static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; char text[LINE_LEN+1], *s, *d; @@ -683,7 +786,10 @@ static subtitle *sub_read_line_pjs(stream_t *st,subtitle *current, int utf16) { return current; } -static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, int utf16) { +static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; float a,b; int num=0; @@ -728,7 +834,10 @@ static subtitle *sub_read_line_mpsub(stream_t *st, subtitle *current, int utf16) subtitle *previous_aqt_sub = NULL; #endif -static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; char *next; int i; @@ -785,7 +894,10 @@ static subtitle *sub_read_line_aqt(stream_t *st,subtitle *current, int utf16) { subtitle *previous_subrip09_sub = NULL; #endif -static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, int utf16) { +static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, + struct readline_args *args) +{ + int utf16 = args->utf16; char line[LINE_LEN+1]; int a1,a2,a3; char * next=NULL; @@ -837,8 +949,10 @@ static subtitle *sub_read_line_subrip09(stream_t *st,subtitle *current, int utf1 return current; } -static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current, int utf16) +static subtitle *sub_read_line_jacosub(stream_t* st, subtitle * current, + struct readline_args *args) { + int utf16 = args->utf16; char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q; unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0; static unsigned jacoTimeres = 30; @@ -1285,7 +1399,8 @@ static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block, } struct subreader { - subtitle * (*read)(stream_t *st,subtitle *dest,int utf16); + subtitle * (*read)(stream_t *st, subtitle *dest, + struct readline_args *args); void (*post)(subtitle *dest); const char *name; }; @@ -1351,7 +1466,8 @@ const char* guess_cp(stream_t *st, const char *preferred_language, const char *f #undef MAX_GUESS_BUFFER_SIZE #endif -sub_data* sub_read_file (char *filename, float fps) { +sub_data* sub_read_file(char *filename, float fps, struct MPOpts *opts) +{ int utf16; stream_t* fd; int n_max, n_first, i, j, sub_first, sub_orig; @@ -1436,7 +1552,7 @@ sub_data* sub_read_file (char *filename, float fps) { sub = &first[sub_num]; #endif memset(sub, '\0', sizeof(subtitle)); - sub=srp->read(fd,sub,utf16); + sub=srp->read(fd, sub, &(struct readline_args){utf16, opts}); if(!sub) break; // EOF #ifdef CONFIG_ICONV if ((sub!=ERR) && sub_utf8 == 2) sub=subcp_recode(sub); diff --git a/subreader.h b/subreader.h index b1aa07421b..9c7465d71a 100644 --- a/subreader.h +++ b/subreader.h @@ -20,6 +20,7 @@ #define MPLAYER_SUBREADER_H #include <stdio.h> +#include <stdbool.h> #include "config.h" @@ -84,7 +85,8 @@ extern char *fribidi_charset; extern int flip_hebrew; extern int fribidi_flip_commas; -sub_data* sub_read_file (char *filename, float pts); +struct MPOpts; +sub_data* sub_read_file (char *filename, float pts, struct MPOpts *opts); subtitle* subcp_recode (subtitle *sub); // enca_fd is the file enca uses to determine the codepage. // setting to NULL disables enca. |