📄 tsubreadermplayer.cpp
字号:
/*
* Subtitle reader with format autodetection
*
* Written by laaz
* Some code cleanup & realloc() by A'rpi/ESP-team
* dunnowhat sub format by szabi
*/
#include "stdafx.h"
#include "TsubreaderMplayer.h"
#include "TsubtitlesSettings.h"
#include "Tstream.h"
#include "Tconfig.h"
#include "ffdebug.h"
//========================================= TsubtitleParser =========================================
template<class tchar> TsubtitleParser<tchar>::TsubtitleParser(int Iformat,double Ifps,const TsubtitlesSettings *Icfg,const Tconfig *Iffcfg,Tsubreader *Isubreader):
TsubtitleParserBase(Iformat,Ifps),
cfg(Icfg),
ffcfg(Iffcfg),
textfix(Icfg,Iffcfg),
subreader(Isubreader),
textformat(Iffcfg->getHtmlColors())
{
}
template<class tchar> int TsubtitleParser<tchar>::eol(tchar p) {
return (p=='\r' || p=='\n' || p=='\0');
}
/* Remove leading and trailing space */
template<class tchar> void TsubtitleParser<tchar>::trail_space(tchar *s) {
int i = 0;
while (tchar_traits<tchar>::isspace((typename tchar_traits<tchar>::uchar_t)s[i])) ++i;
if (i) strcpy(s, s + i);
i = (int)strlen(s) - 1;
while (i > 0 && tchar_traits<tchar>::isspace((typename tchar_traits<tchar>::uchar_t)s[i])) s[i--] = '\0';
}
template<class tchar> Tsubtitle* TsubtitleParser<tchar>::store(TsubtitleTextBase<tchar> &sub)
{
sub.format(textformat);
sub.fix(textfix);
subreader->push_back(new TsubtitleTextBase<tchar>(sub));
return subreader->back();
}
template<class tchar> Tsubtitle* TsubtitleParserSami<tchar>::parse(Tstream &fd,int flags) {
tchar text[this->LINE_LEN+1], *p=NULL,*q;
int state;
/* read the first line */
if (!s)
if ((s = fd.fgets(line, this->LINE_LEN))==NULL) return NULL;
TsubtitleTextBase<tchar> current(this->format);
current.start = current.stop = 0;
state = 0;
do {
switch (state) {
case 0: /* find "START=" or "Slacktime:" */
slacktime_s = stristr (s, _L("Slacktime:"));
if (slacktime_s)
sub_slacktime = strtol (slacktime_s+10, NULL, 0) / 10;
s = (tchar*)stristr (s, _L("Start="));
if (s) {
int sec1000=strtol (s + 6, &s, 0);
current.start = this->hmsToTime(0,0,sec1000/1000,(sec1000%1000)/10);
/* eat '>' */
for (; *s != '>' && *s != '\0'; s++);
s++;
state = 1; continue;
}
break;
case 1: /* find (optionnal) "<P", skip other TAGs */
for (; *s == ' ' || *s == '\t'; s++); /* strip blanks, if any */
if (*s == '\0') break;
if (*s != '<') { state = 3; p = text; continue; } /* not a TAG */
s++;
if (*s == 'P' || *s == 'p') { s++; state = 2; continue; } /* found '<P' */
for (; *s != '>' && *s != '\0'; s++); /* skip remains of non-<P> TAG */
if (s == '\0')
break;
s++;
continue;
case 2: /* find ">" */
if ((s = strchr (s, '>'))!=NULL) { s++; state = 3; p = text; continue; }
break;
case 3: /* get all text until '<' appears */
if (*s == '\0') break;
else if (!_strnicmp (s, _L("<br>"), 4)) {
*p = '\0'; p = text; trail_space (text);
if (text[0] != '\0')
current.add(text);
s += 4;
}
else if ((*s == '{') && !sub_no_text_pp) { state = 5; ++s; continue; }
else if (*s == '<') { state = 4; }
else if (!_strnicmp (s, _L(" "), 6)) { *p++ = ' '; s += 6; }
else if (*s == '\t') { *p++ = ' '; s++; }
else if (*s == '\r' || *s == '\n') { s++; }
else *p++ = *s++;
/* skip duplicated space */
if (p > text + 2) if (*(p-1) == ' ' && *(p-2) == ' ') p--;
continue;
case 4: /* get current->end or skip <TAG> */
q = (tchar*)stristr (s, _L("Start="));
if (q) {
int sec1000=strtol (q + 6, &q, 0);
current.stop = this->hmsToTime(0,0, sec1000/1000,(sec1000%1000)/10-1);
*p = '\0'; trail_space (text);
if (text[0] != '\0')
current.add(text);
if (current.size() > 0) { state = 99; break; }
state = 0; continue;
}
s = strchr (s, '>');
if (s) { s++; state = 3; continue; }
break;
case 5: /* get rid of {...} text, but read the alignment code */
if ((*s == '\\') && (*(s + 1) == 'a') && !sub_no_text_pp) {
if (stristr(s, _L("\\a1")) != NULL) {
//current->alignment = SUB_ALIGNMENT_BOTTOMLEFT;
s = s + 3;
}
if (stristr(s, _L("\\a2")) != NULL) {
//current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
s = s + 3;
} else if (stristr(s, _L("\\a3")) != NULL) {
//current->alignment = SUB_ALIGNMENT_BOTTOMRIGHT;
s = s + 3;
} else if ((stristr(s, _L("\\a4")) != NULL) || (stristr(s, _L("\\a5")) != NULL) || (stristr(s, _L("\\a8")) != NULL)) {
//current->alignment = SUB_ALIGNMENT_TOPLEFT;
s = s + 3;
} else if (stristr(s, _L("\\a6")) != NULL) {
//current->alignment = SUB_ALIGNMENT_TOPCENTER;
s = s + 3;
} else if (stristr(s, _L("\\a7")) != NULL) {
//current->alignment = SUB_ALIGNMENT_TOPRIGHT;
s = s + 3;
} else if (stristr(s, _L("\\a9")) != NULL) {
//current->alignment = SUB_ALIGNMENT_MIDDLELEFT;
s = s + 3;
} else if (stristr(s, _L("\\a10")) != NULL) {
//current->alignment = SUB_ALIGNMENT_MIDDLECENTER;
s = s + 4;
} else if (stristr(s, _L("\\a11")) != NULL) {
//current->alignment = SUB_ALIGNMENT_MIDDLERIGHT;
s = s + 4;
}
}
if (*s == '}') state = 3;
++s;
continue;
}
/* read next line */
if (state != 99 && (s = fd.fgets (line, this->LINE_LEN))==NULL) {
if (current.start > 0) {
break; // if it is the last subtitle
} else {
return NULL;
}
}
} while (state != 99);
// For the last subtitle
if (current.stop <= 0) {
current.stop = current.start + this->hmsToTime(0,0,sub_slacktime/1000,(sub_slacktime%1000)/10);
*p = '\0'; trail_space (text);
if (text[0] != '\0')
current.add(text);
}
return store(current);
}
template<class tchar> const tchar* TsubtitleParser<tchar>::sub_readtext(const tchar *source, TsubtitleTextBase<tchar> &sub) {
int len=0;
const tchar *p=source;
// printf("src=%p dest=%p \n",source,dest);
while ( !eol(*p) && *p!= '|' ) {
p++,len++;
}
sub.add(source,len);
while (*p=='\r' || *p=='\n' || *p=='|') p++;
if (*p) return p; // not-last text field
else return NULL; // last text field
}
template<class tchar> Tsubtitle* TsubtitleParserMicrodvd<tchar>::parse(Tstream &fd,int flags) {
tchar line[this->LINE_LEN+1];
tchar line2[this->LINE_LEN+1];
const tchar *p, *next;
int start=0,stop=0;
bool skip;
do {
do {
if (!fd.fgets (line, this->LINE_LEN)) return NULL;
} while ((tchar_traits<tchar>::sscanf() (line,
_L("{%ld}{}%[^\r\n]"),
&start, line2) < 2) &&
(tchar_traits<tchar>::sscanf() (line,
_L("{%ld}{%ld}%[^\r\n]"),
&start, &stop, line2) < 3));
skip=false;
if (start==1 && stop==1)
{
tchar *e;double newfps;
if ((newfps=strtod(line2,&e))>0 && !*e)
{
this->fps=newfps;
skip=true;
}
}
} while (skip);
TsubtitleTextBase<tchar> current(this->format);
current.start=this->frameToTime(start);
current.stop =this->frameToTime(stop );
p=line2;
next=p;
while ((next =sub_readtext (next, current))!=NULL)
;
return store(current);
}
template<class tchar> Tsubtitle* TsubtitleParserSubrip<tchar>::parse(Tstream &fd,int flags) {
tchar line[this->LINE_LEN+1];
int a1,a2,a3,a4,b1,b2,b3,b4;
tchar *p=NULL, *q=NULL;
int len;
TsubtitleTextBase<tchar> current(this->format);
while (1) {
if (!fd.fgets (line, this->LINE_LEN)) return NULL;
if (flags&this->PARSETIME)
{
if (tchar_traits<tchar>::sscanf() (line, _L("%d:%d:%d.%d,%d:%d:%d.%d"),&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;
current.start = this->hmsToTime(a1,a2,a3,a4);
current.stop = this->hmsToTime(b1,b2,b3,b4);
if (!fd.fgets (line, this->LINE_LEN)) return NULL;
}
p=q=line;
for (;;) {
for (q=p,len=0; *p && *p!='\r' && *p!='\n' && *p!='|' && strncmp(p,_L("[br]"),4); p++,len++);
current.add(q,len);
if (!*p || *p=='\r' || *p=='\n') break;
if (*p=='|') p++;
else while (*p++!=']');
}
break;
}
return store(current);
}
template<class tchar> Tsubtitle* TsubtitleParserSubviewer<tchar>::parse(Tstream &fd,int flags) {
tchar line[this->LINE_LEN+1];
int a1,a2,a3,a4,b1,b2,b3,b4;
tchar *p=NULL;
int len;
TsubtitleTextBase<tchar> current(this->format);
TsubtitleParser<tchar>::textformat.resetProps();
while (!current.size()) {
if (flags&this->PARSETIME)
{
if (!fd.fgets (line, this->LINE_LEN)) return NULL;
int li;
if ((len=tchar_traits<tchar>::sscanf() (line, _L("%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d"),&a1,&a2,&a3,&li,&a4,&b1,&b2,&b3,&li,&b4)) < 10)
continue;
current.start = this->hmsToTime(a1,a2,a3,a4/10);
current.stop = this->hmsToTime(b1,b2,b3,b4/10);
}
for (;;) {
if (!fd.fgets (line, this->LINE_LEN)) goto end;//break;
len=0;
for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++);
if (len) {
int j=0,skip=0;
tchar *curptr0,*curptr=curptr0=(tchar*)_alloca((len+1)*sizeof(tchar));
for(; j<len; j++) {
/* let's filter html tags ::atmos */
/*
if(line[j]=='>') {
skip=0;
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -