diff options
Diffstat (limited to 'src/libsputext')
-rw-r--r-- | src/libsputext/Makefile.am | 3 | ||||
-rw-r--r-- | src/libsputext/demux_sputext.c | 1088 | ||||
-rw-r--r-- | src/libsputext/xine_sputext_decoder.c | 325 |
3 files changed, 728 insertions, 688 deletions
diff --git a/src/libsputext/Makefile.am b/src/libsputext/Makefile.am index 4f03d7fa9..ad6c1b776 100644 --- a/src/libsputext/Makefile.am +++ b/src/libsputext/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_LDFLAGS = $(xineplug_ldflags) @@ -8,6 +9,6 @@ xineplug_dmx_sputext_la_SOURCES = demux_sputext.c xineplug_dmx_sputext_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_sputext_la_CFLAGS = $(VISIBILITY_FLAG) -xineplug_decode_sputext_la_SOURCES = xine_sputext_decoder.c +xineplug_decode_sputext_la_SOURCES = xine_sputext_decoder.c xineplug_decode_sputext_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_decode_sputext_la_CFLAGS = $(VISIBILITY_FLAG) diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c index acf8e10f6..b0e1299d9 100644 --- a/src/libsputext/demux_sputext.c +++ b/src/libsputext/demux_sputext.c @@ -1,18 +1,18 @@ /* * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -67,7 +67,7 @@ typedef struct { long start; /* csecs */ long end; /* csecs */ - + char *text[SUB_MAX_TEXT]; } subtitle_t; @@ -84,10 +84,10 @@ typedef struct { char buf[SUB_BUFSIZE]; off_t buflen; - float mpsub_position; + float mpsub_position; - int uses_time; - int errs; + int uses_time; + int errs; subtitle_t *subtitles; int num; /* number of subtitle structs */ int cur; /* current subtitle */ @@ -117,8 +117,8 @@ typedef struct demux_sputext_class_s { #define FORMAT_RT 5 #define FORMAT_SSA 6 /* Sub Station Alpha */ #define FORMAT_PJS 7 -#define FORMAT_MPSUB 8 -#define FORMAT_AQTITLE 9 +#define FORMAT_MPSUB 8 +#define FORMAT_AQTITLE 9 #define FORMAT_JACOBSUB 10 #define FORMAT_SUBVIEWER2 11 #define FORMAT_SUBRIP09 12 @@ -129,7 +129,6 @@ static int eol(char p) { } static inline void trail_space(char *s) { - int i; while (isspace(*s)) { char *copy = s; do { @@ -137,8 +136,8 @@ static inline void trail_space(char *s) { copy++; } while(*copy); } - i = strlen(s) - 1; - while (i > 0 && isspace(s[i])) + size_t i = strlen(s) - 1; + while (i > 0 && isspace(s[i])) s[i--] = '\0'; } @@ -147,26 +146,24 @@ static inline void trail_space(char *s) { */ static char *read_line_from_input(demux_sputext_t *this, char *line, off_t len) { off_t nread = 0; - char *s; - int linelen; - - if ((len - this->buflen) > 512) { - if((nread = this->input->read(this->input, + + if ((len - this->buflen) > 512 && len < SUB_BUFSIZE) { + if((nread = this->input->read(this->input, &this->buf[this->buflen], len - this->buflen)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "read failed.\n"); return NULL; } } - + this->buflen += nread; this->buf[this->buflen] = '\0'; - s = strchr(this->buf, '\n'); + char *s = strchr(this->buf, '\n'); if (line && (s || this->buflen)) { - - linelen = s ? (s - this->buf) + 1 : this->buflen; - + + size_t linelen = s ? (s - this->buf) + 1 : this->buflen; + memcpy(line, this->buf, linelen); line[linelen] = '\0'; @@ -184,21 +181,20 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current static char line[LINE_LEN + 1]; static char *s = NULL; - char text[LINE_LEN + 1], *p, *q; - int state; + char text[LINE_LEN + 1]; - p = NULL; + char *p = NULL; current->lines = current->start = 0; current->end = -1; - state = 0; - + int state = 0; + /* read the first line */ if (!s) if (!(s = read_line_from_input(this, line, LINE_LEN))) return 0; - + do { switch (state) { - + case 0: /* find "START=" */ s = strstr (s, "Start="); if (s) { @@ -206,15 +202,15 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current state = 1; continue; } break; - + case 1: /* find "<P" */ if ((s = strstr (s, "<P"))) { s += 2; state = 2; continue; } break; - + case 2: /* find ">" */ if ((s = strchr (s, '>'))) { s++; state = 3; p = text; continue; } break; - + case 3: /* get all text until '<' appears */ if (*s == '\0') { break; } else if (*s == '<') { state = 4; } @@ -228,50 +224,47 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current } else *p++ = *s++; continue; - + case 4: /* get current->end or skip <TAG> */ - q = strstr (s, "Start="); - if (q) { - current->end = strtol (q + 6, &q, 0) / 10 - 1; - *p = '\0'; trail_space (text); - if (text[0] != '\0') - current->text[current->lines++] = strdup (text); - if (current->lines > 0) { state = 99; break; } - state = 0; continue; + { + char *q = strstr (s, "Start="); + if (q) { + current->end = strtol (q + 6, &q, 0) / 10 - 1; + *p = '\0'; trail_space (text); + if (text[0] != '\0') + current->text[current->lines++] = strdup (text); + if (current->lines > 0) { state = 99; break; } + state = 0; continue; + } } s = strchr (s, '>'); if (s) { s++; state = 3; continue; } break; } - + /* read next line */ - if (state != 99 && !(s = read_line_from_input (this, line, LINE_LEN))) + if (state != 99 && !(s = read_line_from_input (this, line, LINE_LEN))) return 0; - + } while (state != 99); - + return current; } static char *sub_readtext(char *source, char **dest) { - int len=0; + size_t len=0; char *p=source; - + while ( !eol(*p) && *p!= '|' ) { p++,len++; } - - *dest= (char *)xine_xmalloc (len+1); - if (!dest) - return ERR; - - strncpy(*dest, source, len); - (*dest)[len]=0; - + + *dest = strndup(source, len); + while (*p=='\r' || *p=='\n' || *p=='|') p++; - + if (*p) return p; /* not-last text field */ else return NULL; /* last text field */ } @@ -280,63 +273,62 @@ static subtitle_t *sub_read_line_microdvd(demux_sputext_t *this, subtitle_t *cur char line[LINE_LEN + 1]; char line2[LINE_LEN + 1]; - char *p, *next; - int i; - + memset (current, 0, sizeof(subtitle_t)); - + current->end=-1; do { if (!read_line_from_input (this, line, LINE_LEN)) return NULL; } while ((sscanf (line, "{%ld}{}%" LINE_LEN_QUOT "[^\r\n]", &(current->start), line2) !=2) && (sscanf (line, "{%ld}{%ld}%" LINE_LEN_QUOT "[^\r\n]", &(current->start), &(current->end),line2) !=3) ); - - p=line2; - - next=p, i=0; + + char *p=line2; + + char *next=p; + size_t i=0; while ((next =sub_readtext (next, &(current->text[i])))) { if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; } } current->lines= ++i; - + return current; } static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - char *p=NULL, *q=NULL; - int len; - + memset (current, 0, sizeof(subtitle_t)); - + while (1) { if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) { - if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) - continue; + + { + int a1,a2,a3,a4,b1,b2,b3,b4; + if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) { + if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) + continue; + } + + current->start = a1*360000+a2*6000+a3*100+a4; + current->end = b1*360000+b2*6000+b3*100+b4; } - current->start = a1*360000+a2*6000+a3*100+a4; - current->end = b1*360000+b2*6000+b3*100+b4; - + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - - p=q=line; + + char *p = line, *q = line; for (current->lines=1; current->lines <= SUB_MAX_TEXT; current->lines++) { + size_t len; for (q=p,len=0; *p && *p!='\r' && *p!='\n' && *p!='|' && strncasecmp(p,"[br]",4); p++,len++); - current->text[current->lines-1]=(char *)xine_xmalloc (len+1); + current->text[current->lines-1] = strndup(q, len); if (!current->text[current->lines-1]) return ERR; - strncpy (current->text[current->lines-1], q, len); - current->text[current->lines-1][len]='\0'; if (!*p || *p=='\r' || *p=='\n') break; if (*p=='[') while (*p++!=']'); if (*p=='|') p++; @@ -348,25 +340,27 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *cu } static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *current) { - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - int i,end_sub; - memset(current,0,sizeof(subtitle_t)); - do { - if(!read_line_from_input(this,line,LINE_LEN)) - return NULL; - i = sscanf(line,"%d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4); - } while(i < 8); - current->start = a1*360000+a2*6000+a3*100+a4/10; - current->end = b1*360000+b2*6000+b3*100+b4/10; - i=0; - end_sub=0; + + { + int a1,a2,a3,a4,b1,b2,b3,b4,i; + do { + char line[LINE_LEN + 1]; + if(!read_line_from_input(this,line,LINE_LEN)) + return NULL; + i = sscanf(line,"%d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4); + } while(i < 8); + current->start = a1*360000+a2*6000+a3*100+a4/10; + current->end = b1*360000+b2*6000+b3*100+b4/10; + } + + int i=0; + int end_sub=0; do { char *p; /* pointer to the curently read char */ - char temp_line[SUB_BUFSIZE]; /* subtitle line that will be transfered to current->text[i] */ - int temp_index; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */ - temp_line[SUB_BUFSIZE-1]='\0'; /* just in case... */ + char line[LINE_LEN + 1]; + char temp_line[SUB_BUFSIZE] = { 0, }; /* subtitle line that will be transfered to current->text[i] */ + size_t temp_index; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */ if(!read_line_from_input(this,line,LINE_LEN)) { if(i) break; /* if something was read, transmit it */ @@ -396,10 +390,10 @@ static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *curren xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many characters in a subtitle line\n"); if(temp_line[temp_index-1]=='\0' || temp_index==SUB_BUFSIZE) { if(temp_index>1) { /* more than 1 char (including '\0') -> that is a valid one */ - current->text[i]=(char *)xine_xmalloc(temp_index); + /* temp_index<=SUB_BUFSIZE is always true here */ + current->text[i] = strndup(temp_line, temp_index); if(!current->text[i]) return ERR; - strncpy(current->text[i],temp_line,temp_index); /* temp_index<=SUB_BUFSIZE is always true here */ i++; temp_index=0; } else @@ -416,12 +410,9 @@ static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *curren static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *current) { char line[LINE_LEN + 1]; - int a1,a2,a3,b1,b2,b3; - char *p=NULL, *next, *p2; - int i; - + memset (current, 0, sizeof(subtitle_t)); - + while (!current->text[0]) { if( this->next_line[0] == '\0' ) { /* if the buffer is empty.... */ if( !read_line_from_input(this, line, LINE_LEN) ) return NULL; @@ -436,29 +427,37 @@ static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *curre this->next_line[0] = '\0'; return NULL; } - if( (sscanf( line, "%d:%d:%d:", &a1, &a2, &a3) < 3) || - (sscanf( this->next_line, "%d:%d:%d:", &b1, &b2, &b3) < 3) ) - continue; - current->start = a1*360000+a2*6000+a3*100; - current->end = b1*360000+b2*6000+b3*100; - if ((current->end - current->start) > LINE_LEN) + + { + int a1,a2,a3,b1,b2,b3; + if( (sscanf( line, "%d:%d:%d:", &a1, &a2, &a3) < 3) || + (sscanf( this->next_line, "%d:%d:%d:", &b1, &b2, &b3) < 3) ) + continue; + current->start = a1*360000+a2*6000+a3*100; + current->end = b1*360000+b2*6000+b3*100; + } + + if ((current->end - current->start) > LINE_LEN) current->end = current->start + LINE_LEN; /* not too long though. */ /* teraz czas na wkopiowanie stringu */ - p=line; + char *p=line; /* finds the body of the subtitle_t */ - for (i=0; i<3; i++){ - p2=strchr( p, ':'); - if( p2 == NULL ) break; - p=p2+1; - } - - next=p; - i=0; + { + int i; + for (i=0; i<3; i++){ + char *p2=strchr( p, ':'); + if( p2 == NULL ) break; + p=p2+1; + } + } + + char *next=p; + int i=0; while( (next = sub_readtext( next, &(current->text[i]))) ) { - if (current->text[i]==ERR) + if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; @@ -471,44 +470,49 @@ static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *curre static subtitle_t *sub_read_line_rt(demux_sputext_t *this,subtitle_t *current) { /* - * TODO: This format uses quite rich (sub/super)set of xhtml + * 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 + * WARNING: full XML parses can be required for proper parsing */ - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - char *p=NULL,*next=NULL; - int i,len,plen; - memset (current, 0, sizeof(subtitle_t)); - + while (!current->text[0]) { + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + + char *p = line; /* * TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0 * to describe the same moment in time. Maybe there are even more formats in use. */ - if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8) - - plen=a1=a2=a3=a4=b1=b2=b3=b4=0; - if ( - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&plen)) < 4) && - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&b4,&plen)) < 5) && - /* ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen)) < 5) && */ - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&b4,&plen)) < 6) && - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d:%d.%d\" %*[Ee]nd=\"%d:%d:%d.%d\"%*[^<]<clear/>%n",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen)) < 8) - ) - continue; - current->start = a1*360000+a2*6000+a3*100+a4/10; - current->end = b1*360000+b2*6000+b3*100+b4/10; - p=line; p+=plen;i=0; + { + int a1,a2,a3,a4,b1,b2,b3,b4,len,plen; + if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8) + + a1=a2=a3=a4=b1=b2=b3=b4=0; + if ( + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&plen)) < 4) && + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&b4,&plen)) < 5) && + /* ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen)) < 5) && */ + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&b4,&plen)) < 6) && + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d:%d.%d\" %*[Ee]nd=\"%d:%d:%d.%d\"%*[^<]<clear/>%n",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen)) < 8) + ) + continue; + + current->start = a1*360000+a2*6000+a3*100+a4/10; + current->end = b1*360000+b2*6000+b3*100+b4/10; + + p += plen; + } + + int i=0; /* TODO: I don't know what kind of convention is here for marking multiline subs, maybe <br/> like in xml? */ - next = strstr(line,"<clear/>")+8;i=0; + char *next = strstr(line,"<clear/>")+8;i=0; while ((next =sub_readtext (next, &(current->text[i])))) { - if (current->text[i]==ERR) + if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; @@ -520,61 +524,63 @@ static subtitle_t *sub_read_line_rt(demux_sputext_t *this,subtitle_t *current) { } static subtitle_t *sub_read_line_ssa(demux_sputext_t *this,subtitle_t *current) { - int comma; static int max_comma = 32; /* let's use 32 for the case that the */ /* amount of commas increase with newer SSA versions */ - + int hour1, min1, sec1, hunsec1, hour2, min2, sec2, hunsec2, nothing; - int num; - char line[LINE_LEN + 1], line3[LINE_LEN + 1], *line2; - char *tmp; - - do { - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d," - "%[^\n\r]", ¬hing, - &hour1, &min1, &sec1, &hunsec1, - &hour2, &min2, &sec2, &hunsec2, - line3) < 9 - && - sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d," - "%[^\n\r]", ¬hing, - &hour1, &min1, &sec1, &hunsec1, - &hour2, &min2, &sec2, &hunsec2, - line3) < 9 ); - - line2=strchr(line3, ','); - - for (comma = 4; comma < max_comma; comma ++) - { - tmp = line2; - if(!(tmp=strchr(++tmp, ','))) break; - if(*(++tmp) == ' ') break; - /* a space after a comma means we're already in a sentence */ - line2 = tmp; - } - + char line3[LINE_LEN + 1]; + + { + char line[LINE_LEN + 1]; + do { + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d," + "%[^\n\r]", ¬hing, + &hour1, &min1, &sec1, &hunsec1, + &hour2, &min2, &sec2, &hunsec2, + line3) < 9 + && + sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d," + "%[^\n\r]", ¬hing, + &hour1, &min1, &sec1, &hunsec1, + &hour2, &min2, &sec2, &hunsec2, + line3) < 9 ); + } + + char *line2=strchr(line3, ','); + if (!line2) + return NULL; + + int comma; + for (comma = 4; comma < max_comma; comma ++) { + char *tmp = line2; + if(!(tmp=strchr(++tmp, ','))) break; + if(*(++tmp) == ' ') break; + /* a space after a comma means we're already in a sentence */ + line2 = tmp; + } + if(comma < max_comma)max_comma = comma; /* eliminate the trailing comma */ if(*line2 == ',') line2++; - - current->lines=0;num=0; + + current->lines=0; current->start = 360000*hour1 + 6000*min1 + 100*sec1 + hunsec1; current->end = 360000*hour2 + 6000*min2 + 100*sec2 + hunsec2; - + + int num=0; + char *tmp; while (((tmp=strstr(line2, "\\n")) != NULL) || ((tmp=strstr(line2, "\\N")) != NULL) ){ - current->text[num]=(char *)malloc(tmp-line2+1); - strncpy (current->text[num], line2, tmp-line2); - current->text[num][tmp-line2]='\0'; + current->text[num] = strndup(line2, tmp-line2); line2=tmp+2; num++; current->lines++; if (current->lines >= SUB_MAX_TEXT) return current; } - + current->text[num]=strdup(line2); current->lines++; - + return current; } @@ -591,11 +597,10 @@ static subtitle_t *sub_read_line_ssa(demux_sputext_t *this,subtitle_t *current) static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current) { char line[LINE_LEN + 1]; - char text[LINE_LEN + 1]; - char *s, *d; - + char *s; + memset (current, 0, sizeof(subtitle_t)); - + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; for (s = line; *s && isspace(*s); s++); @@ -607,7 +612,7 @@ static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current /* the files I have are in tenths of second */ current->start *= 10; current->end *= 10; - + /* walk to the beggining of the string */ for (; *s; s++) if (*s==',') break; if (*s) { @@ -618,56 +623,57 @@ static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current return ERR; } /* copy the string to the text buffer */ + char text[LINE_LEN + 1]; + char *d = NULL; for (s++, d=text; *s && *s!='"'; s++, d++) *d=*s; *d=0; current->text[0] = strdup(text); current->lines = 1; - + return current; } static subtitle_t *sub_read_line_mpsub (demux_sputext_t *this, subtitle_t *current) { char line[LINE_LEN + 1]; - float a,b; - int num=0; - char *p, *q; - - do { - if (!read_line_from_input(this, line, LINE_LEN)) - return NULL; - } while (sscanf (line, "%f %f", &a, &b) !=2); - this->mpsub_position += (a*100.0); - current->start = (int) this->mpsub_position; - this->mpsub_position += (b*100.0); - current->end = (int) this->mpsub_position; - + { + float a,b; + do { + if (!read_line_from_input(this, line, LINE_LEN)) + return NULL; + } while (sscanf (line, "%f %f", &a, &b) !=2); + + this->mpsub_position += (a*100.0); + current->start = (int) this->mpsub_position; + this->mpsub_position += (b*100.0); + current->end = (int) this->mpsub_position; + } + + int num = 0; while (num < SUB_MAX_TEXT) { - if (!read_line_from_input(this, line, LINE_LEN)) + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - p=line; - while (isspace(*p)) + char *p=line; + while (isspace(*p)) p++; - if (eol(*p) && num > 0) + if (eol(*p) && num > 0) return current; - if (eol(*p)) + if (eol(*p)) return NULL; - + + char *q; for (q=p; !eol(*q); q++); *q='\0'; - if (strlen(p)) { + if (*p) { current->text[num]=strdup(p); xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, ">%s<\n",p); current->lines = ++num; } else { - if (num) - return current; - else - return NULL; + return num ? current : NULL; } } @@ -675,299 +681,296 @@ static subtitle_t *sub_read_line_mpsub (demux_sputext_t *this, subtitle_t *curre } static subtitle_t *sub_read_line_aqt (demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - memset (current, 0, sizeof(subtitle_t)); while (1) { + char line[LINE_LEN + 1]; /* try to locate next subtitle_t */ if (!read_line_from_input(this, line, LINE_LEN)) return NULL; if (!(sscanf (line, "-->> %ld", &(current->start)) <1)) break; } - + + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - + sub_readtext((char *) &line,¤t->text[0]); current->lines = 1; current->end = -1; - + if (!read_line_from_input(this, line, LINE_LEN)) return current;; - + sub_readtext((char *) &line,¤t->text[1]); current->lines = 2; - + if ((current->text[0][0]==0) && (current->text[1][0]==0)) { return NULL; } - + return current; } static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *this, subtitle_t *current) { - 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; - - memset(current, 0, sizeof(subtitle_t)); - memset(line1, 0, LINE_LEN); - memset(line2, 0, LINE_LEN); - memset(directive, 0, LINE_LEN); - while (!current->text[0]) { - if (!read_line_from_input(this, line1, LINE_LEN)) { - return NULL; - } - if (sscanf - (line1, "%u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT "[^\n\r]", &a1, &a2, &a3, &a4, - &b1, &b2, &b3, &b4, line2) < 9) { - if (sscanf(line1, "@%u @%u %" LINE_LEN_QUOT "[^\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; - } - } - continue; + char line1[LINE_LEN] = { 0, }, line2[LINE_LEN] = { 0, }, directive[LINE_LEN] = { 0, }, *p, *q; + unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0; + static unsigned jacoTimeres = 30; + static int jacoShift = 0; + + memset(current, 0, sizeof(subtitle_t)); + while (!current->text[0]) { + if (!read_line_from_input(this, line1, LINE_LEN)) { + return NULL; + } + if (sscanf + (line1, "%u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT "[^\n\r]", &a1, &a2, &a3, &a4, + &b1, &b2, &b3, &b4, line2) < 9) { + if (sscanf(line1, "@%u @%u %" LINE_LEN_QUOT "[^\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 { - current->start = - (unsigned long) ((a4 + jacoShift) * 100.0 / - jacoTimeres); - current->end = - (unsigned long) ((b4 + jacoShift) * 100.0 / - jacoTimeres); - } - } 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); - } - current->lines = 0; - p = line2; - while ((*p == ' ') || (*p == '\t')) { - ++p; - } - if (isalpha(*p)||*p == '[') { - int cont, jLength; - - if (sscanf(p, "%s %" LINE_LEN_QUOT "[^\n\r]", directive, line1) < 2) - return ERR; - jLength = strlen(directive); - for (cont = 0; cont < jLength; ++cont) { - if (isalpha(*(directive + cont))) - *(directive + cont) = toupper(*(directive + cont)); + delta = 2; } - if ((strstr(directive, "RDB") != NULL) - || (strstr(directive, "RDC") != NULL) - || (strstr(directive, "RLB") != NULL) - || (strstr(directive, "RLG") != NULL)) { - continue; + 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; } - /* no alignment */ -#if 0 - if (strstr(directive, "JL") != NULL) { - current->alignment = SUB_ALIGNMENT_HLEFT; - } else if (strstr(directive, "JR") != NULL) { - current->alignment = SUB_ALIGNMENT_HRIGHT; + break; + case 'T': + if (isalpha(line1[2])) { + delta = 8; } else { - current->alignment = SUB_ALIGNMENT_HCENTER; + delta = 2; } + sscanf(&line1[delta], "%u", &jacoTimeres); + break; + } + } + continue; + } else { + current->start = + (unsigned long) ((a4 + jacoShift) * 100.0 / + jacoTimeres); + current->end = + (unsigned long) ((b4 + jacoShift) * 100.0 / + jacoTimeres); + } + } 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); + } + current->lines = 0; + p = line2; + while ((*p == ' ') || (*p == '\t')) { + ++p; + } + if (isalpha(*p)||*p == '[') { + if (sscanf(p, "%s %" LINE_LEN_QUOT "[^\n\r]", directive, line1) < 2) + return ERR; + if ((strcasestr(directive, "RDB") != NULL) + || (strcasestr(directive, "RDC") != NULL) + || (strcasestr(directive, "RLB") != NULL) + || (strcasestr(directive, "RLG") != NULL)) { + continue; + } + /* no alignment */ +#if 0 + if (strcasestr(directive, "JL") != NULL) { + current->alignment = SUB_ALIGNMENT_HLEFT; + } else if (strcasestr(directive, "JR") != NULL) { + current->alignment = SUB_ALIGNMENT_HRIGHT; + } else { + current->alignment = SUB_ALIGNMENT_HCENTER; + } #endif - strcpy(line2, line1); - p = line2; + strcpy(line2, line1); + p = line2; + } + for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); ++p) { + switch (*p) { + case '{': + comment++; + break; + case '}': + if (comment) { + --comment; + /* the next line to get rid of a blank after the comment */ + if ((*(p + 1)) == ' ') + p++; } - for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); ++p) { - switch (*p) { - case '{': - comment++; - break; - case '}': - 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 = line1; - current->text[current->lines++] = strdup(line1); - ++p; - break; - } - if ((toupper(*(p + 1)) == 'C') - || (toupper(*(p + 1)) == 'F')) { - ++p,++p; - break; - } - if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || - /* actually this means "insert current date here" */ - (*(p + 1) == 'D') || - (*(p + 1) == 'I') || (*(p + 1) == 'i') || - (*(p + 1) == 'N') || - /* actually this means "insert current time here" */ - (*(p + 1) == 'T') || - (*(p + 1) == 'U') || (*(p + 1) == 'u')) { - ++p; - break; - } - if ((*(p + 1) == '\\') || - (*(p + 1) == '~') || (*(p + 1) == '{')) { - ++p; - } else if (eol(*(p + 1))) { - if (!read_line_from_input(this, directive, LINE_LEN)) - return NULL; - trail_space(directive); - strncat(line2, directive, - ((LINE_LEN > 511) ? LINE_LEN-1 : 511) - - strlen(line2)); - break; - } - default: - if (!comment) { - *q = *p; - ++q; - } - } + 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 = line1; + current->text[current->lines++] = strdup(line1); + ++p; + break; + } + if ((toupper(*(p + 1)) == 'C') + || (toupper(*(p + 1)) == 'F')) { + ++p,++p; + break; + } + if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || + /* actually this means "insert current date here" */ + (*(p + 1) == 'D') || + (*(p + 1) == 'I') || (*(p + 1) == 'i') || + (*(p + 1) == 'N') || + /* actually this means "insert current time here" */ + (*(p + 1) == 'T') || + (*(p + 1) == 'U') || (*(p + 1) == 'u')) { + ++p; + break; } - *q = '\0'; - current->text[current->lines] = strdup(line1); + if ((*(p + 1) == '\\') || + (*(p + 1) == '~') || (*(p + 1) == '{')) { + ++p; + } else if (eol(*(p + 1))) { + if (!read_line_from_input(this, directive, LINE_LEN)) + return NULL; + trail_space(directive); + strncat(line2, directive, + ((LINE_LEN > 511) ? LINE_LEN-1 : 511) + - strlen(line2)); + break; + } + default: + if (!comment) { + *q = *p; + ++q; + } + } } - current->lines++; - return current; + *q = '\0'; + if (current->lines < SUB_MAX_TEXT) + current->text[current->lines] = strdup(line1); + else + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); + } + current->lines++; + return current; } static subtitle_t *sub_read_line_subviewer2(demux_sputext_t *this, subtitle_t *current) { + char *p=NULL; + + while (!current->text[0]) { char line[LINE_LEN+1]; - int a1,a2,a3,a4; - char *p=NULL; - int i,len; - - while (!current->text[0]) { - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - if (line[0]!='{') - continue; - if ((len=sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4)) < 4) - continue; - current->start = a1*360000+a2*6000+a3*100+a4/10; - for (i=0; i<SUB_MAX_TEXT;) { - if (!read_line_from_input(this, line, LINE_LEN)) break; - if (line[0]=='}') break; - len=0; - for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len); - if (len) { - current->text[i]=(char *)malloc (len+1); - if (!current->text[i]) return ERR; - strncpy (current->text[i], line, len); current->text[i][len]='\0'; - ++i; - } else { - break; - } - } - current->lines=i; + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + if (line[0]!='{') + continue; + + { + int a1,a2,a3,a4; + const int len = sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4); + if (len < 4) + continue; + current->start = a1*360000+a2*6000+a3*100+a4/10; } - return current; + + int i; + for (i=0; i<SUB_MAX_TEXT;) { + if (!read_line_from_input(this, line, LINE_LEN)) break; + if (line[0]=='}') break; + size_t len=0; + for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len); + if (len) { + current->text[i] = strndup(line, len); + if (!current->text[i]) return ERR; + ++i; + } else { + break; + } + } + current->lines=i; + } + return current; } static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - char *next; - int h, m, s; - int i; - memset (current, 0, sizeof(subtitle_t)); - - do { - if (!read_line_from_input (this, line, LINE_LEN)) return NULL; - } while (sscanf (line, "[%d:%d:%d]", &h, &m, &s) != 3); + int h, m, s; + { + char line[LINE_LEN + 1]; + do { + if (!read_line_from_input (this, line, LINE_LEN)) return NULL; + } while (sscanf (line, "[%d:%d:%d]", &h, &m, &s) != 3); + } + + char line[LINE_LEN + 1]; if (!read_line_from_input (this, line, LINE_LEN)) return NULL; current->start = 360000 * h + 6000 * m + 100 * s; current->end = -1; - next=line; - i=0; + char *next = line; + int i=0; while ((next = sub_readtext (next, &(current->text[i])))) { if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; } } current->lines= ++i; - + return current; } @@ -976,22 +979,27 @@ static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *this, subtitle_t *cu */ static subtitle_t *sub_read_line_mpl2(demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN+1]; char line2[LINE_LEN+1]; - char *p, *next; - int i; memset (current, 0, sizeof(subtitle_t)); - do { - if (!read_line_from_input (this, line, LINE_LEN)) return NULL; - } while ((sscanf (line, + + { + char line[LINE_LEN+1]; + long start, end; + + do { + if (!read_line_from_input (this, line, LINE_LEN)) return NULL; + } while ((sscanf (line, "[%ld][%ld]%[^\r\n]", - &(current->start), &(current->end), line2) < 3)); - current->start *= 10; - current->end *= 10; - p=line2; + &start, &end, line2) < 3)); + + current->start = start * 10; + current->end = end * 10; + } + + char *p = line2, *next = p; + int i = 0; - next=p, i=0; while ((next = sub_readtext (next, &(current->text[i])))) { if (current->text[i] == ERR) {return ERR;} i++; @@ -1009,16 +1017,13 @@ static subtitle_t *sub_read_line_mpl2(demux_sputext_t *this, subtitle_t *current static int sub_autodetect (demux_sputext_t *this) { - - char line[LINE_LEN + 1]; - int i, j=0; - char p; - - while (j < 100) { - j++; + int j; + for(j = 1; j < 100; j++) { + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return FORMAT_UNKNOWN; + int i; if ((sscanf (line, "{%d}{}", &i)==1) || (sscanf (line, "{%d}{%d}", &i, &i)==2)) { this->uses_time=0; @@ -1045,7 +1050,7 @@ static int sub_autodetect (demux_sputext_t *this) { } if (strstr (line, "<SAMI>")) { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "sami subtitle format detected\n"); return FORMAT_SAMI; } @@ -1064,7 +1069,7 @@ static int sub_autodetect (demux_sputext_t *this) { return FORMAT_RT; } if ((!memcmp(line, "Dialogue: Marked", 16)) || (!memcmp(line, "Dialogue: ", 10))) { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ssa subtitle format detected\n"); return FORMAT_SSA; } @@ -1074,17 +1079,20 @@ static int sub_autodetect (demux_sputext_t *this) { return FORMAT_PJS; } if (sscanf (line, "FORMAT=%d", &i) == 1) { - this->uses_time=0; + this->uses_time=0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpsub subtitle format detected\n"); return FORMAT_MPSUB; } + + char p; if (sscanf (line, "FORMAT=TIM%c", &p)==1 && p=='E') { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpsub subtitle format detected\n"); return FORMAT_MPSUB; } + if (strstr (line, "-->>")) { - this->uses_time=0; + this->uses_time=0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "aqtitle subtitle format detected\n"); return FORMAT_AQTITLE; } @@ -1104,7 +1112,7 @@ static int sub_autodetect (demux_sputext_t *this) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subrip 0.9 subtitle format detected\n"); return FORMAT_SUBRIP09; } - + if (sscanf (line, "[%d][%d]", &i, &i) == 2) { this->uses_time = 1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpl2 subtitle format detected\n"); @@ -1116,9 +1124,6 @@ static int sub_autodetect (demux_sputext_t *this) { static subtitle_t *sub_read_file (demux_sputext_t *this) { - int n_max; - int timeout; - subtitle_t *first; subtitle_t * (*func[])(demux_sputext_t *this,subtitle_t *dest)= { sub_read_line_microdvd, @@ -1151,7 +1156,7 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { } xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Detected subtitle file format: %d\n",this->format); - + /* Rewind */ if(this->input->seek(this->input, 0, SEEK_SET) == -1) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "seek failed.\n"); @@ -1159,33 +1164,33 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { } this->buflen = 0; - this->num=0;n_max=32; - first = (subtitle_t *) xine_xmalloc(n_max*sizeof(subtitle_t)); + this->num=0; + int n_max=32; + subtitle_t *first = calloc(n_max, sizeof(subtitle_t)); if(!first) return NULL; - timeout = ((demux_sputext_class_t *) - (this->demux_plugin.demux_class))->max_timeout; - if (this->uses_time) timeout *= 100; - else timeout *= 10; - while(1) { - subtitle_t *sub; + const int timeout = + (((demux_sputext_class_t *) + (this->demux_plugin.demux_class))->max_timeout) * + (this->uses_time ? 100 : 10); + while(1) { if(this->num>=n_max){ n_max+=16; first=realloc(first,n_max*sizeof(subtitle_t)); } - sub = func[this->format] (this, &first[this->num]); + subtitle_t *sub = func[this->format] (this, &first[this->num]); - if (!sub) + if (!sub) break; /* EOF */ - if (sub==ERR) - ++this->errs; + if (sub==ERR) + ++this->errs; else { if (this->num > 0 && first[this->num-1].end == -1) { /* end time not defined in the subtitle */ - if (timeout > 0) { + if (timeout > 0) { /* timeout */ if (timeout > sub->start - first[this->num-1].start) { first[this->num-1].end = sub->start; @@ -1210,57 +1215,56 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { sprintf(buffer, "Read %i subtitles", this->num); - if(this->errs) + if(this->errs) sprintf(buffer + strlen(buffer), ", %i bad line(s).\n", this->errs); else strcat(buffer, "\n"); - + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "%s", buffer); } - + return first; } static int demux_sputext_next (demux_sputext_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - buf_element_t *buf; - uint32_t *val; - char *str; - subtitle_t *sub; - int line; - + if (this->cur >= this->num) return 0; - sub = &this->subtitles[this->cur]; - - buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); + subtitle_t *sub = &this->subtitles[this->cur]; + + buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); buf->type = BUF_SPU_TEXT; buf->pts = 0; - val = (uint32_t * )buf->content; + uint32_t *val = (uint32_t * )buf->content; *val++ = sub->lines; *val++ = this->uses_time; *val++ = (this->uses_time) ? sub->start * 10 : sub->start; *val++ = (this->uses_time) ? sub->end * 10 : sub->end; - str = (char *)val; + char *str = (char *)val; + + /** @FIXME The way this works seems wrong, SUB_BUFSIZE-1 is not the + right maximum, I think. */ + int line; for (line = 0; line < sub->lines; line++, str+=strlen(str)+1) { - if( strlen(sub->text[line]) > SUB_BUFSIZE ) - sub->text[line][SUB_BUFSIZE] = '\0'; - strcpy(str, sub->text[line]); + strncpy(str, sub->text[line], SUB_BUFSIZE-1); + str[SUB_BUFSIZE-1] = '\0'; } - + this->stream->video_fifo->put(this->stream->video_fifo, buf); this->cur++; - + return 1; } static void demux_sputext_dispose (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - int i, l; - + + int i; for (i = 0; i < this->num; i++) { + int l; for (l = 0; l < this->subtitles[i].lines; l++) free(this->subtitles[i].text[l]); } @@ -1276,16 +1280,14 @@ static int demux_sputext_get_status (demux_plugin_t *this_gen) { static int demux_sputext_get_stream_length (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - if( this->uses_time && this->num ) { - return this->subtitles[this->num-1].end * 10; - } else { - return 0; - } + return ( this->uses_time && this->num ) ? + this->subtitles[this->num-1].end * 10 : + 0; } static int demux_sputext_send_chunk (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - + if (!demux_sputext_next (this)) { this->status = DEMUX_FINISHED; } @@ -1299,35 +1301,33 @@ static int demux_sputext_seek (demux_plugin_t *this_gen, lprintf("seek() called\n"); - /* simple seeking approach: just go back to start. + /* simple seeking approach: just go back to start. * decoder will discard subtitles until the desired position. */ this->cur = 0; this->status = DEMUX_OK; - + _x_demux_flush_engine (this->stream); _x_demux_control_newpts(this->stream, 0, 0); - + return this->status; } static void demux_sputext_send_headers(demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t*)this_gen; - buf_element_t *buf; - lprintf("send_headers() called\n"); - + _x_demux_control_start(this->stream); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0); /* enable the SPU channel */ - buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); + buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); buf->type = BUF_CONTROL_SPU_CHANNEL; buf->decoder_info[0] = buf->decoder_info[1] = buf->decoder_info[2] = 0; this->stream->video_fifo->put(this->stream->video_fifo, buf); - + this->status = DEMUX_OK; } @@ -1357,8 +1357,8 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ demux_sputext_t *this; lprintf("open_plugin() called\n"); - - this = xine_xmalloc (sizeof (demux_sputext_t)); + + this = calloc(1, sizeof (demux_sputext_t)); this->stream = stream; this->input = input; @@ -1392,26 +1392,26 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ } } /* falling through is intended */ - + case METHOD_EXPLICIT: /* case METHOD_BY_CONTENT: */ - + /* FIXME: for now this demuxer only works when requested explicitly * to make sure it does not interfere with others; * If this is found too inconvenient, this may be changed after making * sure the content detection does not produce any false positives. */ - + if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { - + this->subtitles = sub_read_file (this); this->cur = 0; if (this->subtitles) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subtitle format %s time.\n", + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subtitle format %s time.\n", this->uses_time ? "uses" : "doesn't use"); - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "read %i subtitles, %i errors.\n", this->num, this->errs); return &this->demux_plugin; } @@ -1422,7 +1422,7 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ free (this); return NULL; } - + static const char *get_demux_description (demux_class_t *this_gen) { return "sputext demuxer plugin"; } @@ -1460,7 +1460,7 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { lprintf("initializing\n"); - this = xine_xmalloc (sizeof (demux_sputext_class_t)); + this = calloc(1, sizeof (demux_sputext_class_t)); this->demux_class.open_plugin = open_demux_plugin; this->demux_class.get_description = get_demux_description; @@ -1469,13 +1469,13 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { this->demux_class.get_extensions = get_demux_extensions; this->demux_class.dispose = demux_class_dispose; - /* + /* * Some subtitling formats, namely AQT and Subrip09, define the end of a - * subtitle as the beginning of the following. From end-user view it's + * subtitle as the beginning of the following. From end-user view it's * better define timeout of hidding. Setting to zero means "no timeout". */ - this->max_timeout = xine->config->register_num(xine->config, - "subtitles.separate.timeout", 4, + this->max_timeout = xine->config->register_num(xine->config, + "subtitles.separate.timeout", 4, _("default duration of subtitle display in seconds"), _("Some subtitle formats do not explicitly give a duration for each subtitle. " "For these, you can set a default duration here. Setting to zero will result " @@ -1486,7 +1486,7 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { } const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "sputext", XINE_VERSION_CODE, NULL, &init_sputext_demux_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libsputext/xine_sputext_decoder.c b/src/libsputext/xine_sputext_decoder.c index 1de1eb099..cda8a5983 100644 --- a/src/libsputext/xine_sputext_decoder.c +++ b/src/libsputext/xine_sputext_decoder.c @@ -1,23 +1,27 @@ /* * Copyright (C) 2000-2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -63,7 +67,7 @@ #define rgb2yuv(R,G,B) ((((((66*R+129*G+25*B+128)>>8)+16)<<8)|(((112*R-94*G-18*B+128)>>8)+128))<<8|(((-38*R-74*G+112*B+128)>>8)+128)) -static uint32_t sub_palette[22]={ +static const uint32_t sub_palette[22]={ /* RED */ rgb2yuv(0,0,0), rgb2yuv(0,0,0), @@ -90,7 +94,7 @@ static uint32_t sub_palette[22]={ rgb2yuv(0,170,255) }; -static uint8_t sub_trans[22]={ +static const uint8_t sub_trans[22]={ 0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15, 0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }; @@ -169,7 +173,7 @@ typedef struct sputext_decoder_s { int64_t img_duration; int64_t last_subtitle_end; /* no new subtitle before this vpts */ int unscaled; /* use unscaled OSD */ - + int last_y; /* location of the previous subtitle */ int last_lines; /* number of lines of the previous subtitle */ video2wnd_t video2wnd; @@ -185,12 +189,12 @@ static inline char *get_font (sputext_class_t *class) } static void update_font_size (sputext_decoder_t *this, int force_update) { - static int sizes[SUBTITLE_SIZE_NUM] = { 16, 20, 24, 32, 48, 64 }; + static const int sizes[SUBTITLE_SIZE_NUM] = { 16, 20, 24, 32, 48, 64 }; if ((this->subtitle_size != this->class->subtitle_size) || (this->vertical_offset != this->class->vertical_offset) || force_update) { - + this->subtitle_size = this->class->subtitle_size; this->vertical_offset = this->class->vertical_offset; this->last_lines = 0; @@ -203,7 +207,7 @@ static void update_font_size (sputext_decoder_t *this, int force_update) { if( this->osd ) this->renderer->free_object (this->osd); - this->osd = this->renderer->new_object (this->renderer, + this->osd = this->renderer->new_object (this->renderer, this->width, this->height); @@ -214,11 +218,9 @@ static void update_font_size (sputext_decoder_t *this, int force_update) { } static void update_output_size (sputext_decoder_t *this) { - int unscaled; - - unscaled = this->class->use_unscaled && - (this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY); + const int unscaled = this->class->use_unscaled && + (this->stream->video_out->get_capabilities(this->stream->video_out) & + VO_CAP_UNSCALED_OVERLAY); if( unscaled != this->unscaled ) { this->unscaled = unscaled; @@ -227,14 +229,14 @@ static void update_output_size (sputext_decoder_t *this) { /* initialize decoder if needed */ if( this->unscaled ) { - if( this->width != this->stream->video_out->get_property(this->stream->video_out, + if( this->width != this->stream->video_out->get_property(this->stream->video_out, VO_PROP_WINDOW_WIDTH) || - this->height != this->stream->video_out->get_property(this->stream->video_out, + this->height != this->stream->video_out->get_property(this->stream->video_out, VO_PROP_WINDOW_HEIGHT) || !this->img_duration || !this->osd ) { int width = 0, height = 0; - + this->stream->video_out->status(this->stream->video_out, NULL, &width, &height, &this->img_duration ); if( width && height ) { @@ -251,13 +253,13 @@ static void update_output_size (sputext_decoder_t *this) { /* and a displacement factor because video may have blacks lines. */ int output_width, output_height, output_xoffset, output_yoffset; - output_width = this->stream->video_out->get_property(this->stream->video_out, + output_width = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_WIDTH); - output_height = this->stream->video_out->get_property(this->stream->video_out, + output_height = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_HEIGHT); - output_xoffset = this->stream->video_out->get_property(this->stream->video_out, + output_xoffset = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_XOFFSET); - output_yoffset = this->stream->video_out->get_property(this->stream->video_out, + output_yoffset = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_YOFFSET); /* driver don't seen to be capable to give us those values */ @@ -281,16 +283,16 @@ static void update_output_size (sputext_decoder_t *this) { } } else { if( !this->width || !this->height || !this->img_duration || !this->osd ) { - + this->width = 0; this->height = 0; - + this->stream->video_out->status(this->stream->video_out, NULL, &this->width, &this->height, &this->img_duration ); - + if(!this->osd || ( this->width && this->height)) { this->renderer = this->stream->osd_renderer; - + /* in scaled mode, we have to convert subtitle position in film coordinates. */ this->video2wnd.x = 0; this->video2wnd.y = 0; @@ -303,18 +305,18 @@ static void update_output_size (sputext_decoder_t *this) { } } -static int parse_utf8_size(unsigned char *c) +static int parse_utf8_size(const uint8_t *c) { if ( c[0]<0x80 ) return 1; - + if( c[1]==0 ) return 1; if ( (c[0]>=0xC2 && c[0]<=0xDF) && (c[1]>=0x80 && c[1]<=0xBF) ) return 2; - + if( c[2]==0 ) - return 2; + return 2; else if ( c[0]==0xE0 && (c[1]>=0xA0 && c[1]<=0xBF) && (c[2]>=0x80 && c[1]<=0xBF) ) return 3; else if ( (c[0]>=0xE1 && c[0]<=0xEC) && (c[1]>=0x80 && c[1]<=0xBF) && (c[2]>=0x80 && c[1]<=0xBF) ) @@ -329,13 +331,8 @@ static int parse_utf8_size(unsigned char *c) static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const char *text, int render) { - int i = 0, w, value; - char* end; - char letter[5]={0, 0, 0, 0, 0}; - const char *encoding = this->buf_encoding ? this->buf_encoding - : this->class->src_encoding; - int shift, isutf8 = !strcmp(encoding, "utf-8"); - size_t length = strlen (text); + const size_t length = strlen (text); + size_t i = 0; while (i <= length) { @@ -352,7 +349,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; i=i+4; continue; - } else if (!strncmp("<i>", text+i, 3)) { + } else if (!strncmp("<i>", text+i, 3)) { /* enable italics color */ if (render) this->current_osd_text = OSD_TEXT3; @@ -364,7 +361,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; i=i+4; continue; - } else if (!strncmp("<font>", text+i, 6)) { + } else if (!strncmp("<font>", text+i, 6)) { /*Do somethink to disable typing fixme - no teststreams*/ i=i+6; @@ -379,6 +376,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const if (text[i] == '{') { if (!strncmp("{\\", text+i, 2)) { + int value; if (sscanf(text+i, "{\\b%d}", &value) == 1) { if (render) { @@ -395,7 +393,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; } } - end = strstr(text+i+2, "}"); + char *const end = strstr(text+i+2, "}"); if (end) { i=end-text+1; continue; @@ -403,15 +401,20 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const } } - shift = isutf8 ? parse_utf8_size (&text[i]) : 1; + char letter[5]; + const char *const encoding = this->buf_encoding ? : this->class->src_encoding; + const int isutf8 = !strcmp(encoding, "utf-8"); + const size_t shift = isutf8 ? parse_utf8_size (&text[i]) : 1; memcpy(letter,&text[i],shift); letter[shift]=0; - + if (render) this->renderer->render_text(this->osd, x, y, letter, this->current_osd_text); - this->renderer->get_text_size(this->osd, letter, &w, &value); - x=x+w; - i+=shift; + + int w, dummy; + this->renderer->get_text_size(this->osd, letter, &w, &dummy); + x += w; + i += shift; } return x; @@ -429,7 +432,7 @@ static inline void ogm_render_line(sputext_decoder_t *this, int x, int y, char* /* \a : alignment in SSA code (see #defines) */ /* \an : alignment in 'numpad code' */ /* \pos : absolute position of subtitles. Alignment define origin. */ -static void read_ssa_tag(sputext_decoder_t *this, const char* text, +static void read_ssa_tag(sputext_decoder_t *this, const char* text, int* alignment, int* sub_x, int* sub_y, int* max_width) { int in_tag = 0; @@ -465,7 +468,7 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, if (*text == '}') in_tag = 0; } - + text++; } @@ -479,7 +482,7 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, if ((*sub_x) >= 0 && (*sub_y) >= 0) { (*sub_x) = this->video2wnd.x + this->video2wnd.dx * (*sub_x); (*sub_y) = this->video2wnd.y + this->video2wnd.dy * (*sub_y); - } + } /* check validity, compute max width */ if ( (*sub_x) < 0 || (*sub_x) >= this->width || @@ -506,15 +509,50 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, (*sub_x), (*sub_y), (*max_width), (*alignment)); } +static int is_cjk_encoding(const char *enc) { + /* CJK charset strings defined in iconvdata/gconv-modules of glibc */ + static const char cjk_encoding_strings[][16] = { + "SJIS", + "CP932", + "EUC-KR", + "UHC", + "JOHAB", + "BIG5", + "BIG5HKSCS", + "EUC-JP-MS", + "EUC-JP", + "EUC-CN", + "GBBIG5", + "GBK", + "GBGBK", + "EUC-TW", + "ISO-2022-JP", + "ISO-2022-JP-2", + "ISO-2022-JP-3", + "ISO-2022-KR", + "ISO-2022-CN", + "ISO-2022-CN-EXT", + "GB18030", + "EUC-JISX0213", + "SHIFT_JISX0213", + }; + + int pstr; + + /* return 1 if encoding string is one of the CJK(Chinese,Jananese,Korean) + * character set strings. */ + for (pstr = 0; pstr < sizeof (cjk_encoding_strings) / sizeof (cjk_encoding_strings[0]); pstr++) + if (strcasecmp (enc, cjk_encoding_strings[pstr]) == 0) + return 1; + + return 0; +} + static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t sub_end ) { - - int line, y; - int font_size; - char *font; + + int y; int sub_x, sub_y, max_width; int alignment; - int rebuild_all; - _x_assert(this->renderer != NULL); if ( ! this->renderer ) @@ -523,22 +561,21 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su read_ssa_tag(this, this->text[0], &alignment, &sub_x, &sub_y, &max_width); update_font_size(this, 0); - - font = get_font (this->class); + + const char *const font = get_font (this->class); if( strcmp(this->font, font) ) { strncpy(this->font, font, FILENAME_MAX); this->font[FILENAME_MAX - 1] = '\0'; this->renderer->set_font (this->osd, font, this->font_size); } - font_size = this->font_size; - if (this->buf_encoding) - this->renderer->set_encoding(this->osd, this->buf_encoding); - else - this->renderer->set_encoding(this->osd, this->class->src_encoding); + int font_size = this->font_size; + const char *const encoding = this->buf_encoding ? : this->class->src_encoding; + this->renderer->set_encoding(this->osd, encoding); - rebuild_all = 0; + int rebuild_all = 0; + int line; for (line = 0; line < this->lines; line++) { int line_width = ogm_get_width(this, this->text[line]); @@ -547,13 +584,13 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su char *current_cut, *best_cut; int a; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "libsputext: Line too long: %d > %d, split at max size.\n", + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "libsputext: Line too long: %d > %d, split at max size.\n", line_width, max_width); /* can't fit with keeping existing lines */ if (this->lines + 1 > SUB_MAX_TEXT) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libsputext: Can't fit with keeping existing line, we have to rebuild all the subtitle\n"); rebuild_all = 1; break; @@ -577,7 +614,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su } if (best_cut == NULL) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libsputext: Can't wrap line: a word is too long, abort.\n"); break; } @@ -596,30 +633,27 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su /* regenerate all the lines to find something that better fits */ if (rebuild_all) { - int line, line_width; - char *stream, *current_cut, *best_cut; - char buf[SUB_BUFSIZE * SUB_MAX_TEXT]; + char buf[SUB_BUFSIZE * SUB_MAX_TEXT] = { 0, }; - buf[0] = 0; + int line; for(line = 0; line < this->lines; line++) { - int len = strlen(buf); - if (len) { + const size_t len = strlen(buf); + if (len) buf[len] = ' '; - len++; - } - strncpy(buf + len, this->text[line], SUB_BUFSIZE); - *(buf + len + SUB_BUFSIZE) = 0; + + strncat(buf, this->text[line], SUB_BUFSIZE-len-1); } - stream = buf; + char *stream = buf; this->lines = 0; + char *current_cut, *best_cut; do { if (this->lines + 1 < SUB_MAX_TEXT) { - + /* find the longest sequence witch fit */ - line_width = 0; + int line_width = 0; current_cut = stream; best_cut = NULL; while (line_width < max_width) { @@ -637,7 +671,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su } } } - + /* line maybe too long, but we have reached last subtitle line */ else { best_cut = current_cut = stream + strlen(stream); @@ -650,7 +684,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su stream = best_cut + 1; - } while (best_cut != current_cut); + } while (best_cut != current_cut); } @@ -658,7 +692,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su /* Erase subtitle : use last_y and last_lines saved last turn. */ if (this->last_lines) { this->renderer->filled_rect (this->osd, 0, this->last_y, - this->width - 1, this->last_y + this->last_lines * this->line_height, + this->width - 1, this->last_y + this->last_lines * this->line_height, 0); } @@ -672,23 +706,23 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su if (sub_y >= 0) y = sub_y - (this->lines * this->line_height) / 2; else y = (this->height - this->lines * this->line_height) / 2; break; - + case ALIGN_BOTTOM: default: if (sub_y >= 0) y = sub_y - this->lines * this->line_height; else y = this->height - this->lines * this->line_height - this->class->vertical_offset; break; } - if (y < 0 || y >= this->height) + if (y < 0 || y >= this->height) y = this->height - this->line_height * this->lines; - this->last_lines = this->lines; - this->last_y = y; + this->last_lines = this->lines; + this->last_y = y; for (line = 0; line < this->lines; line++) { int w, x; - + while(1) { w = ogm_get_width( this, this->text[line]); @@ -702,7 +736,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su if (sub_x >= 0) x = sub_x - w; else x = max_width - w - 5; break; - + case ALIGN_CENTER: default: if (sub_x >= 0) x = sub_x - w / 2; @@ -718,34 +752,39 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su break; } } - - ogm_render_line(this, x, y + line*this->line_height, this->text[line]); + + if( is_cjk_encoding(encoding) ) { + this->renderer->render_text (this->osd, x, y + line * this->line_height, + this->text[line], OSD_TEXT1); + } else { + ogm_render_line(this, x, y + line*this->line_height, this->text[line]); + } } - + if( font_size != this->font_size ) this->renderer->set_font (this->osd, get_font (this->class), this->font_size); - + if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) { sub_start = this->last_subtitle_end; } this->last_subtitle_end = sub_end; - + this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1); this->renderer->get_palette(this->osd, this->spu_palette, this->spu_trans); /* append some colors for colored typeface tag */ memcpy(this->spu_palette+OSD_TEXT2, sub_palette, sizeof(sub_palette)); memcpy(this->spu_trans+OSD_TEXT2, sub_trans, sizeof(sub_trans)); this->renderer->set_palette(this->osd, this->spu_palette, this->spu_trans); - + if (this->unscaled) this->renderer->show_unscaled (this->osd, sub_start); else this->renderer->show (this->osd, sub_start); - + this->renderer->hide (this->osd, sub_end); - + lprintf ("scheduling subtitle >%s< at %"PRId64" until %"PRId64", current time is %"PRId64"\n", - this->text[0], sub_start, sub_end, + this->text[0], sub_start, sub_end, this->stream->xine->clock->get_current_time (this->stream->xine->clock)); } @@ -770,7 +809,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - + if ((this->stream->spu_channel & 0x1f) != (buf->type & 0x1f)) return; @@ -793,9 +832,9 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (!*str) return; /* Empty ogm packets (as created by ogmmux) clears out old messages. We already respect the end time. */ - + this->lines = 0; - + i = 0; while (*str && (this->lines < SUB_MAX_TEXT) && (i < SUB_BUFSIZE)) { if (*str == '\r' || *str == '\n') { @@ -813,7 +852,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } if (i == SUB_BUFSIZE) i--; - + if (i) { this->text[ this->lines ][i] = 0; this->lines++; @@ -823,7 +862,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { this->ogm = 0; val = (uint32_t * )buf->content; - + this->lines = *val++; uses_time = *val++; start = *val++; @@ -835,7 +874,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } } - + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: decoder data [%s]\n", this->text[0]); xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, @@ -846,7 +885,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { "libsputext: discarding subtitle with invalid timing\n"); return; } - + spu_offset = this->stream->master->metronom->get_option (this->stream->master->metronom, METRONOM_SPU_OFFSET); if( uses_time ) { @@ -858,17 +897,17 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { end += spu_offset / this->img_duration; } } - + while( !this->finished ) { - + master_status = xine_get_status (this->stream->master); slave_status = xine_get_status (this->stream); - vo_discard = this->stream->video_out->get_property(this->stream->video_out, + vo_discard = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_DISCARD_FRAMES); _x_get_current_info (this->stream->master, &extra_info, sizeof(extra_info) ); - - lprintf("master: %d slave: %d input_normpos: %d vo_discard: %d\n", + + lprintf("master: %d slave: %d input_normpos: %d vo_discard: %d\n", master_status, slave_status, extra_info.input_normpos, vo_discard); if( !this->started && (master_status == XINE_STATUS_PLAY && @@ -886,63 +925,63 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if( this->started ) { - if( master_status != XINE_STATUS_PLAY || + if( master_status != XINE_STATUS_PLAY || slave_status != XINE_STATUS_PLAY || vo_discard ) { lprintf("finished\n"); - + this->width = this->height = 0; this->finished = 1; return; } if( this->osd ) { - + /* try to use frame number mode */ if( !uses_time && extra_info.frame_number ) { - + diff = end - extra_info.frame_number; - + /* discard old subtitles */ if( diff < 0 ) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: discarding old subtitle\n"); return; } - + diff = start - extra_info.frame_number; - + start_vpts = extra_info.vpts + diff * this->img_duration; end_vpts = start_vpts + (end-start) * this->img_duration; - + } else { - + if( !uses_time ) { start = start * this->img_duration / 90; end = end * this->img_duration / 90; uses_time = 1; } - + diff = end - extra_info.input_time; - + /* discard old subtitles */ if( diff < 0 ) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: discarding old subtitle\n"); return; } - + diff = start - extra_info.input_time; - + start_vpts = extra_info.vpts + diff * 90; end_vpts = start_vpts + (end-start) * 90; } - + _x_spu_decoder_sleep(this->stream, start_vpts); update_output_size( this ); draw_subtitle(this, start_vpts, end_vpts); - - return; + + return; } } @@ -951,12 +990,12 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { else return; } -} +} static void spudec_reset (spu_decoder_t *this_gen) { sputext_decoder_t *this = (sputext_decoder_t *) this_gen; - + lprintf("i guess we just seeked\n"); this->width = this->height = 0; this->started = this->finished = 0; @@ -970,7 +1009,7 @@ static void spudec_discontinuity (spu_decoder_t *this_gen) { static void spudec_dispose (spu_decoder_t *this_gen) { sputext_decoder_t *this = (sputext_decoder_t *) this_gen; - + if (this->osd) { this->renderer->free_object (this->osd); this->osd = NULL; @@ -991,7 +1030,7 @@ static void update_osd_font(void *class_gen, xine_cfg_entry_t *entry) strncpy(class->font, entry->str_value, FONTNAME_SIZE); class->font[FONTNAME_SIZE - 1] = '\0'; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_font = %s\n", class->font ); } @@ -1002,7 +1041,7 @@ static void update_osd_font_ft(void *class_gen, xine_cfg_entry_t *entry) strncpy(class->font_ft, entry->str_value, FILENAME_MAX); class->font_ft[FILENAME_MAX - 1] = '\0'; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_font_ft = %s\n", class->font_ft); } @@ -1011,7 +1050,7 @@ static void update_osd_use_font_ft(void *class_gen, xine_cfg_entry_t *entry) sputext_class_t *class = (sputext_class_t *)class_gen; class->use_font_ft = entry->num_value; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_use_font_ft = %d\n", class->use_font_ft); } #endif @@ -1035,7 +1074,7 @@ static spu_decoder_t *sputext_class_open_plugin (spu_decoder_class_t *class_gen, sputext_class_t *class = (sputext_class_t *)class_gen; sputext_decoder_t *this ; - this = (sputext_decoder_t *) xine_xmalloc (sizeof (sputext_decoder_t)); + this = (sputext_decoder_t *) calloc(1, sizeof(sputext_decoder_t)); this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -1082,14 +1121,14 @@ static void update_src_encoding(void *class_gen, xine_cfg_entry_t *entry) static void *init_spu_decoder_plugin (xine_t *xine, void *data) { - static const char *subtitle_size_strings[] = { - "tiny", "small", "normal", "large", "very large", "huge", NULL + static const char *subtitle_size_strings[] = { + "tiny", "small", "normal", "large", "very large", "huge", NULL }; sputext_class_t *this ; lprintf("init class\n"); - - this = (sputext_class_t *) xine_xmalloc (sizeof (sputext_class_t)); + + this = (sputext_class_t *) calloc(1, sizeof(sputext_class_t)); this->class.open_plugin = sputext_class_open_plugin; this->class.get_identifier = sputext_class_get_identifier; @@ -1098,8 +1137,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { this->xine = xine; - this->subtitle_size = xine->config->register_enum(xine->config, - "subtitles.separate.subtitle_size", + this->subtitle_size = xine->config->register_enum(xine->config, + "subtitles.separate.subtitle_size", 1, subtitle_size_strings, _("subtitle size"), @@ -1107,7 +1146,7 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { "be evaluated relative to the window size."), 0, update_subtitle_size, this); this->vertical_offset = xine->config->register_num(xine->config, - "subtitles.separate.vertical_offset", + "subtitles.separate.vertical_offset", 0, _("subtitle vertical offset"), _("You can adjust the vertical position of the subtitle. " @@ -1136,8 +1175,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { NULL, 10, update_osd_use_font_ft, this); #endif - this->src_encoding = xine->config->register_string(xine->config, - "subtitles.separate.src_encoding", + this->src_encoding = xine->config->register_string(xine->config, + "subtitles.separate.src_encoding", xine_guess_spu_encoding(), _("encoding of the subtitles"), _("The encoding of the subtitle text in the stream. This setting " @@ -1170,7 +1209,7 @@ static const decoder_info_t spudec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER | PLUGIN_MUST_PRELOAD, 16, "sputext", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |