diff options
author | henry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-04-07 16:04:02 +0000 |
---|---|---|
committer | henry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-04-07 16:04:02 +0000 |
commit | 3f4505eabb260dca3cc0714d36f9c76632821771 (patch) | |
tree | 745dd9cb07e48e80849e6825463639bdc3f02470 | |
parent | bc745edb16dfcea782082205fba3ca854c6bd0c9 (diff) | |
download | mpv-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.1 | 11 | ||||
-rw-r--r-- | Gui/interface.c | 27 | ||||
-rw-r--r-- | cfg-common.h | 4 | ||||
-rw-r--r-- | find_sub.c | 56 | ||||
-rw-r--r-- | mencoder.c | 20 | ||||
-rw-r--r-- | mplayer.c | 137 | ||||
-rw-r--r-- | mplayer.h | 5 | ||||
-rw-r--r-- | subreader.c | 476 | ||||
-rw-r--r-- | subreader.h | 35 |
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; } } @@ -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 @@ -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_noex |