summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-06-01 19:50:46 +0200
committerwm4 <wm4@nowhere>2013-06-03 02:09:07 +0200
commit14dd95154820d4ec9afb5200335177b011233049 (patch)
treef38046e2220e18ee958f7364474bcfa5ef7545d9 /sub
parent3000df35d31f09f13a7c662e2f96bcd7d0f6ac13 (diff)
downloadmpv-14dd95154820d4ec9afb5200335177b011233049.tar.bz2
mpv-14dd95154820d4ec9afb5200335177b011233049.tar.xz
sub: split subassconvert.c into sd_microdvd.c and sd_srt.c
Diffstat (limited to 'sub')
-rw-r--r--sub/sd_microdvd.c311
-rw-r--r--sub/sd_srt.c (renamed from sub/subassconvert.c)256
2 files changed, 311 insertions, 256 deletions
diff --git a/sub/sd_microdvd.c b/sub/sd_microdvd.c
new file mode 100644
index 0000000000..c6c8745e32
--- /dev/null
+++ b/sub/sd_microdvd.c
@@ -0,0 +1,311 @@
+/*
+ * 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 <ctype.h>
+
+#include "core/mp_msg.h"
+#include "subassconvert.h"
+#include "core/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;
+}
+
+
+/*
+ * 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.c b/sub/sd_srt.c
index c665750682..fd1d252924 100644
--- a/sub/subassconvert.c
+++ b/sub/sd_srt.c
@@ -60,13 +60,6 @@ static void append_text_n(struct line *dst, char *start, size_t length)
append_text(dst, "%.*s", (int)length, start);
}
-static int indexof(const char *s, int c)
-{
- char *f = strchr(s, c);
- return f ? (f - s) : -1;
-}
-
-
/*
* SubRip
@@ -443,252 +436,3 @@ void subassconvert_subrip(const char *orig, char *dest, int dest_buffer_size)
}
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;
-}