[MPlayer-dev-eng] [PATCH] Jacosub subtitles 2
Salvatore Falco
sfalco at studenti.ing.uniroma1.it
Thu Nov 14 19:51:00 CET 2002
I recently sent a patch for a new subtitles format, JACOsub. Since then I
found a better definition of jacosub standard, and this patch is the
result. It supports timeresolutions changes and shifts.
Bye.
-------------- next part --------------
--- subreader.c.20021114 Thu Nov 14 10:40:01 2002
+++ subreader.c Thu Nov 14 12:38:09 2002
@@ -605,191 +593,185 @@
subtitle *sub_read_line_jacosub(FILE * fd, subtitle * current)
{
- char commands[LINE_LEN], line1[LINE_LEN], line2[LINE_LEN],
- text[LINE_LEN], *p, *q;
- int a1, a2, a3, a4, b1, b2, b3, b4, comment = 0;
- unsigned short directive = 0;
+ 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;
+ static int jacoShift = 0;
bzero(current, sizeof(subtitle));
- bzero(commands, sizeof(char) * LINE_LEN);
- bzero(line1, sizeof(char) * LINE_LEN);
- bzero(line2, sizeof(char) * LINE_LEN);
+ bzero(line1, LINE_LEN);
+ bzero(line2, LINE_LEN);
+ bzero(directive, LINE_LEN);
while (!current->text[0]) {
- if (!fgets(line1, LINE_LEN, fd))
+ if (!fgets(line1, LINE_LEN, fd)) {
return NULL;
+ }
if (sscanf
- (line1, "%d:%d:%d.%d %d:%d:%d.%d %[^\n\r]", &a1, &a2, &a3, &a4,
- &b1, &b2, &b3, &b4, line2) < 9)
- continue;
- //a Jacosub script *may* have some commands before the text, so let's recognize them
- switch (toupper(line2[0])) {
- case 'C':
- switch (toupper(line2[1])) {
- case 'F':
- case 'P':
- case 'S':
- case 'B':
- if (isdigit(line2[2]))
- directive = 1;
- }
- break;
- case 'D':
- if ((line2[1] == ' ') || isdigit(line2[1]))
- directive = 1;
- // special case
- if (toupper(line2[1]) == 'C')
- directive = 1;
- break;
- case 'E':
- switch (toupper(line2[1])) {
- case 'D':
- case 'P':
- if (isdigit(line2[2]))
- directive = 1;
- break;
- case 'I':
- if ((toupper(line2[2]) == 'O') && (isdigit(line2[3])))
- directive = 1;
- break;
- case 'R':
- if ((toupper(line2[2]) == 'D') && (isdigit(line2[3])))
- directive = 1;
- break;
- case 'W':
- if ((toupper(line2[2]) == 'L')
- || (toupper(line2[2]) == 'R'))
- directive = 1;
- break;
- }
- break;
- case 'F':
- if (isdigit(line2[1]))
- directive = 1;
- else
- switch (toupper(line2[1])) {
- case 'O':
- if (isdigit(line2[2]))
- directive = 1;
- break;
- case 'S':
- directive = 1;
+ (line1, "%u:%u:%u.%u %u:%u:%u.%u %[^\n\r]", &a1, &a2, &a3, &a4,
+ &b1, &b2, &b3, &b4, line2) < 9) {
+ if (sscanf(line1, "@%u @%u %[^\n\r]", &a4, &b4, line2) < 3) {
+ if (line1[0] == '#') {
+ int hours = 0, minutes = 0, seconds, delta, inverter =
+ 1;
+ unsigned units = jacoShift;
+ switch (toupper(line1[1])) {
+ case 'S':
+ if (isalpha(line1[2])) {
+ delta = 6;
+ } else {
+ delta = 2;
+ }
+ if (sscanf(&line1[delta], "%d", &hours)) {
+ if (hours < 0) {
+ hours *= -1;
+ inverter = -1;
+ }
+ if (sscanf(&line1[delta], "%*d:%d", &minutes)) {
+ if (sscanf
+ (&line1[delta], "%*d:%*d:%d",
+ &seconds)) {
+ sscanf(&line1[delta], "%*d:%*d:%*d.%d",
+ &units);
+ } else {
+ hours = 0;
+ sscanf(&line1[delta], "%d:%d.%d",
+ &minutes, &seconds, &units);
+ minutes *= inverter;
+ }
+ } else {
+ hours = minutes = 0;
+ sscanf(&line1[delta], "%d.%d", &seconds,
+ &units);
+ seconds *= inverter;
+ }
+ jacoShift =
+ ((hours * 3600 + minutes * 60 +
+ seconds) * jacoTimeres +
+ units) * inverter;
+ }
+ break;
+ case 'T':
+ if (isalpha(line1[2])) {
+ delta = 8;
+ } else {
+ delta = 2;
+ }
+ sscanf(&line1[delta], "%u", &jacoTimeres);
+ break;
+ }
}
- break;
- case 'G':
- if ((line2[1] == 'G') && (isdigit(line2[2])))
- directive = 2;
- break;
- case 'H':
- switch (toupper(line2[1])) {
- case 'L':
- case 'R':
- if (isdigit(line2[2]))
- directive = 1;
- }
- break;
- case 'J':
- switch (toupper(line2[1])) {
- case 'B':
- if (toupper(line2[2]) == 'C')
- directive = 1;
- break;
- case 'C':
- case 'L':
- case 'R':
- directive = 1;
- break;
- case 'F':
- if ((line2[2] == ':') && (toupper(line2[3]) == 'L'))
- directive = 1;
- }
- break;
- case 'R':
- if (((toupper(line2[1]) == 'D') && (toupper(line2[2]) == 'B'))
- || ((toupper(line2[1]) == 'D')
- && (toupper(line2[2]) == 'C'))
- || ((toupper(line2[1]) == 'L')
- && (toupper(line2[2]) == 'B')))
- directive = 2;
- break;
- case 'V':
- switch (toupper(line2[1])) {
- case 'A':
- case 'B':
- case 'M':
- case 'T':
- case 'U':
- directive = 1;
- break;
- case 'L':
- case 'P':
- if (isdigit(line2[2]))
- directive = 1;
+ continue;
+ } else {
+ current->start =
+ (unsigned long) ((a4 + jacoShift) * 100.0 /
+ jacoTimeres);
+ current->end =
+ (unsigned long) ((b4 + jacoShift) * 100.0 /
+ jacoTimeres);
}
- break;
- case '[':
- directive = 1;
- break;
- case '~':
- directive = 2;
+ } else {
+ current->start =
+ (unsigned
+ long) (((a1 * 3600 + a2 * 60 + a3) * jacoTimeres + a4 +
+ jacoShift) * 100.0 / jacoTimeres);
+ current->end =
+ (unsigned
+ long) (((b1 * 3600 + b2 * 60 + b3) * jacoTimeres + b4 +
+ jacoShift) * 100.0 / jacoTimeres);
}
- if (directive == 1) {
- strcpy(line1, line2);
- sscanf(line1, "%s %[^\n\r]", commands, line2);
- } else if (directive == 2) {
- continue;
- }
- current->start = a1 * 360000 + a2 * 6000 + a3 * 100 + a4;
- current->end = b1 * 360000 + b2 * 6000 + b3 * 100 + b4;
current->lines = 0;
-
- q = text;
p = line2;
- while ((*p) == ' ')
- p++;
+ while ((*p == ' ') || (*p == '\t')) {
+ ++p;
+ }
+ if (isalpha(*p)||*p == '[') {
+ int cont, jLength;
- for (; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); p++) {
+ if (sscanf(p, "%s %[^\n\r]", directive, line1) < 2)
+ return (subtitle *) ERR;
+ jLength = strlen(directive);
+ for (cont = 0; cont < jLength; ++cont) {
+ if (isalpha(*(directive + cont)))
+ *(directive + cont) = toupper(*(directive + cont));
+ }
+ if ((strstr(directive, "RDB") != NULL)
+ || (strstr(directive, "RDC") != NULL)
+ || (strstr(directive, "RLB") != NULL)
+ || (strstr(directive, "RLG") != NULL)) {
+ continue;
+ }
+ strcpy(line2, line1);
+ p = line2;
+ }
+ for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT);
+ ++p) {
switch (*p) {
case '{':
comment++;
break;
case '}':
- comment--;
- //the next to get rid of a blank after the comment
- if ((*(p + 1)) == ' ')
- p++;
+ if (comment) {
+ --comment;
+ //the next line to get rid of a blank after the comment
+ if ((*(p + 1)) == ' ')
+ p++;
+ }
+ break;
+ case '~':
+ if (!comment) {
+ *q = ' ';
+ ++q;
+ }
+ break;
+ case ' ':
+ case '\t':
+ if ((*(p + 1) == ' ') || (*(p + 1) == '\t'))
+ break;
+ if (!comment) {
+ *q = ' ';
+ ++q;
+ }
break;
case '\\':
if (*(p + 1) == 'n') {
*q = '\0';
- q = text;
- current->text[current->lines++] = strdup(text);
- p++;
+ q = line1;
+ current->text[current->lines++] = strdup(line1);
+ ++p;
break;
- } else if (toupper(*(p + 1)) == 'C') {
- p++;
- p++;
+ }
+ if ((toupper(*(p + 1)) == 'C')
+ || (toupper(*(p + 1)) == 'F')) {
+ ++p,++p;
break;
- } else if ((toupper(*(p + 1)) == 'I')
- || (toupper(*(p + 1)) == 'B')
- || (toupper(*(p + 1)) == 'N')) {
- p++;
+ }
+ if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || (*(p + 1) == 'D') || //actually this means "insert current date here"
+ (*(p + 1) == 'I') || (*(p + 1) == 'i') || (*(p + 1) == 'N') || (*(p + 1) == 'T') || //actually this means "insert current time here"
+ (*(p + 1) == 'U') || (*(p + 1) == 'u')) {
+ ++p;
break;
+ }
+ if ((*(p + 1) == '\\') ||
+ (*(p + 1) == '~') || (*(p + 1) == '{')) {
+ ++p;
} else if (eol(*(p + 1))) {
- if (!fgets(line1, LINE_LEN, fd))
+ if (!fgets(directive, LINE_LEN, fd))
return NULL;
- trail_space(line1);
- p = line1;
+ trail_space(directive);
+ strncat(line2, directive,
+ (LINE_LEN > 511) ? LINE_LEN : 511);
+ break;
}
default:
if (!comment) {
*q = *p;
- q++;
+ ++q;
}
- }
- }
+ } //-- switch
+ } //-- for
*q = '\0';
- current->text[current->lines] = strdup(text);
- }
+ current->text[current->lines] = strdup(line1);
+ } //-- while
current->lines++;
return current;
}
@@ -818,6 +800,8 @@
{sub_uses_time=1; return SUB_SAMI;}
if (sscanf(line, "%d:%d:%d.%d %d:%d:%d.%d", &i, &i, &i, &i, &i, &i, &i, &i) == 8)
{sub_uses_time = 1; return SUB_JACOSUB;}
+ if (sscanf(line, "@%d @%d", &i, &i) == 2)
+ {sub_uses_time = 1; return SUB_JACOSUB;}
if (sscanf (line, "%d:%d:%d:", &i, &i, &i )==3)
{sub_uses_time=1;return SUB_VPLAYER;}
if (sscanf (line, "%d:%d:%d ", &i, &i, &i )==3)
More information about the MPlayer-dev-eng
mailing list