forked from mia/Aegisub
Some refactoring and bug fixing to subtitle format stuff, and improved saving of srt, ttxt and microdvd.
Originally committed to SVN as r1259.
This commit is contained in:
parent
0aaedd7b49
commit
708622cc63
8 changed files with 112 additions and 146 deletions
|
@ -38,6 +38,7 @@
|
||||||
// Includes
|
// Includes
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
|
#include <wx/regex.h>
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_override.h"
|
#include "ass_override.h"
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
@ -544,22 +545,8 @@ void AssDialogue::ParseASSTags () {
|
||||||
//////////////
|
//////////////
|
||||||
// Strip tags
|
// Strip tags
|
||||||
void AssDialogue::StripTags () {
|
void AssDialogue::StripTags () {
|
||||||
using std::list;
|
static wxRegEx reg(_T("\\{[^\\{]*\\}"),wxRE_ADVANCED);
|
||||||
using std::vector;
|
reg.Replace(&Text,_T(""));
|
||||||
ParseASSTags();
|
|
||||||
vector<AssDialogueBlock*>::iterator next;
|
|
||||||
for (vector<AssDialogueBlock*>::iterator cur=Blocks.begin();cur!=Blocks.end();cur=next) {
|
|
||||||
next = cur;
|
|
||||||
next++;
|
|
||||||
// FIXME: doesn't this crash when there's too many override blocks in one line?
|
|
||||||
if ((*cur)->type == BLOCK_OVERRIDE) {
|
|
||||||
delete *cur;
|
|
||||||
Blocks.erase(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateText();
|
|
||||||
UpdateData();
|
|
||||||
ClearBlocks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -314,3 +314,83 @@ double SubtitleFormat::AskForFPS() {
|
||||||
// fubar
|
// fubar
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// Sort lines
|
||||||
|
void SubtitleFormat::SortLines() {
|
||||||
|
Line->sort(LessByPointedToValue<AssEntry>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
// Convert tags
|
||||||
|
void SubtitleFormat::ConvertTags(int format,wxString lineEnd) {
|
||||||
|
using std::list;
|
||||||
|
list<AssEntry*>::iterator next;
|
||||||
|
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||||
|
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
||||||
|
if (current) {
|
||||||
|
// Strip tags
|
||||||
|
if (format == 1) current->StripTags();
|
||||||
|
else if (format == 2) current->ConvertTagsToSRT();
|
||||||
|
|
||||||
|
// Replace line breaks
|
||||||
|
current->Text.Replace(_T("\\h"),_T(" "),true);
|
||||||
|
current->Text.Replace(_T("\\n"),lineEnd,true);
|
||||||
|
current->Text.Replace(_T("\\N"),lineEnd,true);
|
||||||
|
while (current->Text.Replace(lineEnd+lineEnd,lineEnd,true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Merge identical and/or overlapping lines
|
||||||
|
void SubtitleFormat::Merge(bool identical,bool overlaps,bool stripComments) {
|
||||||
|
using std::list;
|
||||||
|
list<AssEntry*>::iterator next;
|
||||||
|
list<AssEntry*>::iterator prev = Line->end();
|
||||||
|
AssDialogue *previous = NULL;
|
||||||
|
|
||||||
|
// Loop through each line
|
||||||
|
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur=next) {
|
||||||
|
next = cur;
|
||||||
|
next++;
|
||||||
|
|
||||||
|
// Dialogue line
|
||||||
|
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
||||||
|
if (current) {
|
||||||
|
// Strip comments and empty lines
|
||||||
|
if ((current->Comment && stripComments) || current->Text.IsEmpty()) {
|
||||||
|
delete *cur;
|
||||||
|
Line->erase(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proper line
|
||||||
|
else {
|
||||||
|
// Check for duplication
|
||||||
|
if (previous != NULL) {
|
||||||
|
if (previous->Text == current->Text) {
|
||||||
|
if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) {
|
||||||
|
current->Start = (current->Start < previous->Start ? current->Start : previous->Start);
|
||||||
|
current->End = (current->End > previous->End ? current->End : previous->End);
|
||||||
|
delete *prev;
|
||||||
|
Line->erase(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set as previous
|
||||||
|
prev = cur;
|
||||||
|
previous = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other line, delete it
|
||||||
|
else {
|
||||||
|
delete *cur;
|
||||||
|
Line->erase(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -64,8 +64,12 @@ private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::list<AssEntry*> *Line;
|
std::list<AssEntry*> *Line;
|
||||||
|
|
||||||
void CreateCopy();
|
void CreateCopy();
|
||||||
void ClearCopy();
|
void ClearCopy();
|
||||||
|
void SortLines();
|
||||||
|
void ConvertTags(int format,wxString lineEnd);
|
||||||
|
void Merge(bool identical,bool overlaps,bool stripComments);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void LoadDefault(bool defline=true);
|
void LoadDefault(bool defline=true);
|
||||||
|
|
|
@ -175,6 +175,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||||
else if (fps > 0.0) cfr.SetCFR(fps);
|
else if (fps > 0.0) cfr.SetCFR(fps);
|
||||||
else rate = &VFR_Output;
|
else rate = &VFR_Output;
|
||||||
|
|
||||||
|
// Convert file
|
||||||
|
CreateCopy();
|
||||||
|
SortLines();
|
||||||
|
Merge(true,true,true);
|
||||||
|
ConvertTags(1,_T("|"));
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
TextFileWriter file(filename,encoding);
|
TextFileWriter file(filename,encoding);
|
||||||
|
|
||||||
|
@ -191,11 +197,12 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||||
// Prepare data
|
// Prepare data
|
||||||
int start = rate->GetFrameAtTime(current->Start.GetMS(),true);
|
int start = rate->GetFrameAtTime(current->Start.GetMS(),true);
|
||||||
int end = rate->GetFrameAtTime(current->End.GetMS(),false);
|
int end = rate->GetFrameAtTime(current->End.GetMS(),false);
|
||||||
wxString text = current->Text;
|
|
||||||
text.Replace(_T("\\N"),_T("|"));
|
|
||||||
|
|
||||||
// Write data
|
// Write data
|
||||||
file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,text.c_str()));
|
file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,current->Text.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
ClearCopy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,9 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||||
|
|
||||||
// Convert to SRT
|
// Convert to SRT
|
||||||
CreateCopy();
|
CreateCopy();
|
||||||
ConvertToSRT();
|
SortLines();
|
||||||
|
Merge(true,true,true);
|
||||||
|
ConvertTags(2,_T("\r\n"));
|
||||||
|
|
||||||
// Write lines
|
// Write lines
|
||||||
int i=1;
|
int i=1;
|
||||||
|
@ -202,69 +204,7 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||||
}
|
}
|
||||||
else throw _T("Unexpected line type");
|
else throw _T("Unexpected line type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
ClearCopy();
|
ClearCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Convert line to SRT
|
|
||||||
void SRTSubtitleFormat::DialogueToSRT(AssDialogue *current,std::list<AssEntry*>::iterator prev) {
|
|
||||||
using std::list;
|
|
||||||
AssDialogue *previous;
|
|
||||||
if (prev != Line->end()) previous = AssEntry::GetAsDialogue(*prev);
|
|
||||||
else previous = NULL;
|
|
||||||
|
|
||||||
// Strip ASS tags
|
|
||||||
current->ConvertTagsToSRT();
|
|
||||||
|
|
||||||
// Join equal lines
|
|
||||||
if (previous != NULL) {
|
|
||||||
if (previous->Text == current->Text) {
|
|
||||||
if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) {
|
|
||||||
current->Start = (current->Start < previous->Start ? current->Start : previous->Start);
|
|
||||||
current->End = (current->End > previous->End ? current->End : previous->End);
|
|
||||||
delete *prev;
|
|
||||||
Line->erase(prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix line breaks
|
|
||||||
current->Text.Replace(_T("\\n"),_T("\r\n"),true);
|
|
||||||
current->Text.Replace(_T("\\N"),_T("\r\n"),true);
|
|
||||||
while (current->Text.Replace(_T("\r\n\r\n"),_T("\r\n"),true));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
// Converts whole file to SRT
|
|
||||||
void SRTSubtitleFormat::ConvertToSRT () {
|
|
||||||
using std::list;
|
|
||||||
|
|
||||||
// Sort lines
|
|
||||||
Line->sort(LessByPointedToValue<AssEntry>());
|
|
||||||
|
|
||||||
list<AssEntry*>::iterator next;
|
|
||||||
list<AssEntry*>::iterator prev = Line->end();
|
|
||||||
|
|
||||||
// Process lines
|
|
||||||
bool notfirst = false;
|
|
||||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur=next) {
|
|
||||||
next = cur;
|
|
||||||
next++;
|
|
||||||
|
|
||||||
// Dialogue line (not comment)
|
|
||||||
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
|
||||||
if (current && !current->Comment) {
|
|
||||||
DialogueToSRT(current,prev);
|
|
||||||
notfirst = true;
|
|
||||||
prev = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other line, delete it
|
|
||||||
else {
|
|
||||||
delete *cur;
|
|
||||||
Line->erase(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,10 +50,6 @@ class AssDialogue;
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// SRT reader/writer
|
// SRT reader/writer
|
||||||
class SRTSubtitleFormat : public SubtitleFormat {
|
class SRTSubtitleFormat : public SubtitleFormat {
|
||||||
private:
|
|
||||||
void ConvertToSRT();
|
|
||||||
void DialogueToSRT(AssDialogue *current,std::list<AssEntry*>::iterator prev);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString GetName();
|
wxString GetName();
|
||||||
wxArrayString GetReadWildcards();
|
wxArrayString GetReadWildcards();
|
||||||
|
|
|
@ -316,68 +316,21 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Convert line to TTXT
|
|
||||||
void TTXTSubtitleFormat::DialogueToTTXT(AssDialogue *current,std::list<AssEntry*>::iterator prev) {
|
|
||||||
using std::list;
|
|
||||||
AssDialogue *previous;
|
|
||||||
if (prev != Line->end()) previous = AssEntry::GetAsDialogue(*prev);
|
|
||||||
else previous = NULL;
|
|
||||||
|
|
||||||
// Strip ASS tags
|
|
||||||
current->StripTags();
|
|
||||||
|
|
||||||
// Join equal lines
|
|
||||||
if (previous != NULL) {
|
|
||||||
if (previous->Text == current->Text) {
|
|
||||||
if (abs(current->Start.GetMS() - previous->End.GetMS()) < 20) {
|
|
||||||
current->Start = (current->Start < previous->Start ? current->Start : previous->Start);
|
|
||||||
current->End = (current->End > previous->End ? current->End : previous->End);
|
|
||||||
delete *prev;
|
|
||||||
Line->erase(prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix line breaks
|
|
||||||
current->Text.Replace(_T("\\n"),_T("\r\n"),true);
|
|
||||||
current->Text.Replace(_T("\\N"),_T("\r\n"),true);
|
|
||||||
while (current->Text.Replace(_T("\r\n\r\n"),_T("\r\n"),true));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Converts whole file to TTXT
|
// Converts whole file to TTXT
|
||||||
void TTXTSubtitleFormat::ConvertToTTXT () {
|
void TTXTSubtitleFormat::ConvertToTTXT () {
|
||||||
using std::list;
|
// Convert
|
||||||
|
SortLines();
|
||||||
|
Merge(true,true,true);
|
||||||
|
ConvertTags(1,_T("\r\n"));
|
||||||
|
|
||||||
// Sort lines
|
// Find last line
|
||||||
Line->sort(LessByPointedToValue<AssEntry>());
|
|
||||||
|
|
||||||
// Prepare processing
|
|
||||||
list<AssEntry*>::iterator next;
|
|
||||||
list<AssEntry*>::iterator prev = Line->end();
|
|
||||||
AssTime lastTime;
|
AssTime lastTime;
|
||||||
|
for (std::list<AssEntry*>::reverse_iterator cur=Line->rbegin();cur!=Line->rend();cur++) {
|
||||||
// Process lines
|
AssDialogue *prev = AssEntry::GetAsDialogue(*cur);
|
||||||
bool notfirst = false;
|
if (prev) {
|
||||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur=next) {
|
lastTime = prev->End;
|
||||||
next = cur;
|
break;
|
||||||
next++;
|
|
||||||
|
|
||||||
// Dialogue line (not comment)
|
|
||||||
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
|
||||||
if (current && !current->Comment) {
|
|
||||||
DialogueToTTXT(current,prev);
|
|
||||||
notfirst = true;
|
|
||||||
prev = cur;
|
|
||||||
lastTime = current->End;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other line, delete it
|
|
||||||
else {
|
|
||||||
delete *cur;
|
|
||||||
Line->erase(cur);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ private:
|
||||||
void WriteLine(wxXmlNode *root,AssDialogue *line);
|
void WriteLine(wxXmlNode *root,AssDialogue *line);
|
||||||
|
|
||||||
void ConvertToTTXT();
|
void ConvertToTTXT();
|
||||||
void DialogueToTTXT(AssDialogue *current,std::list<AssEntry*>::iterator prev);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString GetName();
|
wxString GetName();
|
||||||
|
|
Loading…
Reference in a new issue