#include "StdAfx.h"
#include "LrcParser.h"
#include "../Utils/IoUtils.h"
#include <algorithm>
//CLrc
CLrc::CLrc(){
offset = 0;
m_modify = FALSE;
m_curLineTime = m_nextLineTime = 0.0;
}
CLrc::~CLrc(){
Destroy();
}
void CLrc::PutLrcLine(double t, const CString& value,int lineNo){
CString line = value;
line.Replace(_T("\t"), StringUtils::TAB_SPACE);
CLrcLine *lrcLine = new CLrcLine(t, line, lineNo);
m_lrcLineVector.push_back(lrcLine);
}
BOOL CLrc::IsValid(){
return !m_lrcLineVector.empty();
}
CString CLrc::GetShowLrcText(int type,const CString& flag){
int allSize = (int)m_lrcLineVector.size();
if(type == 0){
if(m_currentIndex >= 0 && m_currentIndex < allSize)
return m_lrcLineVector[m_currentIndex]->content;
}else if(type < 0){
CString txt;
for(int i=0;i<m_currentIndex;++i){
txt.Append(m_lrcLineVector[i]->content);
if(i < m_currentIndex - 1)
txt.Append(flag);
}
return txt;
}else{
CString txt;
for(int i=m_currentIndex+1;i< allSize;++i){
txt.Append(m_lrcLineVector[i]->content);
if(i < allSize - 1)
txt.Append(flag);
}
return txt;
}
return StringUtils::EMPTY_STRING;
}
BOOL CLrc::GetCurrentShowLrcLines(CStrArray* lrcLines,int count,int preCount){
if(lrcLines == NULL) return FALSE;
lrcLines->clear();
int start = m_currentIndex-count/2;
for(int i=start;i<start+count+preCount;++i){
if(i < 0 || i >= (int)m_lrcLineVector.size()){
lrcLines->push_back(StringUtils::EMPTY_STRING);
}else{
lrcLines->push_back(m_lrcLineVector[i]->content);
}
}
return TRUE;
}
double CLrc::GetCurrentTimeOffestPercent(){
if(m_lrcLineVector.empty()) return 0.0;
if(epsilon_equal(m_nextLineTime,m_curLineTime)) return 0.0;
double p = (m_currentTime-m_curLineTime)/(m_nextLineTime-m_curLineTime);
if(p >= 1.0) return 1.0;
return p;
}
double CLrc::GetCurrentTimeGap(){
if(m_lrcLineVector.empty()) return 0.0;
double gap = m_nextLineTime-m_curLineTime;
if(epsilon_equal(gap,0)){
if(m_currentIndex > 0 && m_currentIndex < (int)m_lrcLineVector.size())
return m_lrcLineVector[m_currentIndex]->time - m_lrcLineVector[m_currentIndex-1]->time;
else
return m_lrcLineVector[0]->time;
}
return gap;
}
int CLrc::SetCurrentTime(double t){
m_currentTime = t;
m_currentIndex = -1;
if(m_lrcLineVector.empty()){
m_curLineTime = m_nextLineTime = 0.0;
return m_currentIndex;
}
if(t <= m_lrcLineVector.front()->time){
m_curLineTime = 0.0;
m_nextLineTime = m_lrcLineVector.front()->time;
return m_currentIndex;
}
if(t >= m_lrcLineVector.back()->time){
m_curLineTime = m_nextLineTime = m_lrcLineVector.back()->time;
m_currentIndex = (int)m_lrcLineVector.size() - 1;
return m_currentIndex;
}
for(int i=0;i< (int)m_lrcLineVector.size() - 1;++i){
if(t >= m_lrcLineVector[i]->time && t < m_lrcLineVector[i+1]->time){
m_curLineTime = m_lrcLineVector[i]->time;
m_nextLineTime= m_lrcLineVector[i+1]->time;
m_currentIndex = i;
return m_currentIndex;
}
}
return m_currentIndex;
}
void CLrc::SortByTime(){
std::sort(m_lrcLineVector.begin(),m_lrcLineVector.end(), &CLrcLine::compare);
}
void CLrc::Destroy(){
name = author = album = by = filePath = StringUtils::EMPTY_STRING;
m_content.Empty();
offset = 0;
m_modify = FALSE;
for(int i=0;i< (int)m_lrcLineVector.size();++i){
delete m_lrcLineVector[i];
}
m_lrcLineVector.clear();
}
void CLrc::UpdateCurrentLineOffset(double t){
if(m_lrcLineVector.empty()) return;
m_modify = TRUE;
if(m_currentIndex < 0){
m_lrcLineVector.front()->time +=t;
}else if(m_currentIndex >= (int)m_lrcLineVector.size()){
m_lrcLineVector.back()->time +=t;
}else{
m_lrcLineVector[m_currentIndex]->time +=t;
}
}
void CLrc::UpdateLrcOffset(double t){
m_modify = TRUE;
for(int i=0;i< (int)m_lrcLineVector.size();++i){
m_lrcLineVector[i]->time += t;
}
}
const CString& CLrc::GetPlainText(const CString &flag){
if(m_content.IsEmpty()){
for(int i=0;i< (int)m_lrcLineVector.size();++i){
m_content.Append(m_lrcLineVector[i]->content);
m_content.Append(flag);
}
}
return m_content;
}
BOOL CLrc::IsModify(){
return m_modify;
}
void CLrc::SaveLrc(){
if(!m_modify || m_lrcLineVector.empty()) return;
CString content;
content.AppendFormat(_T("[ti:%s]\r\n"),name);
content.AppendFormat(_T("[ar:%s]\r\n"),author);
content.AppendFormat(_T("[al:%s]\r\n"),album);
content.AppendFormat(_T("[by:%s]\r\n"),by);
if(offset != 0)
content.AppendFormat(_T("[offset:%d]\r\n"),offset);
content.Append(_T("\r\n"));
std::sort(m_lrcLineVector.begin(),m_lrcLineVector.end(), &CLrcLine::compareByLineNo);
int lastIndex = 0;
CString lastValue;
double t;
int m,s,ms;
for(int i=0;i< (int)m_lrcLineVector.size();++i){
t = m_lrcLineVector[i]->time;
m = int(t/60);
s = int(t-m*60);
ms = (int)((t -(int)t)*100 + 0.5)%100;
if(m_lrcLineVector[i]->lineNo != lastIndex){
if(!lastValue.IsEmpty())
content.AppendFormat(_T("%s\r\n"),lastValue);
lastIndex = m_lrcLineVector[i]->lineNo;
lastValue.Format(_T("[%02d:%02d.%02d]%s"),m,s,ms,m_lrcLineVector[i]->content);
}else{
CString tempValue = lastValue;
lastValue.Format(_T("[%02d:%02d.%02d]%s"),m,s,ms,tempValue);
}
}
if(!lastValue.IsEmpty())
content.AppendFormat(_T("%s\r\n"),lastValue);
int bufLen;
char *pBuf = StringUtils::CString2_Chars(bufLen,content);
CIoUtils::WriteFile(filePath,pBuf,bufLen);
delete[] pBuf;
m_modify = FALSE;
}
//CLrcParser
BOOL CLrcParser::ParseLrc(CLrc *pLrc,const CString& lrcPath){
if(pLrc == NULL || lrcPath.IsEmpty()) return FALSE;
pLrc->Destroy();
CStdioFile file;
if(!file.Open(lrcPath,CFile::modeRead) || file.GetLength() == 0) return FALSE;
pLrc->filePath = lrcPath;
CString fileLine;
CStrArray lrcArray;
while(file.ReadString(fileLine)){
lrcArray.push_back(StringUtils::CString2_CString(fileLine));
}
file.Close();
CString line,value;
double t;
CStrArray tempArray;
int tSize;
for(int i=0;i<(int)lrcArray.size();++i){
line = lrcArray[i];
line.Trim();
if(line.IsEmpty())
continue;
StringUtils::GetSplitStrArray(&tempArray,line,_T("]"),TRUE);
tSize = (int)tempArray.size();
if(tSize >= 2){
value = tempArray[0];
if(value.Find(_T("[ti:")) == 0 && value.GetLength()>=5 ){
pLrc->name = value.Right(value.GetLength()-4);
continue;
}
if(value.Find(_T("[ar:")) == 0 && value.GetLength()>=5 ){
pLrc->author = value.Right(value.GetLength()-4);
continue;
}
if(value.Find(_T("[al:")) == 0 && value.GetLength()>=5 ){
pLrc->album = value.Right(value.GetLength()-4);
continue;
}
if(value.Find(_T("[by:")) == 0 && value.GetLength()>=5 ){
pLrc->by = value.Right(value.GetLength()-4);
continue;
}
if(value.Find(_T("[offset:")) == 0 && value.GetLength()>=9 ){
pLrc->offset = StringUtils::CString2_int(value.Right(value.GetLength()-8));
continue;
}
value = tempArray[tSize-1];
for(int j=0;j<tSize-1;++j){
t = GetLrcLineTime(tempArray[j]);
if(t != INT_MIN){
pLrc->PutLrcLine(t + pLrc->offset / 1000.0, value, i);
}
}
}
}
pLrc->SortByTime();
return TRUE;
}
double CLrcParser::GetLrcLineTime(CString str){
if(str.Left(1) == _T("[")) str.Delete(0);
CStrArray tempArray;
StringUtils::GetSplitStrArray(&tempArray,str,_T(":"));
if((int)tempArray.size() < 2) return -1.0;
return StringUtils::CString2_double(tempArray[0])*60.0+StringUtils::CString2_double(tempArray[1]);
}