summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-04-07 16:04:02 +0000
committerhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-04-07 16:04:02 +0000
commit3f4505eabb260dca3cc0714d36f9c76632821771 (patch)
tree745dd9cb07e48e80849e6825463639bdc3f02470
parentbc745edb16dfcea782082205fba3ca854c6bd0c9 (diff)
downloadmpv-3f4505eabb260dca3cc0714d36f9c76632821771.tar.bz2
mpv-3f4505eabb260dca3cc0714d36f9c76632821771.tar.xz
support for multiple subtitle files by Marcin Wojdyr <wojdyr@unipress.waw.pl>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9871 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--DOCS/en/mplayer.111
-rw-r--r--Gui/interface.c27
-rw-r--r--cfg-common.h4
-rw-r--r--find_sub.c56
-rw-r--r--mencoder.c20
-rw-r--r--mplayer.c137
-rw-r--r--mplayer.h5
-rw-r--r--subreader.c476
-rw-r--r--subreader.h35
9 files changed, 533 insertions, 238 deletions
diff --git a/DOCS/en/mplayer.1 b/DOCS/en/mplayer.1
index a7b47c3615..5ca66eb46d 100644
--- a/DOCS/en/mplayer.1
+++ b/DOCS/en/mplayer.1
@@ -946,11 +946,13 @@ For the list of available subtitles, use with the \-v option and look at the
output.
.TP
.B \-slang <two\ letter\ country\ code> (also see \-sid option)
-Works only for DVD playback.
-Turns on/\:selects DVD subtitle language.
+For DVD playback, turns on/\:selects DVD subtitle language.
For the list of available subtitles, use with the \-v option and look at the
output.
+Otherwise, determines an optional subtitle suffix which gets a higher
+priority when searching for subtitles.
+
.I EXAMPLE:
.PD 0
.RSs
@@ -960,8 +962,9 @@ Selects Hungarian and falls back to English if Hungarian is not available.
.PD 1
.
.TP
-.B \-sub <subtitle\ file>
-Use/\:display this subtitle file.
+.B \-sub <subtitle\-file1,subtitle\-file2,...>
+Use/\:display these subtitle files. Only one file can be displayed
+at the same time and the files can be switched with 'j'.
.TP
.B \-sub-bg-alpha <0\-255>
Specify the alpha channel value for subtitles and OSD backgrounds.
diff --git a/Gui/interface.c b/Gui/interface.c
index 5313df7048..63777a7684 100644
--- a/Gui/interface.c
+++ b/Gui/interface.c
@@ -328,7 +328,7 @@ void guiInit( void )
if ( filename ) mplSetFileName( NULL,filename,STREAMTYPE_FILE );
if ( plCurrent && !filename ) mplSetFileName( plCurrent->path,plCurrent->name,STREAMTYPE_FILE );
- if ( sub_name ) guiSetFilename( guiIntfStruct.Subtitlename,sub_name );
+ if ( subdata ) guiSetFilename( guiIntfStruct.Subtitlename, subdata->filename );
#if defined( USE_OSD ) || defined( USE_SUB )
guiLoadFont();
#endif
@@ -416,19 +416,20 @@ void guiLoadFont( void )
#ifdef USE_SUB
extern mp_osd_obj_t* vo_osd_list;
+extern char **sub_name;
+
void guiLoadSubtitle( char * name )
{
if ( guiIntfStruct.Playing == 0 )
{
- guiIntfStruct.SubtitleChanged=1;
+ guiIntfStruct.SubtitleChanged=1; //what is this for? (mw)
return;
}
- if ( subtitles )
+ if ( subdata )
{
mp_msg( MSGT_GPLAYER,MSGL_INFO,"[gui] Delete subtitles.\n" );
- sub_free( subtitles );
- subtitles=NULL;
- gfree( (void **)&sub_name );
+ sub_free( subdata );
+ subdata=NULL;
vo_sub=NULL;
if ( vo_osd_list )
{
@@ -449,11 +450,15 @@ void guiLoadSubtitle( char * name )
}
if ( name )
{
- mp_msg( MSGT_GPLAYER,MSGL_INFO,"[gui] Delete Load subtitle: %s\n",name );
- sub_name=gstrdup( name );
- subtitles=sub_read_file( sub_name,guiIntfStruct.FPS );
- if ( !subtitles ) mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_CantLoadSub,name );
+ mp_msg( MSGT_GPLAYER,MSGL_INFO,"[gui] Load subtitle: %s\n",name );
+ subdata=sub_read_file( gstrdup( name ), guiIntfStruct.FPS );
+ if ( !subdata ) mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_CantLoadSub,name );
+ sub_name = (malloc(2 * sizeof(char*))); //when mplayer will be restarted
+ sub_name[0] = strdup(name); //sub_name[0] will be read
+ sub_name[1] = NULL;
}
+ update_set_of_subtitles();
+
}
#endif
@@ -797,7 +802,7 @@ int guiGetEvent( int type,char * arg )
#endif
// -- subtitle
#ifdef USE_SUB
- sub_name=gstrdup( guiIntfStruct.Subtitlename );
+ //subdata->filename=gstrdup( guiIntfStruct.Subtitlename );
stream_dump_type=0;
if ( gtkSubDumpMPSub ) stream_dump_type=4;
if ( gtkSubDumpSrt ) stream_dump_type=6;
diff --git a/cfg-common.h b/cfg-common.h
index d21ddcde0b..8d87504c1e 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -21,10 +21,10 @@
{"dvdangle", &dvd_angle, CONF_TYPE_INT, CONF_RANGE, 1, 99, NULL},
{"chapter", dvd_parse_chapter_range, CONF_TYPE_FUNC_PARAM, 0, 0, 0, NULL},
{"alang", &audio_lang, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"slang", &dvdsub_lang, CONF_TYPE_STRING, 0, 0, 0, NULL},
#else
{"dvd", "MPlayer was compiled WITHOUT libdvdread support!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
#endif
+ {"slang", &dvdsub_lang, CONF_TYPE_STRING, 0, 0, 0, NULL},
#ifdef HAVE_LIBCSS
{"dvdauth", &dvd_auth_device, CONF_TYPE_STRING, 0, 0, 0, NULL},
@@ -192,7 +192,7 @@
// ------------------------- subtitles options --------------------
#ifdef USE_SUB
- {"sub", &sub_name, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"sub", &sub_name, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
#ifdef USE_ICONV
{"subcp", &sub_cp, CONF_TYPE_STRING, 0, 0, 0, NULL},
#endif
diff --git a/find_sub.c b/find_sub.c
index e652bd518f..449788c877 100644
--- a/find_sub.c
+++ b/find_sub.c
@@ -21,11 +21,12 @@ static int nosub_range_end=-1;
extern float sub_delay;
extern float sub_fps;
-void step_sub(subtitle *subtitles, float pts, int movement) {
- int key = sub_uses_time ? (100*(pts+sub_delay)) : ((pts+sub_delay)*sub_fps);
+void step_sub(sub_data *subd, float pts, int movement) {
+ subtitle *subs;
+ int key = (pts+sub_delay) * (subd->sub_uses_time ? 100 : sub_fps);
- if (subtitles == NULL)
- return;
+ if (subd == NULL) return;
+ subs = subd->subtitles;
/* Tell the OSD subsystem that the OSD contents will change soon */
vo_osd_changed(OSDTYPE_SUBTITLE);
@@ -33,25 +34,27 @@ void step_sub(subtitle *subtitles, float pts, int movement) {
/* If we are moving forward, don't count the next (current) subtitle
* if we haven't displayed it yet. Same when moving other direction.
*/
- if (movement > 0 && key < subtitles[current_sub].start)
+ if (movement > 0 && key < subs[current_sub].start)
movement--;
- if (movement < 0 && key >= subtitles[current_sub].end)
+ if (movement < 0 && key >= subs[current_sub].end)
movement++;
/* Never move beyond first or last subtitle. */
if (current_sub+movement < 0)
movement = 0-current_sub;
- if (current_sub+movement >= sub_num)
- movement = sub_num-current_sub-1;
+ if (current_sub+movement >= subd->sub_num)
+ movement = subd->sub_num - current_sub - 1;
current_sub += movement;
- sub_delay = subtitles[current_sub].start/(sub_uses_time ? 100 : sub_fps) - pts;
+ sub_delay = subs[current_sub].start / (subd->sub_uses_time ? 100 : sub_fps) - pts;
}
-void find_sub(subtitle* subtitles,int key){
+void find_sub(sub_data* subd,int key){
+ subtitle *subs;
int i,j;
- if ( !subtitles ) return;
+ if ( !subd || subd->sub_num == 0) return;
+ subs = subd->subtitles;
if(vo_sub){
if(key>=vo_sub->start && key<=vo_sub->end) return; // OK!
@@ -71,28 +74,29 @@ void find_sub(subtitle* subtitles,int key){
// printf("\r---- sub changed ----\n");
// check next sub.
- if(current_sub>=0 && current_sub+1<sub_num){
- if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){
+ if(current_sub>=0 && current_sub+1 < subd->sub_num){
+ if(key>subs[current_sub].end && key<subs[current_sub+1].start){
// no sub
- nosub_range_start=subtitles[current_sub].end;
- nosub_range_end=subtitles[current_sub+1].start;
+ nosub_range_start=subs[current_sub].end;
+ nosub_range_end=subs[current_sub+1].start;
vo_sub=NULL;
return;
}
// next sub?
++current_sub;
- vo_sub=&subtitles[current_sub];
+ vo_sub=&subs[current_sub];
if(key>=vo_sub->start && key<=vo_sub->end) return; // OK!
}
// printf("\r---- sub log search... ----\n");
// use logarithmic search:
- i=0;j=sub_num-1;
-// printf("Searching %d in %d..%d\n",key,subtitles[i].start,subtitles[j].end);
+ i=0;
+ j = subd->sub_num - 1;
+// printf("Searching %d in %d..%d\n",key,subs[i].start,subs[j].end);
while(j>=i){
current_sub=(i+j+1)/2;
- vo_sub=&subtitles[current_sub];
+ vo_sub=&subs[current_sub];
if(key<vo_sub->start) j=current_sub-1;
else if(key>vo_sub->end) i=current_sub+1;
else return; // found!
@@ -110,10 +114,10 @@ void find_sub(subtitle* subtitles,int key){
return;
}
--current_sub;
- if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){
+ if(key>subs[current_sub].end && key<subs[current_sub+1].start){
// no sub
- nosub_range_start=subtitles[current_sub].end;
- nosub_range_end=subtitles[current_sub+1].start;
+ nosub_range_start=subs[current_sub].end;
+ nosub_range_end=subs[current_sub+1].start;
// printf("No sub... 1 \n");
vo_sub=NULL;
return;
@@ -121,7 +125,7 @@ void find_sub(subtitle* subtitles,int key){
printf("HEH???? ");
} else {
if(key<=vo_sub->end) printf("JAJJ! "); else
- if(current_sub+1>=sub_num){
+ if(current_sub+1 >= subd->sub_num){
// at the end?
nosub_range_start=vo_sub->end;
nosub_range_end=0x7FFFFFFF; // MAXINT
@@ -129,10 +133,10 @@ void find_sub(subtitle* subtitles,int key){
vo_sub=NULL;
return;
} else
- if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){
+ if(key>subs[current_sub].end && key<subs[current_sub+1].start){
// no sub
- nosub_range_start=subtitles[current_sub].end;
- nosub_range_end=subtitles[current_sub+1].start;
+ nosub_range_start=subs[current_sub].end;
+ nosub_range_end=subs[current_sub+1].start;
// printf("No sub... 2 \n");
vo_sub=NULL;
return;
diff --git a/mencoder.c b/mencoder.c
index 5965e21635..49776c1485 100644
--- a/mencoder.c
+++ b/mencoder.c
@@ -100,7 +100,7 @@ int video_id=-1;
int dvdsub_id=-1;
int vobsub_id=-1;
static char* audio_lang=NULL;
-static char* dvdsub_lang=NULL;
+char* dvdsub_lang=NULL;
static char* spudec_ifo=NULL;
static char** audio_codec_list=NULL; // override audio codec
@@ -163,7 +163,7 @@ static int play_n_frames_mf=-1;
// sub:
char *font_name=NULL;
float font_factor=0.75;
-char *sub_name=NULL;
+char **sub_name=NULL;
float sub_delay=0;
float sub_fps=0;
int sub_auto = 0;
@@ -171,7 +171,7 @@ int subcc_enabled=0;
int suboverlap_enabled = 1;
#ifdef USE_SUB
-static subtitle* subtitles=NULL;
+static sub_data* subdata=NULL;
float sub_last_pts = -303;
#endif
@@ -588,12 +588,12 @@ vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream-
// we know fps so now we can adjust subtitles time to ~6 seconds AST
// check .sub
// current_module="read_subtitles_file";
- if(sub_name){
- subtitles=sub_read_file(sub_name, sh_video->fps);
- if(!subtitles) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name);
+ if(sub_name && sub_name[0]){
+ subdata=sub_read_file(sub_name[0], sh_video->fps);
+ if(!subdata) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name[0]);
} else
if(sub_auto) { // auto load sub file ...
- subtitles=sub_read_file( filename ? sub_filename( get_path("sub/"), filename )
+ subdata=sub_read_file( filename ? sub_filenames( get_path("sub/"), filename )[0]
: "default.sub", sh_video->fps );
}
#endif
@@ -1226,11 +1226,13 @@ if(sh_audio && !demuxer2){
#ifdef USE_SUB
// find sub
- if(subtitles && sh_video->pts>0){
+ if(subdata && sh_video->pts>0){
float pts=sh_video->pts;
if(sub_fps==0) sub_fps=sh_video->fps;
if (pts > sub_last_pts || pts < sub_last_pts-1.0 ) {
- find_sub(subtitles,sub_uses_time?(100*(pts+sub_delay)):((pts+sub_delay)*sub_fps)); // FIXME! frame counter...
+ find_sub(subdata, (pts+sub_delay) *
+ (subdata->sub_uses_time? 100. : sub_fps));
+ // FIXME! frame counter...
sub_last_pts = pts;
}
}
diff --git a/mplayer.c b/mplayer.c
index 5106d12033..799748802f 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -231,7 +231,7 @@ int video_id=-1;
int dvdsub_id=-1;
int vobsub_id=-1;
static char* audio_lang=NULL;
-static char* dvdsub_lang=NULL;
+char* dvdsub_lang=NULL;
static char* spudec_ifo=NULL;
char* filename=NULL; //"MI2-Trailer.avi";
@@ -275,7 +275,7 @@ extern int vo_flags;
// sub:
char *font_name=NULL;
float font_factor=0.75;
-char *sub_name=NULL;
+char **sub_name=NULL;
float sub_delay=0;
float sub_fps=0;
int sub_auto = 1;
@@ -284,7 +284,9 @@ char *vobsub_name=NULL;
int subcc_enabled=0;
int suboverlap_enabled = 1;
#ifdef USE_SUB
-subtitle* subtitles=NULL;
+sub_data* set_of_subtitles[MAX_SUBTITLE_FILES];
+int set_of_sub_size = 0;
+int set_of_sub_pos = -1;
float sub_last_pts = -303;
#endif
@@ -637,6 +639,56 @@ int playtree_add_playlist(play_tree_t* entry)
static int play_tree_step = 1;
+#ifdef USE_SUB
+
+sub_data* subdata = NULL;
+
+void add_subtitles(char *filename, float fps, int silent)
+{
+ sub_data *subd;
+
+ if (filename == NULL) {
+ subd = (sub_data*)malloc(sizeof(sub_data));
+ subd->filename = strdup("none");
+ subd->subtitles = NULL;
+ subd->sub_uses_time = 1;
+ subd->sub_num = 0;
+ subd->sub_errs = 0;
+ set_of_subtitles[set_of_sub_size] = subd;
+ ++set_of_sub_size;
+ return;
+ }
+
+ subd = sub_read_file(filename, fps);
+ if(!subd && !silent)
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantLoadSub, filename);
+ if (subd == NULL || set_of_sub_size >= MAX_SUBTITLE_FILES) return;
+ set_of_subtitles[set_of_sub_size] = subd;
+ ++set_of_sub_size;
+ printf("SUB: added subtitle file (%d): %s\n", set_of_sub_size, filename);
+}
+
+void update_set_of_subtitles()
+ // subdata was changed, set_of_sub... have to be updated.
+{
+ int i;
+ if (set_of_sub_size > 0 && subdata == NULL) { // *subdata was deleted
+ for (i = set_of_sub_pos + 1; i < set_of_sub_size; ++i)
+ set_of_subtitles[i-1] = set_of_subtitles[i];
+ set_of_subtitles[set_of_sub_size-1] = NULL;
+ --set_of_sub_size;
+ if (set_of_sub_size > 0) subdata = set_of_subtitles[set_of_sub_pos=0];
+ }
+ else if (set_of_sub_size > 0 && subdata != NULL) { // *subdata was changed
+ set_of_subtitles[set_of_sub_pos] = subdata;
+ }
+ else if (set_of_sub_size <= 0 && subdata != NULL) { // *subdata was added
+ set_of_subtitles[set_of_sub_pos=set_of_sub_size] = subdata;
+ ++set_of_sub_size;
+ }
+}
+#endif
+
/*
* In Mac OS X the SDL-lib is built upon Cocoa. The easiest way to
* make it all work is to use the builtin SDL-bootstrap code, which
@@ -670,6 +722,7 @@ int osd_show_sub_pos = 0;
int osd_show_sub_visibility = 0;
int osd_show_sub_alignment = 0;
int osd_show_vobsub_changed = 0;
+int osd_show_sub_changed = 0;
int osd_show_percentage = 0;
int osd_show_tv_channel = 25;
@@ -678,6 +731,7 @@ int rtc_fd=-1;
//float a_frame=0; // Audio
int i;
+char *tmp;
int gui_no_filename=0;
@@ -1485,19 +1539,31 @@ if(sh_video) {
// check .sub
current_module="read_subtitles_file";
if(sub_name){
- subtitles=sub_read_file(sub_name, sh_video->fps);
- if(!subtitles) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name);
- } else
+ for (i = 0; sub_name[i] != NULL; ++i)
+ add_subtitles (sub_name[i], sh_video->fps, 0);
+ }
if(sub_auto) { // auto load sub file ...
- subtitles=sub_read_file( filename ? sub_filename( get_path("sub/"), filename )
- : "default.sub", sh_video->fps );
+ char **tmp = sub_filenames(get_path("sub/"), filename);
+ char **tmp2 = tmp;
+ while (*tmp2)
+ add_subtitles (*tmp2++, sh_video->fps, 0);
+ free(tmp);
+ if (set_of_sub_size == 0)
+ add_subtitles (get_path("default.sub"), sh_video->fps, 1);
+ if (set_of_sub_size > 0)
+ add_subtitles (NULL, sh_video->fps, 1);
+ }
+ if (set_of_sub_size > 0) {
+ osd_show_sub_changed = sh_video->fps;
+ subdata = set_of_subtitles[set_of_sub_pos=0];
+
+ if(stream_dump_type==3) list_sub_file(subdata);
+ if(stream_dump_type==4) dump_mpsub(subdata, sh_video->fps);
+ if(stream_dump_type==6) dump_srt(subdata, sh_video->fps);
+ if(stream_dump_type==7) dump_microdvd(subdata, sh_video->fps);
+ if(stream_dump_type==8) dump_jacosub(subdata, sh_video->fps);
+ if(stream_dump_type==9) dump_sami(subdata, sh_video->fps);
}
- if(subtitles && stream_dump_type==3) list_sub_file(subtitles);
- if(subtitles && stream_dump_type==4) dump_mpsub(subtitles, sh_video->fps);
- if(subtitles && stream_dump_type==6) dump_srt(subtitles, sh_video->fps);
- if(subtitles && stream_dump_type==7) dump_microdvd(subtitles, sh_video->fps);
- if(subtitles && stream_dump_type==8) dump_jacosub(subtitles, sh_video->fps);
- if(subtitles && stream_dump_type==9) dump_sami(subtitles, sh_video->fps);
}
#endif
@@ -2415,7 +2481,7 @@ if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
} break;
case MP_CMD_SUB_STEP : {
int movement = cmd->args[0].v.i;
- step_sub(subtitles, sh_video->pts, movement);
+ step_sub(subdata, sh_video->pts, movement);
osd_show_sub_delay = 9; // show the subdelay in OSD
} break;
case MP_CMD_OSD :
@@ -2787,8 +2853,17 @@ if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
if(new_id != vobsub_id)
osd_show_vobsub_changed = 9;
vobsub_id = new_id;
- break;
}
+#ifdef USE_SUB
+ else if (set_of_sub_size > 0){ //change subtitle file
+ set_of_sub_pos = (set_of_sub_pos + 1) % set_of_sub_size;
+ subdata = set_of_subtitles[set_of_sub_pos];
+ osd_show_sub_changed = sh_video->fps;
+ vo_sub = NULL;
+ vo_osd_changed(OSDTYPE_SUBTITLE);
+ }
+#endif
+ break;
case MP_CMD_SCREENSHOT :
if(vo_config_count) video_out->control(VOCTRL_SCREENSHOT, NULL);
break;
@@ -3199,6 +3274,20 @@ if(rel_seek_secs || abs_seek_pos){
snprintf(osd_text_tmp, 63, "Subtitles: (%d) %s", vobsub_id, language ? language : "unknown");
osd_show_vobsub_changed--;
} else
+#ifdef USE_SUB
+ if (osd_show_sub_changed) {
+ tmp = subdata->filename;
+ char *tmp2;
+ if (tmp2 = strrchr(tmp, '/')) {
+ tmp = tmp2+1;
+ }
+ snprintf(osd_text_tmp, 63, "Sub: (%d) %s%s",
+ set_of_sub_pos + 1,
+ strlen(tmp) < 20 ? "" : "...",
+ strlen(tmp) < 20 ? tmp : tmp+strlen(tmp)-19);
+ osd_show_sub_changed--;
+ } else
+#endif
if (osd_show_sub_delay) {
snprintf(osd_text_tmp, 63, "Sub delay: %d ms", ROUND(sub_delay*1000));
osd_show_sub_delay--;
@@ -3250,12 +3339,14 @@ if(rel_seek_secs || abs_seek_pos){
#ifdef USE_SUB
// find sub
- if(subtitles && sh_video->pts>0){
+ if(subdata && sh_video->pts>0){
float pts=sh_video->pts;
if(sub_fps==0) sub_fps=sh_video->fps;
current_module="find_sub";
if (pts > sub_last_pts || pts < sub_last_pts-1.0 ) {
- find_sub(subtitles,sub_uses_time?(100*(pts+sub_delay)):((pts+sub_delay)*sub_fps)); // FIXME! frame counter...
+ find_sub(subdata, (pts+sub_delay) *
+ (subdata->sub_uses_time ? 100. : sub_fps));
+ // FIXME! frame counter...
sub_last_pts = pts;
}
current_module=NULL;
@@ -3350,14 +3441,14 @@ if(benchmark){
uninit_player(INITED_ALL-(INITED_GUI+INITED_INPUT+(fixed_vo?INITED_VO:0)));
#ifdef USE_SUB
- if ( subtitles )
+ if ( set_of_sub_size > 0 )
{
current_module="sub_free";
- sub_free( subtitles );
- if ( sub_name ) free( sub_name );
- sub_name=NULL;
+ for (i = 0; i < set_of_sub_size; ++i)
+ sub_free( set_of_subtitles[i] );
+ set_of_sub_size = 0;
vo_sub=NULL;
- subtitles=NULL;
+ subdata=NULL;
}
#endif
diff --git a/mplayer.h b/mplayer.h
index 53cd267430..d27a454128 100644
--- a/mplayer.h
+++ b/mplayer.h
@@ -27,14 +27,14 @@ extern float font_factor;
extern float movie_aspect;
extern float force_fps;
-extern char * sub_name;
+//extern char **sub_name;
extern float sub_delay;
extern float sub_fps;
extern int sub_auto;
extern int sub_pos;
extern int sub_unicode;
extern char * sub_cp;
-extern subtitle* subtitles;
+extern sub_data* subdata; //currently used subtitles
extern subtitle* vo_sub;
extern int suboverlap_enabled;
@@ -59,5 +59,6 @@ extern int dvdsub_id;
extern int vobsub_id;
extern void exit_player(char* how);
+extern void update_set_of_subtitles();
#endif
diff --git a/subreader.c b/subreader.c
index f5fdf30831..bbbf6ea399 100644
--- a/subreader.c
+++ b/subreader.c
@@ -12,6 +12,9 @@
#include <string.h>
#include <ctype.h>
+#include <sys/types.h>
+#include <dirent.h>
+
#include "config.h"
#include "mp_msg.h"
#include "subreader.h"
@@ -26,15 +29,14 @@ char *sub_cp=NULL;
#include <fribidi/fribidi.h>
#endif
+extern char* dvdsub_lang;
+
/* Maximal length of line of a subtitle */
#define LINE_LEN 1000
-
static float mpsub_position=0;
+static float mpsub_multiplier=1.;
+static int sub_slacktime = 20000; //20 sec
-int sub_uses_time=0;
-int sub_errs=0;
-int sub_num=0; // number of subtitle structs
-int sub_slacktime=2000; // 20 seconds
int sub_no_text_pp=0; // 1 => do not apply text post-processing
// like {\...} elimination in SSA format.
@@ -87,7 +89,8 @@ subtitle *sub_read_line_sami(FILE *fd, subtitle *current) {
case 0: /* find "START=" or "Slacktime:" */
slacktime_s = strstr (s, "Slacktime:");
- if (slacktime_s) sub_slacktime = strtol (slacktime_s + 10, NULL, 0) / 10;
+ if (slacktime_s)
+ sub_slacktime = strtol (slacktime_s+10, NULL, 0) / 10;
s = strstr (s, "Start=");
if (s) {
@@ -532,9 +535,9 @@ subtitle *sub_read_line_mpsub(FILE *fd, subtitle *current) {
if (!fgets(line, LINE_LEN, fd)) return NULL;
} while (sscanf (line, "%f %f", &a, &b) !=2);
- mpsub_position += a*(sub_uses_time ? 100.0 : 1.0);
+ mpsub_position += a*mpsub_multiplier;
current->start=(int) mpsub_position;
- mpsub_position += b*(sub_uses_time ? 100.0 : 1.0);
+ mpsub_position += b*mpsub_multiplier;
current->end=(int) mpsub_position;
while (num < SUB_MAX_TEXT) {
@@ -860,7 +863,7 @@ subtitle *sub_read_line_jacosub(FILE * fd, subtitle * current)
return current;
}
-int sub_autodetect (FILE *fd) {
+int sub_autodetect (FILE *fd, int *uses_time) {
char line[LINE_LEN+1];
int i,j=0;
char p;
@@ -871,44 +874,44 @@ int sub_autodetect (FILE *fd) {
return SUB_INVALID;
if (sscanf (line, "{%d}{%d}", &i, &i)==2)
- {sub_uses_time=0;return SUB_MICRODVD;}
+ {*uses_time=0;return SUB_MICRODVD;}
if (sscanf (line, "{%d}{}", &i)==1)
- {sub_uses_time=0;return SUB_MICRODVD;}
+ {*uses_time=0;return SUB_MICRODVD;}
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_SUBRIP;}
+ {*uses_time=1;return SUB_SUBRIP;}
if (sscanf (line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d", &i, &i, &i, (char *)&i, &i, &i, &i, &i, (char *)&i, &i)==10)
- {sub_uses_time=1;return SUB_SUBVIEWER;}
+ {*uses_time=1;return SUB_SUBVIEWER;}
if (sscanf (line, "{T %d:%d:%d:%d",&i, &i, &i, &i))
- {sub_uses_time=1;return SUB_SUBVIEWER2;}
+ {*uses_time=1;return SUB_SUBVIEWER2;}
if (strstr (line, "<SAMI>"))
- {sub_uses_time=1; return SUB_SAMI;}
+ {*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;}
+ {*uses_time = 1; return SUB_JACOSUB;}
if (sscanf(line, "@%d @%d", &i, &i) == 2)
- {sub_uses_time = 1; return SUB_JACOSUB;}
+ {*uses_time = 1; return SUB_JACOSUB;}
if (sscanf (line, "%d:%d:%d:", &i, &i, &i )==3)
- {sub_uses_time=1;return SUB_VPLAYER;}
+ {*uses_time=1;return SUB_VPLAYER;}
if (sscanf (line, "%d:%d:%d ", &i, &i, &i )==3)
- {sub_uses_time=1;return SUB_VPLAYER;}
+ {*uses_time=1;return SUB_VPLAYER;}
//TODO: just checking if first line of sub starts with "<" is WAY
// too weak test for RT
// Please someone who knows the format of RT... FIX IT!!!
// It may conflict with other sub formats in the future (actually it doesn't)
if ( *line == '<' )
- {sub_uses_time=1;return SUB_RT;}
+ {*uses_time=1;return SUB_RT;}
if (!memcmp(line, "Dialogue: Marked", 16))
- {sub_uses_time=1; return SUB_SSA;}
+ {*uses_time=1; return SUB_SSA;}
if (sscanf (line, "%d,%d,\"%c", &i, &i, (char *) &i) == 3)
- {sub_uses_time=0;return SUB_DUNNOWHAT;}
+ {*uses_time=0;return SUB_DUNNOWHAT;}
if (sscanf (line, "FORMAT=%d", &i) == 1)
- {sub_uses_time=0; return SUB_MPSUB;}
+ {*uses_time=0; return SUB_MPSUB;}
if (sscanf (line, "FORMAT=TIM%c", &p)==1 && p=='E')
- {sub_uses_time=1; return SUB_MPSUB;}
+ {*uses_time=1; return SUB_MPSUB;}
if (strstr (line, "-->>"))
- {sub_uses_time=0; return SUB_AQTITLE;}
+ {*uses_time=0; return SUB_AQTITLE;}
if (sscanf (line, "[%d:%d:%d]", &i, &i, &i)==3)
- {sub_uses_time=1;return SUB_SUBRIP09;}
+ {*uses_time=1;return SUB_SUBRIP09;}
}
return SUB_INVALID; // too many bad lines
@@ -1071,7 +1074,8 @@ subtitle* sub_fribidi (subtitle *sub, int sub_utf8)
#endif
-static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block){
+static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block,
+ int sub_num, int sub_uses_time) {
int n,m;
subtitle* nextsub;
int i = sub_num;
@@ -1133,10 +1137,13 @@ struct subreader {
const char *name;
};
-subtitle* sub_read_file (char *filename, float fps) {
+sub_data* sub_read_file (char *filename, float fps) {
+ //filename is assumed to be malloc'ed, free() is used in sub_free()
FILE *fd;
int n_max, n_first, i, j, sub_first, sub_orig;
- subtitle *first, *second, *sub;
+ subtitle *first, *second, *sub, *return_sub;
+ sub_data *subt_data;
+ int uses_time = 0, sub_num = 0, sub_errs = 0;
struct subreader sr[]=
{
{ sub_read_line_microdvd, NULL, "microdvd" },
@@ -1158,7 +1165,8 @@ subtitle* sub_read_file (char *filename, float fps) {
if(filename==NULL) return NULL; //qnx segfault
fd=fopen (filename, "r"); if (!fd) return NULL;
- sub_format=sub_autodetect (fd);
+ sub_format=sub_autodetect (fd, &uses_time);
+ mpsub_multiplier = (uses_time ? 100.0 : 1.0);
if (sub_format==SUB_INVALID) {mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: Could not determine file format\n");return NULL;}
srp=sr+sub_format;
mp_msg(MSGT_SUBREADER,MSGL_INFO,"SUB: Detected subtitle file format: %s\n", srp->name);
@@ -1254,7 +1262,7 @@ subtitle* sub_read_file (char *filename, float fps) {
subcp_close();
#endif
-// printf ("SUB: Subtitle format %s time.\n", sub_uses_time?"uses":"doesn't use");
+// printf ("SUB: Subtitle format %s time.\n", uses_time?"uses":"doesn't use");
mp_msg(MSGT_SUBREADER,MSGL_INFO,"SUB: Read %i subtitles", sub_num);
if (sub_errs) mp_msg(MSGT_SUBREADER,MSGL_INFO,", %i bad line(s).\n", sub_errs);
else mp_msg(MSGT_SUBREADER,MSGL_INFO,".\n");
@@ -1270,7 +1278,7 @@ subtitle* sub_read_file (char *filename, float fps) {
// while in others they are probably result of bad timing
if ((suboverlap_enabled == 2) ||
((suboverlap_enabled) && ((sub_format == SUB_JACOSUB) || (sub_format == SUB_SSA)))) {
- adjust_subs_time(first, 6.0, fps, 0); /* ~6 secs AST */
+ adjust_subs_time(first, 6.0, fps, 0, sub_num, uses_time);/*~6 secs AST*/
// here we manage overlapping subtitles
sub_orig = sub_num;
n_first = sub_num;
@@ -1468,12 +1476,19 @@ if ((suboverlap_enabled == 2) ||
}
free(first);
- return second;
+ return_sub = second;
} else { //if(suboverlap_enabled)
- adjust_subs_time(first, 6.0, fps, 1); /* ~6 secs AST */
-
- return first;
+ adjust_subs_time(first, 6.0, fps, 1, sub_num, uses_time);/*~6 secs AST*/
+ return_sub = first;
}
+ if (return_sub == NULL) return NULL;
+ subt_data = (sub_data *)malloc(sizeof(sub_data));
+ subt_data->filename = filename;
+ subt_data->sub_uses_time = uses_time;
+ subt_data->sub_num = sub_num;
+ subt_data->sub_errs = sub_errs;
+ subt_data->subtitles = return_sub;
+ return subt_data;
}
#if 0
@@ -1489,80 +1504,243 @@ char * strreplace( char * in,char * what,char * whereof )
}
#endif
-char * sub_filename(char* path, char * fname )
+
+static void strcpy_trim(char *d, char *s)
{
- char * sub_name1;
- char * sub_name2;
- char * aviptr1, * aviptr2, * tmp;
- int i,j;
- FILE * f;
- int pos=0;
- char * sub_exts[] =
- { ".utf",
- ".UTF",
- ".sub",
- ".SUB",
- ".srt",
- ".SRT",
- ".smi",
- ".SMI",
- ".rt",
- ".RT",
- ".txt",
- ".TXT",
- ".ssa",
- ".SSA",
- ".aqt",
- ".AQT",
- ".jss",
- ".JSS" };
-
-
- if ( fname == NULL ) return NULL;
-
- sub_name1=strrchr(fname,'.');
- if (!sub_name1) return NULL;
- pos=sub_name1-fname;
-
- sub_name1=malloc(strlen(fname)+8);
- strcpy(sub_name1,fname);
-
- sub_name2=malloc (strlen(path) + strlen(fname) + 8);
- if ((tmp=strrchr(fname,'/')))
- sprintf (sub_name2, "%s%s", path, tmp+1);
- else
- sprintf (sub_name2, "%s%s", path, fname);
+ // skip leading whitespace
+ while (*s && !isalnum(*s)) {
+ s++;
+ }
+ for (;;) {
+ // copy word
+ while (*s && isalnum(*s)) {
+ *d = tolower(*s);
+ s++; d++;
+ }
+ if (*s == 0) break;
+ // trim excess whitespace
+ while (*s && !isalnum(*s)) {
+ s++;
+ }
+ if (*s == 0) break;
+ *d++ = ' ';
+ }
+ *d = 0;
+}
- aviptr1=strrchr(sub_name1,'.');
- aviptr2=strrchr(sub_name2,'.');
+static void strcpy_strip_ext(char *d, char *s)
+{
+ char *tmp = strrchr(s,'.');
+ if (!tmp) {
+ strcpy(d, s);
+ return;
+ } else {
+ strncpy(d, s, tmp-s);
+ d[tmp-s] = 0;
+ }
+ while (*d) {
+ *d = tolower(*d);
+ d++;
+ }
+}
- for(j=0;j<=1;j++){
- char* sub_name=j?sub_name1:sub_name2;
-#ifdef USE_ICONV
- for ( i=(sub_cp?2:0);i<(sizeof(sub_exts)/sizeof(char*));i++ ) {
-#else
- for ( i=0;i<(sizeof(sub_exts)/sizeof(char*));i++ ) {
-#endif
- strcpy(j?aviptr1:aviptr2,sub_exts[i]);
-// printf("trying: '%s'\n",sub_name);
- if((f=fopen( sub_name,"rt" ))) {
- fclose( f );
- mp_msg(MSGT_SUBREADER,MSGL_INFO,"SUB: Detected sub file: %s\n",sub_name );
- if (i<2) sub_utf8=1;
- return sub_name;
+static void strcpy_get_ext(char *d, char *s)
+{
+ char *tmp = strrchr(s,'.');
+ if (!tmp) {
+ strcpy(d, "");
+ return;
+ } else {
+ strcpy(d, tmp+1);
}
+}
+
+static int whiteonly(char *s)
+{
+ while (*s) {
+ if (isalnum(*s)) return 0;
+ s++;
}
- }
+ return 1;
+}
+
+typedef struct _subfn
+{
+ int priority;
+ char *fname;
+} subfn;
+
+static int compare_sub_priority(const void *a, const void *b)
+{
+ return ((subfn*)a)->priority < ((subfn*)b)->priority;
+}
+
+char** sub_filenames(char* path, char *fname)
+{
+ char *f_dir, *f_fname, *f_fname_noext, *f_fname_trim, *tmp, *tmp_sub_id;
+ char *tmp_fname_noext, *tmp_fname_trim, *tmp_fname_ext, *tmpresult;
+
+ int len, pos, found, i, j;
+ char * sub_exts[] = { "utf", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", NULL};
+ subfn *result;
+ char **result2;
+
+ int subcnt;
+
+ FILE *f;
+
+ DIR *d;
+ struct dirent *de;
+
+ len = (strlen(fname) > 256 ? strlen(fname) : 256)
+ +(strlen(path) > 256 ? strlen(path) : 256)+2;
+
+ f_dir = (char*)malloc(len);
+ f_fname = (char*)malloc(len);
+ f_fname_noext = (char*)malloc(len);
+ f_fname_trim = (char*)malloc(len);
+
+ tmp_fname_noext = (char*)malloc(len);
+ tmp_fname_trim = (char*)malloc(len);
+ tmp_fname_ext = (char*)malloc(len);
+
+ tmpresult = (char*)malloc(len);
+
+ result = (subfn*)malloc(sizeof(subfn)*MAX_SUBTITLE_FILES);
+ memset(result, 0, sizeof(subfn)*MAX_