summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrantišek Dvořák <valtri@users.sourceforge.net>2004-06-11 09:47:29 +0000
committerFrantišek Dvořák <valtri@users.sourceforge.net>2004-06-11 09:47:29 +0000
commitc450de308294d4dd0e4a6d86b28a59ce72801330 (patch)
treea94984c43e5bcbc9695324b884fbecd43e5c575b
parentcda7393846ea62539cb4582eff20b6b83c4fca81 (diff)
downloadxine-lib-c450de308294d4dd0e4a6d86b28a59ce72801330.tar.gz
xine-lib-c450de308294d4dd0e4a6d86b28a59ce72801330.tar.bz2
Patch with improvements for libsputext from Vincent Pelletier - word wrap and enhanced subtitle parser.
CVS patchset: 6673 CVS date: 2004/06/11 09:47:29
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog1
-rw-r--r--src/libsputext/demux_sputext.c132
-rw-r--r--src/libsputext/xine_decoder.c168
4 files changed, 266 insertions, 38 deletions
diff --git a/AUTHORS b/AUTHORS
index 98e403fca..f02d51a18 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -486,5 +486,8 @@ Moritz Bunkus <moritz@bunkus.org>
Szymon Stefanek <s.stefanek@libero.it>
Improved DVB mrls and dvbs, dvbc and dvbt support
+Vincent Pelletier <subdino2004@yahoo.fr>
+ Word wrap and other improvements in libsputext.
+
(let us know if we've forgotten anyone)
diff --git a/ChangeLog b/ChangeLog
index 24c1beb2d..be256300e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,7 @@
* add support for XVR-100 (Radeon-based) framebuffers to video_out_pgx64
* support DTS audio in AVI
* revised FLAC playback subsystem
+ * subtitles improvements - word wrap and new subtitle format variants
xine-lib (1-rc4a)
* audio out now uses a more user friendly "Speaker arrangement" config item;
diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c
index 664e6b702..9a754b62f 100644
--- a/src/libsputext/demux_sputext.c
+++ b/src/libsputext/demux_sputext.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: demux_sputext.c,v 1.34 2004/04/26 17:50:08 mroi Exp $
+ * $Id: demux_sputext.c,v 1.35 2004/06/11 09:47:30 valtri Exp $
*
* code based on old libsputext/xine_decoder.c
*
@@ -100,7 +100,7 @@ typedef struct {
typedef struct demux_sputext_class_s {
demux_class_t demux_class;
-
+
int max_timeout; /* default timeout of hidding subtitles */
} demux_sputext_class_t;
@@ -109,6 +109,7 @@ typedef struct demux_sputext_class_s {
* Demuxer code start
*/
+#define FORMAT_UNKNOWN -1
#define FORMAT_MICRODVD 0
#define FORMAT_SUBRIP 1
#define FORMAT_SUBVIEWER 2
@@ -314,11 +315,15 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *cu
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) continue;
+ 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;
- if (!read_line_from_input(this, line, LINE_LEN)) return NULL;
+ if (!read_line_from_input(this, line, LINE_LEN))
+ return NULL;
p=q=line;
for (current->lines=1; current->lines < SUB_MAX_TEXT; current->lines++) {
@@ -339,34 +344,91 @@ 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;
- char *p=NULL;
- int i,len;
-
- memset (current, 0, sizeof(subtitle_t));
+ int i,end_sub;
- while (!current->text[0]) {
- if (!read_line_from_input(this, line, LINE_LEN)) return NULL;
-
- if ((len=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/10;
- current->end = b1*360000+b2*6000+b3*100+b4/10;
- for (i=0; i<SUB_MAX_TEXT;) {
- if (!read_line_from_input(this, line, LINE_LEN)) break;
- len=0;
- for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++);
- if (len) {
- current->text[i]=(char *)xine_xmalloc (len+1);
- if (!current->text[i]) return ERR;
- strncpy (current->text[i], line, len); current->text[i][len]='\0';
- i++;
- } else {
- break;
+ memset(current,0,sizeof(subtitle_t));
+ do {
+ if(!read_line_from_input(this,line,LINE_LEN))
+ return NULL;
+ } while(sscanf(line,"%d:%d:%d,%d --> %d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 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;
+ 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... */
+ if(!read_line_from_input(this,line,LINE_LEN)) {
+ if(i)
+ break; /* if something was read, transmit it */
+ else
+ return NULL; /* if not, repport EOF */
+ }
+ for(temp_index=0,p=line;*p!='\0' && !end_sub && temp_index<SUB_BUFSIZE && i<SUB_MAX_TEXT;p++) {
+ switch(*p) {
+ case '\\':
+ if(*(p+1)=='N' || *(p+1)=='n') {
+ temp_line[temp_index++]='\0'; /* end of curent line */
+ p++;
+ } else
+ temp_line[temp_index++]=*p;
+ break;
+ case '{':
+#if 0 /* italic not implemented in renderer, ignore them for now */
+ if(!strncmp(p,"{\\i1}",5) && temp_index+3<SUB_BUFSIZE) {
+ temp_line[temp_index++]='<';
+ temp_line[temp_index++]='i';
+ temp_line[temp_index++]='>';
+#else
+ if(!strncmp(p,"{\\i1}",5)) {
+#endif
+ p+=4;
+ }
+#if 0 /* italic not implemented in renderer, ignore them for now */
+ else if(!strncmp(p,"{\\i0}",5) && temp_index+4<SUB_BUFSIZE) {
+ temp_line[temp_index++]='<';
+ temp_line[temp_index++]='/';
+ temp_line[temp_index++]='i';
+ temp_line[temp_index++]='>';
+#else
+ else if(!strncmp(p,"{\\i0}",5)) {
+#endif
+ p+=4;
+ }
+ else
+ temp_line[temp_index++]=*p;
+ break;
+ case '\r': /* just ignore '\r's */
+ break;
+ case '\n':
+ temp_line[temp_index++]='\0';
+ break;
+ default:
+ temp_line[temp_index++]=*p;
+ break;
+ }
+ if(temp_index>0) {
+ if(temp_index==SUB_BUFSIZE)
+ 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);
+ 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
+ end_sub=1;
+ }
}
}
- current->lines=i;
- }
-
+ } while(i<SUB_MAX_TEXT && !end_sub);
+ if(i>=SUB_MAX_TEXT)
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n");
+ current->lines=i;
return current;
}
@@ -903,7 +965,7 @@ static int sub_autodetect (demux_sputext_t *this) {
while (j < 100) {
j++;
if (!read_line_from_input(this, line, LINE_LEN))
- return -1;
+ return FORMAT_UNKNOWN;
if ((sscanf (line, "{%d}{}", &i)==1) ||
(sscanf (line, "{%d}{%d}", &i, &i)==2)) {
@@ -924,6 +986,12 @@ static int sub_autodetect (demux_sputext_t *this) {
return FORMAT_SUBVIEWER;
}
+ if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d", &i, &i, &i, &i, &i, &i, &i, &i)==8){
+ this->uses_time=1;
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subviewer subtitle format detected\n");
+ return FORMAT_SUBVIEWER;
+ }
+
if (strstr (line, "<SAMI>")) {
this->uses_time=1;
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "sami subtitle format detected\n");
@@ -986,7 +1054,7 @@ static int sub_autodetect (demux_sputext_t *this) {
}
}
- return -1; /* too many bad lines */
+ return FORMAT_UNKNOWN; /* too many bad lines */
}
static subtitle_t *sub_read_file (demux_sputext_t *this) {
@@ -1019,7 +1087,7 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) {
this->buflen = 0;
this->format=sub_autodetect (this);
- if (this->format==-1) {
+ if (this->format==FORMAT_UNKNOWN) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Could not determine file format\n");
return NULL;
}
diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c
index 6e351651e..07f520f0d 100644
--- a/src/libsputext/xine_decoder.c
+++ b/src/libsputext/xine_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.81 2004/06/04 14:37:33 mroi Exp $
+ * $Id: xine_decoder.c,v 1.82 2004/06/11 09:47:30 valtri Exp $
*
*/
@@ -299,17 +299,173 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su
if( this->renderer )
this->renderer->set_font (this->osd, this->class->font, this->font_size);
}
-
+
+ font_size = this->font_size;
+ this->renderer->set_encoding(this->osd, this->class->src_encoding);
+
+ for (line = 0; line < this->lines; line++) /* first, check lenghts and word-wrap if needed */
+ {
+ int w, h;
+ if( this->ogm )
+ w = ogm_get_width( this, this->text[line]);
+ else
+ this->renderer->get_text_size( this->osd, this->text[line], &w, &h);
+ if( w > this->width ) { /* line is too long */
+ int chunks=(int)(w/this->width)+(w%this->width?1:0);
+ if( this->lines+chunks <= SUB_MAX_TEXT && chunks>1 ) { /* try adding newlines while keeping existing ones */
+ int a;
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,"Partial subtitle line splitting in %i chunks\n",chunks);
+ for(a=this->lines-1;a>=0;a--) {
+ if(a>line) /* lines after the too-long one */
+ memcpy(this->text[a+chunks-1],this->text[a],SUB_BUFSIZE);
+ else if(a==line) { /* line to be splitted */
+ int b,len=strlen(this->text[line]);
+ char *p=this->text[line];
+ for(b=0;b<chunks;b++) {
+ char *c;
+ if(b==chunks-1) /* if we are reading the last chunk, copy it completly */
+ strncpy(this->text[line+b],p,SUB_BUFSIZE);
+ else {
+ for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--);
+ if(*c==' ') {
+ *c='\0';
+ if(b) /* we are reading something that has to be moved to another line */
+ strncpy(this->text[line+b],p,SUB_BUFSIZE);
+ p=c+1;
+ }
+ }
+ }
+ }
+ }
+ this->lines+=chunks-1;
+ } else { /* regenerate all the lines to find something that better fits */
+ char buf[SUB_BUFSIZE*SUB_MAX_TEXT];
+ int a,w,h,chunks;
+ buf[0]='\0';
+ for(a=0;a<this->lines;a++) {
+ if(a) {
+ int len=strlen(buf);
+ buf[len]=' ';
+ buf[len+1]='\0';
+ }
+ strcat(buf,this->text[a]);
+ }
+ if( this->ogm )
+ w = ogm_get_width( this, buf);
+ else
+ this->renderer->get_text_size( this->osd, buf, &w, &h);
+ chunks=(int)(w/this->width)+(w%this->width?1:0);
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Complete subtitle line splitting in %i chunks\n",chunks);
+ if(chunks<=SUB_MAX_TEXT) {/* if the length is over than SUB_MAX_TEXT*this->width nothing can be done */
+ int b,len=strlen(buf);
+ char *p=buf;
+ for(b=0;b<chunks;b++) {
+ char *c;
+ if(b==chunks-1) /* if we are reading the last chunk, copy it completly */
+ strncpy(this->text[b],p,SUB_BUFSIZE);
+ else {
+ for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--);
+ if(*c==' ') {
+ *c='\0';
+ strncpy(this->text[b],p,SUB_BUFSIZE);
+ p=c+1;
+ }
+ }
+ }
+ this->lines=chunks;
+ } else
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Subtitle too long to be splited\n");
+ line=this->lines;
+ }
+ }
+ }
+
+ font_size = this->font_size;
+ this->renderer->set_encoding(this->osd, this->class->src_encoding);
+
+ for (line = 0; line < this->lines; line++) /* first, check lenghts and word-wrap if needed */
+ {
+ int w, h;
+ if( this->ogm )
+ w = ogm_get_width( this, this->text[line]);
+ else
+ this->renderer->get_text_size( this->osd, this->text[line], &w, &h);
+ if( w > this->width ) { /* line is too long */
+ int chunks=(int)(w/this->width)+(w%this->width?1:0);
+ if( this->lines+chunks <= SUB_MAX_TEXT && chunks>1 ) { /* try adding newlines while keeping existing ones */
+ int a;
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,"Partial subtitle line splitting in %i chunks\n",chunks);
+ for(a=this->lines-1;a>=0;a--) {
+ if(a>line) /* lines after the too-long one */
+ memcpy(this->text[a+chunks-1],this->text[a],SUB_BUFSIZE);
+ else if(a==line) { /* line to be splitted */
+ int b,len=strlen(this->text[line]);
+ char *p=this->text[line];
+ for(b=0;b<chunks;b++) {
+ char *c;
+ if(b==chunks-1) /* if we are reading the last chunk, copy it completly */
+ strncpy(this->text[line+b],p,SUB_BUFSIZE);
+ else {
+ for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--);
+ if(*c==' ') {
+ *c='\0';
+ if(b) /* we are reading something that has to be moved to another line */
+ strncpy(this->text[line+b],p,SUB_BUFSIZE);
+ p=c+1;
+ }
+ }
+ }
+ }
+ }
+ this->lines+=chunks-1;
+ } else { /* regenerate all the lines to find something that better fits */
+ char buf[SUB_BUFSIZE*SUB_MAX_TEXT];
+ int a,w,h,chunks;
+ buf[0]='\0';
+ for(a=0;a<this->lines;a++) {
+ if(a) {
+ int len=strlen(buf);
+ buf[len]=' ';
+ buf[len+1]='\0';
+ }
+ strcat(buf,this->text[a]);
+ }
+ if( this->ogm )
+ w = ogm_get_width( this, buf);
+ else
+ this->renderer->get_text_size( this->osd, buf, &w, &h);
+ chunks=(int)(w/this->width)+(w%this->width?1:0);
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Complete subtitle line splitting in %i chunks\n",chunks);
+ if(chunks<=SUB_MAX_TEXT) {/* if the length is over than SUB_MAX_TEXT*this->width nothing can be done */
+ int b,len=strlen(buf);
+ char *p=buf;
+ for(b=0;b<chunks;b++) {
+ char *c;
+ if(b==chunks-1) /* if we are reading the last chunk, copy it completly */
+ strncpy(this->text[b],p,SUB_BUFSIZE);
+ else {
+ for(c=p+(int)(len/chunks)+(len%chunks?1:0);*c!=' ' && c>p && c!='\0';c--);
+ if(*c==' ') {
+ *c='\0';
+ strncpy(this->text[b],p,SUB_BUFSIZE);
+ p=c+1;
+ }
+ }
+ }
+ this->lines=chunks;
+ } else
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Subtitle too long to be splited\n");
+ line=this->lines;
+ }
+ }
+ }
+
if (this->last_lines)
this->renderer->filled_rect (this->osd, 0, this->line_height * (SUB_MAX_TEXT - this->last_lines),
this->width - 1, this->line_height * SUB_MAX_TEXT - 1, 0);
this->last_lines = this->lines;
-
y = (SUB_MAX_TEXT - this->lines) * this->line_height;
- font_size = this->font_size;
- this->renderer->set_encoding(this->osd, this->class->src_encoding);
-
for (line = 0; line < this->lines; line++) {
int w, h, x;