📄 subtitle.c
字号:
strcat( psz_text, s ); strcat( psz_text, "\n" ); } p_subtitle->psz_text = psz_text; return VLC_SUCCESS;}static int ParseJSS( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx ){ VLC_UNUSED( i_idx ); demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text, *psz_orig; char *psz_text2, *psz_orig2; int h1, h2, m1, m2, s1, s2, f1, f2; if( !p_sys->jss.b_inited ) { p_sys->jss.i_comment = 0; p_sys->jss.i_time_resolution = 30; p_sys->jss.i_time_shift = 0; p_sys->jss.b_inited = true; } /* Parse the main lines */ for( ;; ) { const char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; psz_orig = malloc( strlen( s ) + 1 ); if( !psz_orig ) return VLC_ENOMEM; psz_text = psz_orig; /* Complete time lines */ if( sscanf( s, "%d:%d:%d.%d %d:%d:%d.%d %[^\n\r]", &h1, &m1, &s1, &f1, &h2, &m2, &s2, &f2, psz_text ) == 9 ) { p_subtitle->i_start = ( (int64_t)( h1 *3600 + m1 * 60 + s1 ) + (int64_t)( ( f1 + p_sys->jss.i_time_shift ) / p_sys->jss.i_time_resolution ) ) * 1000000; p_subtitle->i_stop = ( (int64_t)( h2 *3600 + m2 * 60 + s2 ) + (int64_t)( ( f2 + p_sys->jss.i_time_shift ) / p_sys->jss.i_time_resolution ) ) * 1000000; break; } /* Short time lines */ else if( sscanf( s, "@%d @%d %[^\n\r]", &f1, &f2, psz_text ) == 3 ) { p_subtitle->i_start = (int64_t)( ( f1 + p_sys->jss.i_time_shift ) / p_sys->jss.i_time_resolution * 1000000.0 ); p_subtitle->i_stop = (int64_t)( ( f2 + p_sys->jss.i_time_shift ) / p_sys->jss.i_time_resolution * 1000000.0 ); break; } /* General Directive lines */ /* Only TIME and SHIFT are supported so far */ else if( s[0] == '#' ) { int h = 0, m =0, sec = 1, f = 1; unsigned shift = 1; int inv = 1; strcpy( psz_text, s ); switch( toupper( psz_text[1] ) ) { case 'S': shift = isalpha( psz_text[2] ) ? 6 : 2 ; if( sscanf( &psz_text[shift], "%d", &h ) ) { /* Negative shifting */ if( h < 0 ) { h *= -1; inv = -1; } if( sscanf( &psz_text[shift], "%*d:%d", &m ) ) { if( sscanf( &psz_text[shift], "%*d:%*d:%d", &sec ) ) { sscanf( &psz_text[shift], "%*d:%*d:%*d.%d", &f ); } else { h = 0; sscanf( &psz_text[shift], "%d:%d.%d", &m, &sec, &f ); m *= inv; } } else { h = m = 0; sscanf( &psz_text[shift], "%d.%d", &sec, &f); sec *= inv; } p_sys->jss.i_time_shift = ( ( h * 3600 + m * 60 + sec ) * p_sys->jss.i_time_resolution + f ) * inv; } break; case 'T': shift = isalpha( psz_text[2] ) ? 8 : 2 ; sscanf( &psz_text[shift], "%d", &p_sys->jss.i_time_resolution ); break; } free( psz_orig ); continue; } else /* Unkown type line, probably a comment */ { free( psz_orig ); continue; } } while( psz_text[ strlen( psz_text ) - 1 ] == '\\' ) { const char *s2 = TextGetLine( txt ); if( !s2 ) return VLC_EGENERIC; int i_len = strlen( s2 ); if( i_len == 0 ) break; int i_old = strlen( psz_text ); psz_text = realloc( psz_text, i_old + i_len + 1 ); if( !psz_text ) return VLC_ENOMEM; psz_orig = psz_text; strcat( psz_text, s2 ); } /* Skip the blanks */ while( *psz_text == ' ' || *psz_text == '\t' ) psz_text++; /* Parse the directives */ if( isalpha( *psz_text ) || *psz_text == '[' ) { while( *psz_text != ' ' ) { psz_text++ ;}; /* Directives are NOT parsed yet */ /* This has probably a better place in a decoder ? */ /* directive = malloc( strlen( psz_text ) + 1 ); if( sscanf( psz_text, "%s %[^\n\r]", directive, psz_text2 ) == 2 )*/ } /* Skip the blanks after directives */ while( *psz_text == ' ' || *psz_text == '\t' ) psz_text++; /* Clean all the lines from inline comments and other stuffs */ psz_orig2 = calloc( strlen( psz_text) + 1, 1 ); psz_text2 = psz_orig2; for( ; *psz_text != '\0' && *psz_text != '\n' && *psz_text != '\r'; ) { switch( *psz_text ) { case '{': p_sys->jss.i_comment++; break; case '}': if( p_sys->jss.i_comment ) { p_sys->jss.i_comment = 0; if( (*(psz_text + 1 ) ) == ' ' ) psz_text++; } break; case '~': if( !p_sys->jss.i_comment ) { *psz_text2 = ' '; psz_text2++; } break; case ' ': case '\t': if( (*(psz_text + 1 ) ) == ' ' || (*(psz_text + 1 ) ) == '\t' ) break; if( !p_sys->jss.i_comment ) { *psz_text2 = ' '; psz_text2++; } break; case '\\': if( (*(psz_text + 1 ) ) == 'n' ) { *psz_text2 = '\n'; psz_text++; psz_text2++; break; } if( ( toupper(*(psz_text + 1 ) ) == 'C' ) || ( toupper(*(psz_text + 1 ) ) == 'F' ) ) { psz_text++; psz_text++; break; } if( (*(psz_text + 1 ) ) == 'B' || (*(psz_text + 1 ) ) == 'b' || (*(psz_text + 1 ) ) == 'I' || (*(psz_text + 1 ) ) == 'i' || (*(psz_text + 1 ) ) == 'U' || (*(psz_text + 1 ) ) == 'u' || (*(psz_text + 1 ) ) == 'D' || (*(psz_text + 1 ) ) == 'N' ) { psz_text++; break; } if( (*(psz_text + 1 ) ) == '~' || (*(psz_text + 1 ) ) == '{' || (*(psz_text + 1 ) ) == '\\' ) psz_text++; else if( *(psz_text + 1 ) == '\r' || *(psz_text + 1 ) == '\n' || *(psz_text + 1 ) == '\0' ) { psz_text++; } break; default: if( !p_sys->jss.i_comment ) { *psz_text2 = *psz_text; psz_text2++; } } psz_text++; } p_subtitle->psz_text = psz_orig2; msg_Dbg( p_demux, "%s", p_subtitle->psz_text ); free( psz_orig ); return VLC_SUCCESS;}static int ParsePSB( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx ){ VLC_UNUSED( i_idx ); demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text; int i; for( ;; ) { int h1, m1, s1; int h2, m2, s2; const char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; psz_text = malloc( strlen( s ) + 1 ); if( !psz_text ) return VLC_ENOMEM; if( sscanf( s, "{%d:%d:%d}{%d:%d:%d}%[^\r\n]", &h1, &m1, &s1, &h2, &m2, &s2, psz_text ) == 7 ) { p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 + (int64_t)m1 * 60*1000 + (int64_t)s1 * 1000 ) * 1000; p_subtitle->i_stop = ( (int64_t)h2 * 3600*1000 + (int64_t)m2 * 60*1000 + (int64_t)s2 * 1000 ) * 1000; break; } free( psz_text ); } /* replace | by \n */ for( i = 0; psz_text[i] != '\0'; i++ ) { if( psz_text[i] == '|' ) psz_text[i] = '\n'; } p_subtitle->psz_text = psz_text; return VLC_SUCCESS;}static int64_t ParseRealTime( char *psz, int *h, int *m, int *s, int *f ){ if( strlen( psz ) == 0 ) return 0; if( sscanf( psz, "%d:%d:%d.%d", h, m, s, f ) == 4 || sscanf( psz, "%d:%d.%d", m, s, f ) == 3 || sscanf( psz, "%d.%d", s, f ) == 2 || sscanf( psz, "%d:%d", m, s ) == 2 || sscanf( psz, "%d", s ) == 1 ) { return (int64_t)((( *h * 60 + *m ) * 60 ) + *s ) * 1000 * 1000 + (int64_t)*f * 10 * 1000; } else return VLC_EGENERIC;}static int ParseRealText( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx ){ VLC_UNUSED( i_idx ); demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text; char psz_end[12]= "", psz_begin[12] = ""; for( ;; ) { int h1 = 0, m1 = 0, s1 = 0, f1 = 0; int h2 = 0, m2 = 0, s2 = 0, f2 = 0; const char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; psz_text = malloc( strlen( s ) + 1 ); if( !psz_text ) return VLC_ENOMEM; /* Find the good begining. This removes extra spaces at the beginning of the line.*/ char *psz_temp = strcasestr( s, "<time"); if( psz_temp != NULL ) { /* Line has begin and end */ if( ( sscanf( psz_temp, "<%*[t|T]ime %*[b|B]egin=\"%[^\"]\" %*[e|E]nd=\"%[^\"]%*[^>]%[^\n\r]", psz_begin, psz_end, psz_text) != 3 ) && /* Line has begin and no end */ ( sscanf( psz_temp, "<%*[t|T]ime %*[b|B]egin=\"%[^\"]\"%*[^>]%[^\n\r]", psz_begin, psz_text ) != 2) ) /* Line is not recognized */ { free( psz_text ); continue; } /* Get the times */ int64_t i_time = ParseRealTime( psz_begin, &h1, &m1, &s1, &f1 ); if( i_time >= 0) { p_subtitle->i_start = i_time; } i_time = ParseRealTime( psz_end, &h2, &m2, &s2, &f2 ); if( i_time >= 0 ) { p_subtitle->i_stop = i_time; } break; } /* Line is not recognized */ else continue; free( psz_text ); } /* Get the following Lines */ for( ;; ) { const char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; int i_len = strlen( s ); if( i_len == 0 ) break; if( strcasestr( s, "<time" ) || strcasestr( s, "<clear/") ) { TextPreviousLine( txt ); break; } int i_old = strlen( psz_text ); psz_text = realloc( psz_text, i_old + i_len + 1 + 1 ); if( !psz_text ) return VLC_ENOMEM; strcat( psz_text, s ); strcat( psz_text, "\n" ); } /* Remove the starting ">" that remained after the sscanf */ memmove( &psz_text[0], &psz_text[1], strlen( psz_text ) ); p_subtitle->psz_text = psz_text; return VLC_SUCCESS;}static int ParseDKS( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx ){ VLC_UNUSED( i_idx ); demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text; for( ;; ) { int h1, m1, s1; int h2, m2, s2; char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; psz_text = malloc( strlen( s ) + 1 ); if( !psz_text ) return VLC_ENOMEM; if( sscanf( s, "[%d:%d:%d]%[^\r\n]", &h1, &m1, &s1, psz_text ) == 4 ) { p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 + (int64_t)m1 * 60*1000 + (int64_t)s1 * 1000 ) * 1000; char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; if( sscanf( s, "[%d:%d:%d]", &h2, &m2, &s2 ) == 3 ) p_subtitle->i_stop = ( (int64_t)h2 * 3600*1000 + (int64_t)m2 * 60*1000 + (int64_t)s2 * 1000 ) * 1000; break; } free( psz_text ); } /* replace [br] by \n */ char *p; while( ( p = strstr( psz_text, "[br]" ) ) ) { *p++ = '\n'; memmove( p, &p[3], strlen(&p[3])+1 ); } p_subtitle->psz_text = psz_text; return VLC_SUCCESS;}static int ParseSubViewer1( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx ){ VLC_UNUSED( i_idx ); demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text; for( ;; ) { int h1, m1, s1; int h2, m2, s2; char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; if( sscanf( s, "[%d:%d:%d]", &h1, &m1, &s1 ) == 3 ) { p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 + (int64_t)m1 * 60*1000 + (int64_t)s1 * 1000 ) * 1000; char *s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; psz_text = strdup( s ); if( !psz_text ) return VLC_ENOMEM; s = TextGetLine( txt ); if( !s ) return VLC_EGENERIC; if( sscanf( s, "[%d:%d:%d]", &h2, &m2, &s2 ) == 3 ) p_subtitle->i_stop = ( (int64_t)h2 * 3600*1000 + (int64_t)m2 * 60*1000 + (int64_t)s2 * 1000 ) * 1000; break; } } p_subtitle->psz_text = psz_text; return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -