summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--mplayer.c4
-rw-r--r--sub/subassconvert.c502
-rw-r--r--sub/subassconvert.h27
-rw-r--r--subreader.c152
-rw-r--r--subreader.h4
6 files changed, 669 insertions, 21 deletions
diff --git a/Makefile b/Makefile
index 9f5dbc6f23..15bbfbc31c 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/mplayer.c b/mplayer.c
index 69e4dcd0fb..1c41e35f9d 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -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.