forked from mia/Aegisub
Clean up SubtitleFormat
Document all of the SubtitleFormat methods. Add default implementations of CanReadFile and CanWriteFile that check against the appropriate wildcard list. Clean up and simplify a lot of very odd code. Throw typed exceptions in all subtitle readers rather than strings. Originally committed to SVN as r5617.
This commit is contained in:
parent
156885b56d
commit
4ec507f814
22 changed files with 511 additions and 1182 deletions
|
@ -104,16 +104,6 @@ void AssFile::Load(const wxString &_filename,wxString charset,bool addToRecent)
|
|||
catch (agi::UserCancelException const&) {
|
||||
return;
|
||||
}
|
||||
catch (const char *except) {
|
||||
wxMessageBox(except,"Error loading file",wxICON_ERROR | wxOK);
|
||||
return;
|
||||
}
|
||||
|
||||
catch (wxString &except) {
|
||||
wxMessageBox(except,"Error loading file",wxICON_ERROR | wxOK);
|
||||
return;
|
||||
}
|
||||
|
||||
// Real exception
|
||||
catch (agi::Exception &e) {
|
||||
wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxICON_ERROR|wxOK);
|
||||
|
|
|
@ -360,6 +360,7 @@ namespace Automation4 {
|
|||
///
|
||||
FeatureSubtitleFormat::FeatureSubtitleFormat(const wxString &_name, const wxString &_extension)
|
||||
: Feature(SCRIPTFEATURE_SUBFORMAT, _name)
|
||||
, SubtitleFormat(_name)
|
||||
, extension(_extension)
|
||||
{
|
||||
// nothing to do
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
|
||||
#endif
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "subtitle_format.h"
|
||||
#include "subtitle_format_ass.h"
|
||||
|
@ -52,47 +53,42 @@
|
|||
#include "subtitle_format_transtation.h"
|
||||
#include "subtitle_format_ttxt.h"
|
||||
#include "subtitle_format_txt.h"
|
||||
#include "utils.h"
|
||||
#include "video_context.h"
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
SubtitleFormat::SubtitleFormat() {
|
||||
Line = NULL;
|
||||
Register();
|
||||
isCopy = false;
|
||||
using namespace std::tr1::placeholders;
|
||||
|
||||
SubtitleFormat::SubtitleFormat(wxString const& name)
|
||||
: name(name)
|
||||
, isCopy(0)
|
||||
, Line(0)
|
||||
{
|
||||
formats.push_back(this);
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
SubtitleFormat::~SubtitleFormat () {
|
||||
Remove();
|
||||
SubtitleFormat::~SubtitleFormat() {
|
||||
formats.remove(this);
|
||||
}
|
||||
|
||||
/// DOCME
|
||||
std::list<SubtitleFormat*> SubtitleFormat::formats;
|
||||
|
||||
/// DOCME
|
||||
bool SubtitleFormat::loaded = false;
|
||||
|
||||
/// @brief Set target
|
||||
/// @param file
|
||||
///
|
||||
void SubtitleFormat::SetTarget(AssFile *file) {
|
||||
ClearCopy();
|
||||
if (!file) Line = NULL;
|
||||
else Line = &file->Line;
|
||||
Line = file ? &file->Line : 0;
|
||||
assFile = file;
|
||||
}
|
||||
|
||||
/// @brief Create copy
|
||||
///
|
||||
bool SubtitleFormat::CanReadFile(wxString const& filename) const {
|
||||
return GetReadWildcards().Index(filename.AfterLast('.'), false) != wxNOT_FOUND;
|
||||
}
|
||||
|
||||
bool SubtitleFormat::CanWriteFile(wxString const& filename) const {
|
||||
return GetWriteWildcards().Index(filename.AfterLast('.'), false) != wxNOT_FOUND;
|
||||
}
|
||||
|
||||
void SubtitleFormat::CreateCopy() {
|
||||
SetTarget(new AssFile(*assFile));
|
||||
isCopy = true;
|
||||
}
|
||||
|
||||
/// @brief Clear copy
|
||||
///
|
||||
void SubtitleFormat::ClearCopy() {
|
||||
if (isCopy) {
|
||||
delete assFile;
|
||||
|
@ -101,184 +97,19 @@ void SubtitleFormat::ClearCopy() {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief Clear subtitles
|
||||
///
|
||||
void SubtitleFormat::Clear() {
|
||||
assFile->Clear();
|
||||
}
|
||||
|
||||
/// @brief Load default
|
||||
/// @param defline
|
||||
///
|
||||
void SubtitleFormat::LoadDefault(bool defline) {
|
||||
assFile->LoadDefault(defline);
|
||||
}
|
||||
|
||||
/// @brief Add line
|
||||
/// @param data
|
||||
/// @param group
|
||||
/// @param version
|
||||
/// @param outgroup
|
||||
void SubtitleFormat::AddLine(wxString data,wxString group,int &version,wxString *outgroup) {
|
||||
assFile->AddLine(data,group,version,outgroup);
|
||||
}
|
||||
|
||||
/// @brief Add formats
|
||||
///
|
||||
void SubtitleFormat::LoadFormats () {
|
||||
if (!loaded) {
|
||||
new ASSSubtitleFormat();
|
||||
new SRTSubtitleFormat();
|
||||
new TXTSubtitleFormat();
|
||||
new TTXTSubtitleFormat();
|
||||
new MicroDVDSubtitleFormat();
|
||||
new MKVSubtitleFormat();
|
||||
new EncoreSubtitleFormat();
|
||||
new TranStationSubtitleFormat();
|
||||
#ifdef _DEBUG
|
||||
new DVDSubtitleFormat();
|
||||
#endif
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
/// @brief Destroy formats
|
||||
///
|
||||
void SubtitleFormat::DestroyFormats () {
|
||||
std::list<SubtitleFormat*>::iterator cur;
|
||||
for (cur=formats.begin();cur!=formats.end();cur = formats.begin()) {
|
||||
delete *cur;
|
||||
}
|
||||
formats.clear();
|
||||
}
|
||||
|
||||
/// @brief Get an appropriate reader
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
SubtitleFormat *SubtitleFormat::GetReader(wxString filename) {
|
||||
LoadFormats();
|
||||
std::list<SubtitleFormat*>::iterator cur;
|
||||
SubtitleFormat *reader;
|
||||
for (cur=formats.begin();cur!=formats.end();cur++) {
|
||||
reader = *cur;
|
||||
if (reader->CanReadFile(filename)) return reader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Get an appropriate writer
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
SubtitleFormat *SubtitleFormat::GetWriter(wxString filename) {
|
||||
LoadFormats();
|
||||
std::list<SubtitleFormat*>::iterator cur;
|
||||
SubtitleFormat *writer;
|
||||
for (cur=formats.begin();cur!=formats.end();cur++) {
|
||||
writer = *cur;
|
||||
if (writer->CanWriteFile(filename)) return writer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Register
|
||||
/// @return
|
||||
///
|
||||
void SubtitleFormat::Register() {
|
||||
std::list<SubtitleFormat*>::iterator cur;
|
||||
for (cur=formats.begin();cur!=formats.end();cur++) {
|
||||
if (*cur == this) return;
|
||||
}
|
||||
formats.push_back(this);
|
||||
}
|
||||
|
||||
/// @brief Remove
|
||||
/// @return
|
||||
///
|
||||
void SubtitleFormat::Remove() {
|
||||
std::list<SubtitleFormat*>::iterator cur;
|
||||
for (cur=formats.begin();cur!=formats.end();cur++) {
|
||||
if (*cur == this) {
|
||||
formats.erase(cur);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString SubtitleFormat::GetReadWildcards() {
|
||||
return wxArrayString();
|
||||
}
|
||||
|
||||
/// @brief Get write wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString SubtitleFormat::GetWriteWildcards() {
|
||||
return wxArrayString();
|
||||
}
|
||||
|
||||
/// @brief Get wildcard list
|
||||
/// @param mode
|
||||
/// @return
|
||||
///
|
||||
wxString SubtitleFormat::GetWildcards(int mode) {
|
||||
// Ensure it's loaded
|
||||
LoadFormats();
|
||||
|
||||
// Variables
|
||||
wxArrayString all;
|
||||
wxArrayString cur;
|
||||
wxString wild;
|
||||
wxString final;
|
||||
wxString temp1;
|
||||
wxString temp2;
|
||||
|
||||
// For each format
|
||||
std::list<SubtitleFormat*>::iterator curIter;
|
||||
SubtitleFormat *format;
|
||||
for (curIter=formats.begin();curIter!=formats.end();curIter++) {
|
||||
// Get list
|
||||
format = *curIter;
|
||||
if (mode == 0) cur = format->GetReadWildcards();
|
||||
else if (mode == 1) cur = format->GetWriteWildcards();
|
||||
temp1.Clear();
|
||||
temp2.Clear();
|
||||
|
||||
// Has wildcards
|
||||
if (cur.Count()) {
|
||||
// Process entries
|
||||
for (unsigned int i=0;i<cur.Count();i++) {
|
||||
wild = "*." + cur[i];
|
||||
all.Add(wild);
|
||||
temp1 += wild + ",";
|
||||
temp2 += wild + ";";
|
||||
}
|
||||
|
||||
// Assemble final name
|
||||
final += format->GetName() + " (" + temp1.Left(temp1.Length()-1) + ")|" + temp2.Left(temp2.Length()-1) + "|";
|
||||
}
|
||||
}
|
||||
|
||||
// Add "all formats" list
|
||||
temp1.Clear();
|
||||
temp2.Clear();
|
||||
for (unsigned int i=0;i<all.Count();i++) {
|
||||
temp1 += all[i] + ",";
|
||||
temp2 += all[i] + ";";
|
||||
}
|
||||
final = wxString(_("All Supported Formats")) + " (" + temp1.Left(temp1.Length()-1) + ")|" + temp2.Left(temp2.Length()-1) + "|" + final.Left(final.Length()-1);
|
||||
|
||||
// Return final list
|
||||
return final;
|
||||
void SubtitleFormat::AddLine(wxString data, wxString group, int &version, wxString *outgroup) {
|
||||
assFile->AddLine(data, group, version, outgroup);
|
||||
}
|
||||
|
||||
/// @brief Ask the user to enter the FPS
|
||||
/// @param showSMPTE
|
||||
/// @return
|
||||
///
|
||||
SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
||||
wxArrayString choices;
|
||||
FPSRational fps_rat;
|
||||
|
@ -290,8 +121,8 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
|||
if (vidLoaded) {
|
||||
wxString vidFPS;
|
||||
if (context->FPS().IsVFR()) vidFPS = "VFR";
|
||||
else vidFPS = wxString::Format("%.3f",context->FPS().FPS());
|
||||
choices.Add(wxString::Format("From video (%s)",vidFPS));
|
||||
else vidFPS = wxString::Format("%.3f", context->FPS().FPS());
|
||||
choices.Add(wxString::Format("From video (%s)", vidFPS));
|
||||
}
|
||||
|
||||
// Standard FPS values
|
||||
|
@ -310,7 +141,7 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
|||
choices.Add(_("120.000 FPS"));
|
||||
|
||||
// Ask
|
||||
int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"),_("FPS"),choices);
|
||||
int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"), _("FPS"), choices);
|
||||
if (choice == -1) {
|
||||
fps_rat.num = 0;
|
||||
fps_rat.den = 0;
|
||||
|
@ -364,191 +195,143 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
|||
return fps_rat;
|
||||
}
|
||||
|
||||
/// @brief Sort lines
|
||||
///
|
||||
void SubtitleFormat::SortLines() {
|
||||
AssFile::Sort(*Line);
|
||||
}
|
||||
|
||||
/// @brief Convert tags
|
||||
/// @param format
|
||||
/// @param lineEnd
|
||||
///
|
||||
void SubtitleFormat::ConvertTags(int format,const wxString &lineEnd,bool mergeLineBreaks) {
|
||||
using std::list;
|
||||
list<AssEntry*>::iterator next;
|
||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (current) {
|
||||
void SubtitleFormat::ConvertTags(int format, const wxString &lineEnd, bool mergeLineBreaks) {
|
||||
for (std::list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); ++cur) {
|
||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||
// Strip tags
|
||||
if (format == 1) current->StripTags();
|
||||
else if (format == 2) current->ConvertTagsToSRT();
|
||||
|
||||
// Replace line breaks
|
||||
current->Text.Replace("\\h"," ",true);
|
||||
current->Text.Replace("\\n",lineEnd,true);
|
||||
current->Text.Replace("\\N",lineEnd,true);
|
||||
current->Text.Replace("\\h", " ");
|
||||
current->Text.Replace("\\n", lineEnd);
|
||||
current->Text.Replace("\\N", lineEnd);
|
||||
if (mergeLineBreaks) {
|
||||
while (current->Text.Replace(lineEnd+lineEnd,lineEnd,true)) {};
|
||||
while (current->Text.Replace(lineEnd+lineEnd, lineEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Remove all comment lines
|
||||
///
|
||||
void SubtitleFormat::StripComments() {
|
||||
using std::list;
|
||||
list<AssEntry*>::iterator next;
|
||||
|
||||
for (list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); cur = next) {
|
||||
next = cur;
|
||||
next++;
|
||||
|
||||
AssDialogue *dlg = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (dlg && (dlg->Comment || dlg->Text.IsEmpty())) {
|
||||
delete *cur;
|
||||
Line->erase(cur);
|
||||
for (std::list<AssEntry*>::iterator it = Line->begin(); it != Line->end(); ) {
|
||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(*it);
|
||||
if (!diag || (!diag->Comment && diag->Text.size()))
|
||||
++it;
|
||||
else {
|
||||
delete *it;
|
||||
Line->erase(it++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Remove all non-dialogue lines
|
||||
///
|
||||
void SubtitleFormat::StripNonDialogue() {
|
||||
using std::list;
|
||||
list<AssEntry*>::iterator next;
|
||||
|
||||
for (list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); cur = next) {
|
||||
next = cur;
|
||||
next++;
|
||||
|
||||
if (!dynamic_cast<AssDialogue*>(*cur)) {
|
||||
delete *cur;
|
||||
Line->erase(cur);
|
||||
for (std::list<AssEntry*>::iterator it = Line->begin(); it != Line->end(); ) {
|
||||
if (dynamic_cast<AssDialogue*>(*it))
|
||||
++it;
|
||||
else {
|
||||
delete *it;
|
||||
Line->erase(it++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Helper function for RecombineOverlaps()
|
||||
/// @param list
|
||||
/// @param next
|
||||
/// @param newdlg
|
||||
///
|
||||
static void InsertLineSortedIntoList(std::list<AssEntry*> &list, std::list<AssEntry*>::iterator next, AssDialogue *newdlg) {
|
||||
std::list<AssEntry*>::iterator insertpos = next;
|
||||
bool inserted = false;
|
||||
while (insertpos != list.end()) {
|
||||
AssDialogue *candidate = dynamic_cast<AssDialogue*>(*insertpos);
|
||||
if (candidate && candidate->Start >= newdlg->Start) {
|
||||
list.insert(insertpos, newdlg);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
insertpos++;
|
||||
}
|
||||
if (!inserted) {
|
||||
list.push_back(newdlg);
|
||||
}
|
||||
static bool dialog_start_lt(AssEntry *pos, AssDialogue *to_insert) {
|
||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(pos);
|
||||
return diag && diag->Start > to_insert->Start;
|
||||
}
|
||||
|
||||
/// @brief Split and merge lines so there are no overlapping lines
|
||||
///
|
||||
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
||||
void SubtitleFormat::RecombineOverlaps() {
|
||||
using std::list;
|
||||
list<AssEntry*>::iterator next;
|
||||
|
||||
for (list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); cur = next) {
|
||||
next = cur;
|
||||
next++;
|
||||
|
||||
if (next == Line->end()) break;
|
||||
|
||||
std::list<AssEntry*>::iterator cur, next = Line->begin();
|
||||
cur = next++;
|
||||
|
||||
for (; next != Line->end(); cur = next++) {
|
||||
AssDialogue *prevdlg = dynamic_cast<AssDialogue*>(*cur);
|
||||
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(*next);
|
||||
|
||||
if (curdlg && prevdlg && prevdlg->End > curdlg->Start) {
|
||||
// Use names like in the algorithm description and prepare for erasing
|
||||
// old dialogues from the list
|
||||
list<AssEntry*>::iterator prev = cur;
|
||||
cur = next;
|
||||
next++;
|
||||
|
||||
// std::list::insert() inserts items before the given iterator, so
|
||||
// we need 'next' for inserting. 'prev' and 'cur' can safely be erased
|
||||
// from the list now.
|
||||
Line->erase(prev);
|
||||
Line->erase(cur);
|
||||
|
||||
//Is there an A part before the overlap?
|
||||
if (curdlg->Start > prevdlg->Start) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = prevdlg->Start;
|
||||
newdlg->End = curdlg->Start;
|
||||
newdlg->Text = prevdlg->Text;
|
||||
|
||||
InsertLineSortedIntoList(*Line, next, newdlg);
|
||||
}
|
||||
|
||||
// Overlapping A+B part
|
||||
{
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = curdlg->Start;
|
||||
newdlg->End = (prevdlg->End < curdlg->End) ? prevdlg->End : curdlg->End;
|
||||
// Put an ASS format hard linewrap between lines
|
||||
newdlg->Text = curdlg->Text + "\\N" + prevdlg->Text;
|
||||
|
||||
InsertLineSortedIntoList(*Line, next, newdlg);
|
||||
}
|
||||
|
||||
// Is there an A part after the overlap?
|
||||
if (prevdlg->End > curdlg->End) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = curdlg->End;
|
||||
newdlg->End = prevdlg->End;
|
||||
newdlg->Text = prevdlg->Text;
|
||||
|
||||
InsertLineSortedIntoList(*Line, next, newdlg);
|
||||
}
|
||||
|
||||
// Is there a B part after the overlap?
|
||||
if (curdlg->End > prevdlg->End) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = prevdlg->End;
|
||||
newdlg->End = curdlg->End;
|
||||
newdlg->Text = curdlg->Text;
|
||||
|
||||
InsertLineSortedIntoList(*Line, next, newdlg);
|
||||
}
|
||||
|
||||
next--;
|
||||
|
||||
if (!curdlg || !prevdlg) continue;
|
||||
if (prevdlg->End <= curdlg->Start) continue;
|
||||
|
||||
// Use names like in the algorithm description and prepare for erasing
|
||||
// old dialogues from the list
|
||||
std::list<AssEntry*>::iterator prev = cur;
|
||||
cur = next;
|
||||
next++;
|
||||
|
||||
// std::list::insert() inserts items before the given iterator, so
|
||||
// we need 'next' for inserting. 'prev' and 'cur' can safely be erased
|
||||
// from the list now.
|
||||
Line->erase(prev);
|
||||
Line->erase(cur);
|
||||
|
||||
//Is there an A part before the overlap?
|
||||
if (curdlg->Start > prevdlg->Start) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = prevdlg->Start;
|
||||
newdlg->End = curdlg->Start;
|
||||
newdlg->Text = prevdlg->Text;
|
||||
|
||||
Line->insert(find_if(next, Line->end(), bind(dialog_start_lt, _1, newdlg)), newdlg);
|
||||
}
|
||||
|
||||
// Overlapping A+B part
|
||||
{
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = curdlg->Start;
|
||||
newdlg->End = (prevdlg->End < curdlg->End) ? prevdlg->End : curdlg->End;
|
||||
// Put an ASS format hard linewrap between lines
|
||||
newdlg->Text = curdlg->Text + "\\N" + prevdlg->Text;
|
||||
|
||||
Line->insert(find_if(next, Line->end(), bind(dialog_start_lt, _1, newdlg)), newdlg);
|
||||
}
|
||||
|
||||
// Is there an A part after the overlap?
|
||||
if (prevdlg->End > curdlg->End) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = curdlg->End;
|
||||
newdlg->End = prevdlg->End;
|
||||
newdlg->Text = prevdlg->Text;
|
||||
|
||||
Line->insert(find_if(next, Line->end(), bind(dialog_start_lt, _1, newdlg)), newdlg);
|
||||
}
|
||||
|
||||
// Is there a B part after the overlap?
|
||||
if (curdlg->End > prevdlg->End) {
|
||||
// Produce new entry with correct values
|
||||
AssDialogue *newdlg = dynamic_cast<AssDialogue*>(prevdlg->Clone());
|
||||
newdlg->Start = prevdlg->End;
|
||||
newdlg->End = curdlg->End;
|
||||
newdlg->Text = curdlg->Text;
|
||||
|
||||
Line->insert(find_if(next, Line->end(), bind(dialog_start_lt, _1, newdlg)), newdlg);
|
||||
}
|
||||
|
||||
next--;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Merge identical lines that follow each other
|
||||
///
|
||||
void SubtitleFormat::MergeIdentical() {
|
||||
using std::list;
|
||||
list<AssEntry*>::iterator next;
|
||||
std::list<AssEntry*>::iterator cur, next = Line->begin();
|
||||
cur = next++;
|
||||
|
||||
for (list<AssEntry*>::iterator cur = Line->begin(); cur != Line->end(); cur = next) {
|
||||
next = cur;
|
||||
next++;
|
||||
|
||||
if (next == Line->end()) break;
|
||||
|
||||
for (; next != Line->end(); cur = next++) {
|
||||
AssDialogue *curdlg = dynamic_cast<AssDialogue*>(*cur);
|
||||
AssDialogue *nextdlg = dynamic_cast<AssDialogue*>(*next);
|
||||
|
||||
if (curdlg && nextdlg && curdlg->End == nextdlg->Start && curdlg->Text == nextdlg->Text) {
|
||||
// Merge timing
|
||||
nextdlg->Start = (nextdlg->Start < curdlg->Start ? nextdlg->Start : curdlg->Start);
|
||||
nextdlg->End = (nextdlg->End > curdlg->End ? nextdlg->End : curdlg->End);
|
||||
nextdlg->Start = std::min(nextdlg->Start, curdlg->Start);
|
||||
nextdlg->End = std::max(nextdlg->End, curdlg->End);
|
||||
|
||||
// Remove duplicate line
|
||||
delete *cur;
|
||||
|
@ -556,3 +339,66 @@ void SubtitleFormat::MergeIdentical() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<SubtitleFormat*> SubtitleFormat::formats;
|
||||
|
||||
void SubtitleFormat::LoadFormats() {
|
||||
if (formats.empty()) {
|
||||
new ASSSubtitleFormat();
|
||||
new EncoreSubtitleFormat();
|
||||
new MKVSubtitleFormat();
|
||||
new MicroDVDSubtitleFormat();
|
||||
new SRTSubtitleFormat();
|
||||
new TTXTSubtitleFormat();
|
||||
new TXTSubtitleFormat();
|
||||
new TranStationSubtitleFormat();
|
||||
#ifdef _DEBUG
|
||||
new DVDSubtitleFormat();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SubtitleFormat::DestroyFormats() {
|
||||
for (std::list<SubtitleFormat*>::iterator it = formats.begin(); it != formats.end(); )
|
||||
delete *it++;
|
||||
}
|
||||
|
||||
template<class Cont, class Pred>
|
||||
SubtitleFormat *find_or_null(Cont &container, Pred pred) {
|
||||
typename Cont::iterator it = find_if(container.begin(), container.end(), pred);
|
||||
if (it == container.end())
|
||||
return 0;
|
||||
return *it;
|
||||
}
|
||||
|
||||
SubtitleFormat *SubtitleFormat::GetReader(wxString const& filename) {
|
||||
LoadFormats();
|
||||
return find_or_null(formats, bind(&SubtitleFormat::CanReadFile, _1, filename));
|
||||
}
|
||||
|
||||
SubtitleFormat *SubtitleFormat::GetWriter(wxString const& filename) {
|
||||
LoadFormats();
|
||||
return find_or_null(formats, bind(&SubtitleFormat::CanWriteFile, _1, filename));
|
||||
}
|
||||
|
||||
wxString SubtitleFormat::GetWildcards(int mode) {
|
||||
LoadFormats();
|
||||
|
||||
wxArrayString all;
|
||||
wxString final;
|
||||
|
||||
std::list<SubtitleFormat*>::iterator curIter;
|
||||
for (curIter=formats.begin();curIter!=formats.end();curIter++) {
|
||||
SubtitleFormat *format = *curIter;
|
||||
wxArrayString cur = mode == 0 ? format->GetReadWildcards() : format->GetWriteWildcards();
|
||||
if (cur.empty()) continue;
|
||||
|
||||
for_each(cur.begin(), cur.end(), bind(&wxString::Prepend, _1, "*."));
|
||||
copy(cur.begin(), cur.end(), std::back_inserter(all));
|
||||
final += "|" + format->GetName() + " (" + wxJoin(cur, ',') + ")|" + wxJoin(cur, ';');
|
||||
}
|
||||
|
||||
final.Prepend(_("All Supported Formats") + " (" + wxJoin(all, ',') + ")|" + wxJoin(all, ';'));
|
||||
|
||||
return final;
|
||||
}
|
||||
|
|
|
@ -54,96 +54,113 @@ class AssEntry;
|
|||
///
|
||||
/// DOCME
|
||||
class SubtitleFormat {
|
||||
/// DOCME
|
||||
wxString name;
|
||||
bool isCopy;
|
||||
|
||||
/// DOCME
|
||||
AssFile *assFile;
|
||||
|
||||
void Register();
|
||||
void Remove();
|
||||
/// Get this format's wildcards for a load dialog
|
||||
virtual wxArrayString GetReadWildcards() const { return wxArrayString(); }
|
||||
/// Get this format's wildcards for a save dialog
|
||||
virtual wxArrayString GetWriteWildcards() const { return wxArrayString(); }
|
||||
|
||||
/// DOCME
|
||||
/// List of loaded subtitle formats
|
||||
static std::list<SubtitleFormat*> formats;
|
||||
|
||||
/// DOCME
|
||||
static bool loaded;
|
||||
|
||||
protected:
|
||||
/// DOCME
|
||||
struct FPSRational {
|
||||
|
||||
/// DOCME
|
||||
int num;
|
||||
|
||||
/// DOCME
|
||||
int den;
|
||||
|
||||
/// DOCME
|
||||
bool smpte_dropframe;
|
||||
};
|
||||
|
||||
/// DOCME
|
||||
std::list<AssEntry*> *Line;
|
||||
|
||||
/// Copy the input subtitles file; must be called before making any changes
|
||||
void CreateCopy();
|
||||
/// Delete the subtitle file if we own it; should be called after processing
|
||||
/// if CreateCopy was used
|
||||
void ClearCopy();
|
||||
/// Sort the lines by start time
|
||||
void SortLines();
|
||||
void ConvertTags(int format,const wxString &lineEnd,bool mergeLineBreaks=true);
|
||||
//void Merge(bool identical,bool overlaps,bool stripComments,bool stripNonDialogue);
|
||||
/// Strip tags or convert them to SRT
|
||||
/// @param format 1: strip tags 2: SRT
|
||||
/// @param lineEnd Newline character(s)
|
||||
/// @param mergeLineBreaks Should multiple consecutive line breaks be merged into one?
|
||||
void ConvertTags(int format, const wxString &lineEnd, bool mergeLineBreaks=true);
|
||||
/// Remove All commented and empty lines
|
||||
void StripComments();
|
||||
/// Remove everything but the dialogue lines
|
||||
void StripNonDialogue();
|
||||
/// @brief Split and merge lines so there are no overlapping lines
|
||||
///
|
||||
/// Algorithm described at http://devel.aegisub.org/wiki/Technical/SplitMerge
|
||||
void RecombineOverlaps();
|
||||
/// Merge sequential identical lines
|
||||
void MergeIdentical();
|
||||
|
||||
/// Clear the subtitle file
|
||||
void Clear();
|
||||
/// Load the default file
|
||||
/// @param defline Add a blank line?
|
||||
void LoadDefault(bool defline=true);
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
AssFile *GetAssFile() { return assFile; }
|
||||
/// Add a line to the output file
|
||||
/// @param data Line data
|
||||
/// @param group File section
|
||||
void AddLine(wxString data,wxString group,int &version,wxString *outgroup=NULL);
|
||||
/// Prompt the user for a framerate to use
|
||||
/// @param showSMPTE Include SMPTE as an option?
|
||||
FPSRational AskForFPS(bool showSMPTE=false);
|
||||
|
||||
virtual wxString GetName()=0;
|
||||
virtual wxArrayString GetReadWildcards();
|
||||
virtual wxArrayString GetWriteWildcards();
|
||||
|
||||
public:
|
||||
SubtitleFormat();
|
||||
/// Constructor
|
||||
/// @param Subtitle format name
|
||||
/// @note Automatically registers the format
|
||||
SubtitleFormat(wxString const& name);
|
||||
/// Destructor
|
||||
/// @note Automatically unregisters the format
|
||||
virtual ~SubtitleFormat();
|
||||
|
||||
/// Set the target file to write
|
||||
void SetTarget(AssFile *file);
|
||||
|
||||
/// Get this format's name
|
||||
wxString GetName() const { return name; }
|
||||
|
||||
/// @brief Check if the given file can be read by this format
|
||||
///
|
||||
/// Default implemention simply checks if the file's extension is in the
|
||||
/// format's wildcard list
|
||||
virtual bool CanReadFile(wxString const& filename) const;
|
||||
|
||||
/// @brief Check if the given file can be written by this format
|
||||
///
|
||||
/// Default implemention simply checks if the file's extension is in the
|
||||
/// format's wildcard list
|
||||
virtual bool CanWriteFile(wxString const& filename) const;
|
||||
|
||||
/// Load a subtitle file
|
||||
/// @param filename File to load
|
||||
/// @param forceEncoding Encoding to use or empty string for default
|
||||
virtual void ReadFile(wxString const& filename, wxString const& forceEncoding="") { }
|
||||
|
||||
/// Save a subtitle file
|
||||
/// @param filename File to write to
|
||||
/// @param forceEncoding Encoding to use or empty string for default
|
||||
virtual void WriteFile(wxString const& filename, wxString const& encoding="") { }
|
||||
|
||||
/// Get the wildcards for a save or load dialog
|
||||
/// @param mode 0: load 1: save
|
||||
static wxString GetWildcards(int mode);
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
virtual bool CanReadFile(wxString filename) { return false; };
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
virtual bool CanWriteFile(wxString filename) { return false; };
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
/// @param forceEncoding
|
||||
///
|
||||
virtual void ReadFile(wxString filename,wxString forceEncoding="") { };
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
virtual void WriteFile(wxString filename,wxString encoding="") { };
|
||||
|
||||
static SubtitleFormat *GetReader(wxString filename);
|
||||
static SubtitleFormat *GetWriter(wxString filename);
|
||||
/// Get a subtitle format that can read the given file or NULL if none can
|
||||
static SubtitleFormat *GetReader(wxString const& filename);
|
||||
/// Get a subtitle format that can write the given file or NULL if none can
|
||||
static SubtitleFormat *GetWriter(wxString const& filename);
|
||||
/// Initialize subtitle formats
|
||||
static void LoadFormats();
|
||||
/// Deinitialize subtitle formats
|
||||
static void DestroyFormats();
|
||||
};
|
||||
|
||||
|
|
|
@ -34,148 +34,92 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "subtitle_format_ass.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "compat.h"
|
||||
#include "text_file_reader.h"
|
||||
#include "text_file_writer.h"
|
||||
|
||||
DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass")
|
||||
|
||||
/// @brief Can read?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool ASSSubtitleFormat::CanReadFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".ass" || filename.Right(4).Lower() == ".ssa");
|
||||
ASSSubtitleFormat::ASSSubtitleFormat()
|
||||
: SubtitleFormat("Advanced Substation Alpha")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get name
|
||||
/// @return
|
||||
///
|
||||
wxString ASSSubtitleFormat::GetName() {
|
||||
return "Advanced Substation Alpha";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString ASSSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString ASSSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("ass");
|
||||
formats.Add("ssa");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get write wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString ASSSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString ASSSubtitleFormat::GetWriteWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("ass");
|
||||
formats.Add("ssa");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Read file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void ASSSubtitleFormat::ReadFile(wxString filename,wxString encoding) {
|
||||
void ASSSubtitleFormat::ReadFile(wxString const& filename, wxString const& encoding) {
|
||||
using namespace std;
|
||||
|
||||
// Reader
|
||||
TextFileReader file(filename,encoding);
|
||||
int version = 1;
|
||||
if (filename.Right(4).Lower() == ".ssa") version = 0;
|
||||
TextFileReader file(filename, encoding);
|
||||
int version = filename.Right(4).Lower() != ".ssa";
|
||||
|
||||
// Parse file
|
||||
wxString curgroup;
|
||||
wxString wxbuffer;
|
||||
while (file.HasMoreLines()) {
|
||||
// Reads line
|
||||
wxbuffer = file.ReadLineFromFile();
|
||||
wxString line = file.ReadLineFromFile();
|
||||
|
||||
// Make sure that the first non-blank non-comment non-group-header line
|
||||
// is really [Script Info]
|
||||
if (curgroup.IsEmpty() && !wxbuffer.IsEmpty() && wxbuffer[0] != ';' && wxbuffer[0] != '[') {
|
||||
if (curgroup.empty() && !line.empty() && line[0] != ';' && line[0] != '[') {
|
||||
curgroup = "[Script Info]";
|
||||
AddLine(curgroup,curgroup,version,&curgroup);
|
||||
AddLine(curgroup, curgroup, version, &curgroup);
|
||||
}
|
||||
|
||||
// Convert v4 styles to v4+ styles
|
||||
if (!wxbuffer.IsEmpty() && wxbuffer[0] == '[') {
|
||||
if (!line.empty() && line[0] == '[') {
|
||||
// Ugly hacks to allow intermixed v4 and v4+ style sections
|
||||
wxString low = wxbuffer.Lower();
|
||||
wxString low = line.Lower();
|
||||
if (low == "[v4 styles]") {
|
||||
wxbuffer = "[V4+ Styles]";
|
||||
curgroup = wxbuffer;
|
||||
line = "[V4+ Styles]";
|
||||
curgroup = line;
|
||||
version = 0;
|
||||
}
|
||||
else if (low == "[v4+ styles]") {
|
||||
wxbuffer = "[V4+ Styles]";
|
||||
curgroup = wxbuffer;
|
||||
line = "[V4+ Styles]";
|
||||
curgroup = line;
|
||||
version = 1;
|
||||
}
|
||||
else if (low == "[v4++ styles]") {
|
||||
wxbuffer = "[V4+ Styles]";
|
||||
curgroup = wxbuffer;
|
||||
line = "[V4+ Styles]";
|
||||
curgroup = line;
|
||||
version = 2;
|
||||
}
|
||||
// Not-so-special case for other groups, just set it
|
||||
else {
|
||||
curgroup = wxbuffer;
|
||||
curgroup = line;
|
||||
}
|
||||
}
|
||||
|
||||
// Add line
|
||||
try {
|
||||
AddLine(wxbuffer,curgroup,version,&curgroup);
|
||||
AddLine(line, curgroup, version, &curgroup);
|
||||
}
|
||||
catch (const char *err) {
|
||||
Clear();
|
||||
throw wxString("Error processing line: ") + wxbuffer + ": " + wxString(err);
|
||||
}
|
||||
catch (...) {
|
||||
Clear();
|
||||
throw wxString("Error processing line: ") + wxbuffer;
|
||||
throw AssParseError("Error processing line: " + STD_STR(line) + ": " + err, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write to file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool ASSSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".ass" || filename.Right(4).Lower() == ".ssa");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param _filename
|
||||
/// @param encoding
|
||||
///
|
||||
void ASSSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||
// Open file
|
||||
TextFileWriter file(filename,encoding);
|
||||
void ASSSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
TextFileWriter file(filename, encoding);
|
||||
bool ssa = filename.Right(4).Lower() == ".ssa";
|
||||
|
||||
// Write lines
|
||||
std::list<AssEntry*>::iterator last = Line->end(); --last;
|
||||
wxString group = Line->front()->group;
|
||||
for (std::list<AssEntry*>::iterator cur=Line->begin(); cur!=Line->end(); ++cur) {
|
||||
|
@ -189,9 +133,7 @@ void ASSSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
|||
bool lineBreak = cur != last;
|
||||
|
||||
// Write line
|
||||
if (ssa) file.WriteLineToFile((*cur)->GetSSAText(),lineBreak);
|
||||
else file.WriteLineToFile((*cur)->GetEntryData(),lineBreak);
|
||||
if (ssa) file.WriteLineToFile((*cur)->GetSSAText(), lineBreak);
|
||||
else file.WriteLineToFile((*cur)->GetEntryData(), lineBreak);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,20 +34,8 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AssDialogue;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class ASSSubtitleFormat
|
||||
/// @brief DOCME
|
||||
|
@ -55,15 +43,11 @@ class AssDialogue;
|
|||
/// DOCME
|
||||
class ASSSubtitleFormat : public SubtitleFormat {
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
wxArrayString GetWriteWildcards();
|
||||
ASSSubtitleFormat();
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
wxArrayString GetReadWildcards() const;
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,19 +34,16 @@
|
|||
/// @ingroup subtitle_io vobsub
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "subtitle_format_dvd.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "subtitle_format_dvd.h"
|
||||
#include "include/aegisub/subtitles_provider.h"
|
||||
#include "video_provider_dummy.h"
|
||||
|
||||
|
||||
/// DOCME
|
||||
#undef _OPENMP
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
|
@ -58,41 +55,17 @@
|
|||
//
|
||||
//#pragma comment(lib, "tessdll.lib")
|
||||
|
||||
|
||||
|
||||
/// @brief Format name
|
||||
/// @return
|
||||
///
|
||||
wxString DVDSubtitleFormat::GetName() {
|
||||
return "DVD Subpictures";
|
||||
DVDSubtitleFormat::DVDSubtitleFormat()
|
||||
: SubtitleFormat("DVD Subpictures")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Extensions
|
||||
/// @return
|
||||
///
|
||||
wxArrayString DVDSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString DVDSubtitleFormat::GetWriteWildcards() const {
|
||||
wxArrayString results;
|
||||
results.Add("sup");
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool DVDSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Lower().EndsWith(".sup"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get subpicture list
|
||||
/// @param pics
|
||||
///
|
||||
void DVDSubtitleFormat::GetSubPictureList(std::vector<SubPicture> &pics) {
|
||||
// Create video frame
|
||||
int w = 720;
|
||||
|
@ -361,7 +334,7 @@ void DVDSubtitleFormat::GetSubPictureList(std::vector<SubPicture> &pics) {
|
|||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void DVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||
void DVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
// Prepare subtitles
|
||||
CreateCopy();
|
||||
SortLines();
|
||||
|
|
|
@ -34,18 +34,12 @@
|
|||
/// @ingroup subtitle_io vobsub
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
/// DOCME
|
||||
struct SubPicture {
|
||||
|
||||
|
@ -55,17 +49,17 @@ struct SubPicture {
|
|||
/// DOCME
|
||||
|
||||
/// DOCME
|
||||
int x,y;
|
||||
int x, y;
|
||||
|
||||
/// DOCME
|
||||
|
||||
/// DOCME
|
||||
int w,h;
|
||||
int w, h;
|
||||
|
||||
/// DOCME
|
||||
|
||||
/// DOCME
|
||||
int start,end;
|
||||
int start, end;
|
||||
};
|
||||
|
||||
|
||||
|
@ -81,12 +75,7 @@ struct RLEGroup {
|
|||
/// DOCME
|
||||
bool eol;
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param _col
|
||||
/// @param _len
|
||||
/// @param _eol
|
||||
///
|
||||
RLEGroup(int _col,int _len,bool _eol) { col = _col; len = _len; eol = _eol; }
|
||||
RLEGroup(int col, int len, bool eol) : col(col), len(len), eol(eol) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -97,14 +86,10 @@ struct RLEGroup {
|
|||
///
|
||||
/// DOCME
|
||||
class DVDSubtitleFormat : public SubtitleFormat {
|
||||
private:
|
||||
void GetSubPictureList(std::vector<SubPicture> &pics);
|
||||
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetWriteWildcards();
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
DVDSubtitleFormat();
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,57 +34,29 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "subtitle_format_encore.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "text_file_writer.h"
|
||||
|
||||
|
||||
/// @brief Name
|
||||
/// @return
|
||||
///
|
||||
wxString EncoreSubtitleFormat::GetName() {
|
||||
return "Adobe Encore";
|
||||
EncoreSubtitleFormat::EncoreSubtitleFormat()
|
||||
: SubtitleFormat("Adobe Encore")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString EncoreSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString EncoreSubtitleFormat::GetWriteWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("encore.txt");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool EncoreSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(11).Lower() == ".encore.txt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param _filename
|
||||
/// @param encoding
|
||||
///
|
||||
void EncoreSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||
// Get FPS
|
||||
void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
FPSRational fps_rat = AskForFPS(true);
|
||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) return;
|
||||
|
||||
// Open file
|
||||
TextFileWriter file(_filename,encoding);
|
||||
TextFileWriter file(filename, encoding);
|
||||
|
||||
// Convert to encore
|
||||
CreateCopy();
|
||||
|
@ -92,25 +64,20 @@ void EncoreSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
|||
StripComments();
|
||||
RecombineOverlaps();
|
||||
MergeIdentical();
|
||||
ConvertTags(1,"\r\n");
|
||||
ConvertTags(1, "\r\n");
|
||||
|
||||
// Write lines
|
||||
using std::list;
|
||||
int i = 0;
|
||||
|
||||
// Encore wants ; instead of : if we're dealing with NTSC dropframe stuff
|
||||
FractionalTime ft(fps_rat.smpte_dropframe ? ";" : ":", fps_rat.num, fps_rat.den, fps_rat.smpte_dropframe);
|
||||
|
||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (current && !current->Comment) {
|
||||
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||
++i;
|
||||
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.FromAssTime(current->Start), ft.FromAssTime(current->End), current->Text));
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
ClearCopy();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,11 +34,6 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
|
@ -49,10 +44,7 @@
|
|||
/// DOCME
|
||||
class EncoreSubtitleFormat : public SubtitleFormat {
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetWriteWildcards();
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
EncoreSubtitleFormat();
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -47,41 +47,38 @@
|
|||
#include "text_file_writer.h"
|
||||
#include "video_context.h"
|
||||
|
||||
wxString MicroDVDSubtitleFormat::GetName() {
|
||||
return "MicroDVD";
|
||||
MicroDVDSubtitleFormat::MicroDVDSubtitleFormat()
|
||||
: SubtitleFormat("MicroDVD")
|
||||
{
|
||||
}
|
||||
|
||||
wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("sub");
|
||||
return formats;
|
||||
}
|
||||
|
||||
wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() const {
|
||||
return GetReadWildcards();
|
||||
}
|
||||
|
||||
bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) {
|
||||
bool MicroDVDSubtitleFormat::CanReadFile(wxString const& filename) const {
|
||||
// Return false immediately if extension is wrong
|
||||
if (filename.Right(4).Lower() != ".sub") return false;
|
||||
|
||||
// Since there is an infinity of .sub formats, load first line and check if it's valid
|
||||
TextFileReader file(filename);
|
||||
if (file.HasMoreLines()) {
|
||||
wxRegEx exp("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$",wxRE_ADVANCED);
|
||||
wxRegEx exp("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$", wxRE_ADVANCED);
|
||||
return exp.Matches(file.ReadLineFromFile());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MicroDVDSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".sub");
|
||||
}
|
||||
|
||||
void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) {
|
||||
void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const& forceEncoding) {
|
||||
TextFileReader file(filename);
|
||||
wxRegEx exp("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$",wxRE_ADVANCED);
|
||||
wxRegEx exp("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$", wxRE_ADVANCED);
|
||||
|
||||
LoadDefault(false);
|
||||
|
||||
|
@ -94,10 +91,10 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding)
|
|||
while (file.HasMoreLines()) {
|
||||
wxString line = file.ReadLineFromFile();
|
||||
if (exp.Matches(line)) {
|
||||
long f1,f2;
|
||||
exp.GetMatch(line,1).ToLong(&f1);
|
||||
exp.GetMatch(line,2).ToLong(&f2);
|
||||
wxString text = exp.GetMatch(line,3);
|
||||
long f1, f2;
|
||||
exp.GetMatch(line, 1).ToLong(&f1);
|
||||
exp.GetMatch(line, 2).ToLong(&f2);
|
||||
wxString text = exp.GetMatch(line, 3);
|
||||
|
||||
// If it's the first, check if it contains fps information
|
||||
if (isFirst) {
|
||||
|
@ -123,25 +120,20 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding)
|
|||
}
|
||||
}
|
||||
|
||||
// Start and end times
|
||||
int start,end;
|
||||
start = rate->TimeAtFrame(f1,agi::vfr::START);
|
||||
end = rate->TimeAtFrame(f2,agi::vfr::END);
|
||||
text.Replace("|", "\\N");
|
||||
|
||||
text.Replace("|","\\N");
|
||||
|
||||
AssDialogue *line = new AssDialogue();
|
||||
AssDialogue *line = new AssDialogue;
|
||||
line->group = "[Events]";
|
||||
line->Style = "Default";
|
||||
line->Start.SetMS(start);
|
||||
line->End.SetMS(end);
|
||||
line->Start.SetMS(rate->TimeAtFrame(f1, agi::vfr::START));
|
||||
line->End.SetMS(rate->TimeAtFrame(f2, agi::vfr::END));
|
||||
line->Text = text;
|
||||
Line->push_back(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||
void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
agi::vfr::Framerate cfr;
|
||||
const agi::vfr::Framerate *rate = 𝔠
|
||||
|
||||
|
@ -157,24 +149,22 @@ void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
|||
StripComments();
|
||||
RecombineOverlaps();
|
||||
MergeIdentical();
|
||||
ConvertTags(1,"|");
|
||||
ConvertTags(1, "|");
|
||||
|
||||
TextFileWriter file(filename,encoding);
|
||||
TextFileWriter file(filename, encoding);
|
||||
|
||||
// Write FPS line
|
||||
if (!rate->IsVFR()) {
|
||||
file.WriteLineToFile(wxString::Format("{1}{1}%.6f",rate->FPS()));
|
||||
file.WriteLineToFile(wxString::Format("{1}{1}%.6f", rate->FPS()));
|
||||
}
|
||||
|
||||
// Write lines
|
||||
using std::list;
|
||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (current && !current->Comment) {
|
||||
int start = rate->FrameAtTime(current->Start.GetMS(),agi::vfr::START);
|
||||
int end = rate->FrameAtTime(current->End.GetMS(),agi::vfr::END);
|
||||
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||
int start = rate->FrameAtTime(current->Start.GetMS(), agi::vfr::START);
|
||||
int end = rate->FrameAtTime(current->End.GetMS(), agi::vfr::END);
|
||||
|
||||
file.WriteLineToFile(wxString::Format("{%i}{%i}%s",start,end,current->Text));
|
||||
file.WriteLineToFile(wxString::Format("{%i}{%i}%s", start, end, current->Text));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,13 +43,13 @@
|
|||
/// DOCME
|
||||
class MicroDVDSubtitleFormat : public SubtitleFormat {
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
wxArrayString GetWriteWildcards();
|
||||
MicroDVDSubtitleFormat();
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
wxArrayString GetReadWildcards() const;
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
bool CanReadFile(wxString const& filename) const;
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
|
|
@ -34,44 +34,18 @@
|
|||
/// @ingroup subtitle_io matroska
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "mkv_wrap.h"
|
||||
#include "subtitle_format_mkv.h"
|
||||
|
||||
#include "mkv_wrap.h"
|
||||
|
||||
/// @brief Can read?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool MKVSubtitleFormat::CanReadFile(wxString filename) {
|
||||
if (filename.Right(4).Lower() == ".mkv" || filename.Right(4).Lower() == ".mks"
|
||||
|| filename.Right(4).Lower() == ".mka")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
MKVSubtitleFormat::MKVSubtitleFormat()
|
||||
: SubtitleFormat("Matroska")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get name
|
||||
/// @return
|
||||
///
|
||||
wxString MKVSubtitleFormat::GetName() {
|
||||
return "Matroska";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString MKVSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString MKVSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("mkv");
|
||||
formats.Add("mka");
|
||||
|
@ -79,41 +53,8 @@ wxArrayString MKVSubtitleFormat::GetReadWildcards() {
|
|||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Read file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void MKVSubtitleFormat::ReadFile(wxString filename,wxString encoding) {
|
||||
// Open matroska
|
||||
void MKVSubtitleFormat::ReadFile(wxString const& filename, wxString const& encoding) {
|
||||
MatroskaWrapper wrap;
|
||||
wrap.Open(filename,false);
|
||||
|
||||
// Read subtitles in a temporary object
|
||||
wrap.Open(filename, false);
|
||||
wrap.GetSubtitles(GetAssFile());
|
||||
|
||||
// Close matroska
|
||||
wrap.Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write to file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool MKVSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param _filename
|
||||
/// @param encoding
|
||||
///
|
||||
void MKVSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,19 +34,8 @@
|
|||
/// @ingroup subtitle_io matroska
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AssDialogue;
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class MKVSubtitleFormat
|
||||
/// @brief DOCME
|
||||
|
@ -54,14 +43,8 @@ class AssDialogue;
|
|||
/// DOCME
|
||||
class MKVSubtitleFormat : public SubtitleFormat {
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
MKVSubtitleFormat();
|
||||
wxArrayString GetReadWildcards() const;
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
|
@ -52,67 +49,26 @@
|
|||
|
||||
DEFINE_SIMPLE_EXCEPTION(SRTParseError, SubtitleFormatParseError, "subtitle_io/parse/srt")
|
||||
|
||||
|
||||
/// @brief Can read?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool SRTSubtitleFormat::CanReadFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".srt");
|
||||
SRTSubtitleFormat::SRTSubtitleFormat()
|
||||
: SubtitleFormat("SubRip")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool SRTSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".srt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get name
|
||||
/// @return
|
||||
///
|
||||
wxString SRTSubtitleFormat::GetName() {
|
||||
return "SubRip";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString SRTSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString SRTSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("srt");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get write wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString SRTSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString SRTSubtitleFormat::GetWriteWildcards() const {
|
||||
return GetReadWildcards();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Read file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void SRTSubtitleFormat::ReadFile(wxString filename,wxString encoding) {
|
||||
void SRTSubtitleFormat::ReadFile(wxString const& filename, wxString const& encoding) {
|
||||
using namespace std;
|
||||
|
||||
// Reader
|
||||
TextFileReader file(filename,encoding);
|
||||
|
||||
// Default
|
||||
LoadDefault(false);
|
||||
|
||||
// See parsing algorithm at <http://devel.aegisub.org/wiki/SubtitleFormats/SRT>
|
||||
|
@ -239,7 +195,7 @@ found_timestamps:
|
|||
}
|
||||
|
||||
if (state == 1 || state == 2) {
|
||||
throw SRTParseError(std::string("Parsing SRT: Incomplete file"), 0);
|
||||
throw SRTParseError("Parsing SRT: Incomplete file", 0);
|
||||
}
|
||||
|
||||
if (line) {
|
||||
|
@ -248,15 +204,8 @@ found_timestamps:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param _filename
|
||||
/// @param encoding
|
||||
///
|
||||
void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||
// Open file
|
||||
TextFileWriter file(_filename,encoding);
|
||||
void SRTSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
TextFileWriter file(filename,encoding);
|
||||
|
||||
// Convert to SRT
|
||||
CreateCopy();
|
||||
|
@ -274,22 +223,14 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
|||
|
||||
// Write lines
|
||||
int i=1;
|
||||
using std::list;
|
||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (current && !current->Comment) {
|
||||
// Write line
|
||||
file.WriteLineToFile(wxString::Format("%i",i));
|
||||
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||
file.WriteLineToFile(wxString::Format("%i", i++));
|
||||
file.WriteLineToFile(current->Start.GetSRTFormated() + " --> " + current->End.GetSRTFormated());
|
||||
file.WriteLineToFile(current->Text);
|
||||
file.WriteLineToFile("");
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
ClearCopy();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,20 +34,8 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AssDialogue;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class SRTSubtitleFormat
|
||||
/// @brief DOCME
|
||||
|
@ -55,15 +43,10 @@ class AssDialogue;
|
|||
/// DOCME
|
||||
class SRTSubtitleFormat : public SubtitleFormat {
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
wxArrayString GetWriteWildcards();
|
||||
SRTSubtitleFormat();
|
||||
wxArrayString GetReadWildcards() const;
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,65 +34,36 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "subtitle_format_transtation.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "ass_style.h"
|
||||
#include "ass_time.h"
|
||||
#include "subtitle_format_transtation.h"
|
||||
#include "text_file_writer.h"
|
||||
|
||||
|
||||
/// @brief Name
|
||||
/// @return
|
||||
///
|
||||
wxString TranStationSubtitleFormat::GetName() {
|
||||
return "TranStation";
|
||||
TranStationSubtitleFormat::TranStationSubtitleFormat()
|
||||
: SubtitleFormat("TranStation")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString TranStationSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString TranStationSubtitleFormat::GetWriteWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("transtation.txt");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool TranStationSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(16).Lower() == ".transtation.txt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param _filename
|
||||
/// @param encoding
|
||||
/// @return
|
||||
///
|
||||
void TranStationSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||
// Get FPS
|
||||
void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
FPSRational fps_rat = AskForFPS(true);
|
||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) return;
|
||||
|
||||
// Open file
|
||||
TextFileWriter file(_filename,encoding);
|
||||
TextFileWriter file(filename, encoding);
|
||||
|
||||
// Convert to TranStation
|
||||
CreateCopy();
|
||||
|
@ -101,45 +72,34 @@ void TranStationSubtitleFormat::WriteFile(wxString _filename,wxString encoding)
|
|||
RecombineOverlaps();
|
||||
MergeIdentical();
|
||||
|
||||
// Write lines
|
||||
using std::list;
|
||||
AssDialogue *current = NULL;
|
||||
AssDialogue *next = NULL;
|
||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
if (next)
|
||||
current = next;
|
||||
next = dynamic_cast<AssDialogue*>(*cur);
|
||||
AssDialogue *prev = 0;
|
||||
for (std::list<AssEntry*>::iterator it = Line->begin(); it != Line->end(); ++it) {
|
||||
AssDialogue *cur = dynamic_cast<AssDialogue*>(*it);
|
||||
|
||||
if (current && !current->Comment) {
|
||||
// Write text
|
||||
file.WriteLineToFile(ConvertLine(current,&fps_rat,(next && !next->Comment) ? next->Start.GetMS() : -1));
|
||||
if (prev && cur) {
|
||||
file.WriteLineToFile(ConvertLine(prev, &fps_rat, cur->Start.GetMS()));
|
||||
file.WriteLineToFile("");
|
||||
}
|
||||
|
||||
if (cur)
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
// flush last line
|
||||
if (next && !next->Comment)
|
||||
file.WriteLineToFile(ConvertLine(next,&fps_rat,-1));
|
||||
if (prev)
|
||||
file.WriteLineToFile(ConvertLine(prev, &fps_rat, -1));
|
||||
|
||||
// Every file must end with this line
|
||||
file.WriteLineToFile("SUB[");
|
||||
|
||||
// Clean up
|
||||
ClearCopy();
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param current
|
||||
/// @param fps_rat
|
||||
/// @param nextl_start
|
||||
///
|
||||
wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRational *fps_rat, int nextl_start) {
|
||||
// Get line data
|
||||
AssStyle *style = GetAssFile()->GetStyle(current->Style);
|
||||
int valign = 0;
|
||||
const char *halign = " "; // default is centered
|
||||
const char *type = "N"; // no special style
|
||||
if (style) {
|
||||
if (AssStyle *style = GetAssFile()->GetStyle(current->Style)) {
|
||||
if (style->alignment >= 4) valign = 4;
|
||||
if (style->alignment >= 7) valign = 9;
|
||||
if (style->alignment == 1 || style->alignment == 4 || style->alignment == 7) halign = "L";
|
||||
|
@ -162,16 +122,15 @@ wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRationa
|
|||
end.SetMS(end.GetMS() - ((1000*fps_rat->den)/fps_rat->num));
|
||||
|
||||
FractionalTime ft(":", fps_rat->num, fps_rat->den, fps_rat->smpte_dropframe);
|
||||
wxString header = wxString::Format("SUB[%i%s%s ",valign,halign,type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n";
|
||||
wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n";
|
||||
|
||||
// Process text
|
||||
wxString lineEnd = "\r\n";
|
||||
current->StripTags();
|
||||
current->Text.Replace("\\h"," ",true);
|
||||
current->Text.Replace("\\n",lineEnd,true);
|
||||
current->Text.Replace("\\N",lineEnd,true);
|
||||
while (current->Text.Replace(lineEnd+lineEnd,lineEnd,true)) {};
|
||||
current->Text.Replace("\\h", " ", true);
|
||||
current->Text.Replace("\\n", lineEnd, true);
|
||||
current->Text.Replace("\\N", lineEnd, true);
|
||||
while (current->Text.Replace(lineEnd + lineEnd, lineEnd, true));
|
||||
|
||||
return header + current->Text;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,13 +34,9 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
class AssDialogue;
|
||||
|
||||
/// DOCME
|
||||
/// @class TranStationSubtitleFormat
|
||||
|
@ -48,14 +44,10 @@
|
|||
///
|
||||
/// DOCME
|
||||
class TranStationSubtitleFormat : public SubtitleFormat {
|
||||
private:
|
||||
wxString ConvertLine(AssDialogue *line, FPSRational *fps_rat, int nextl_start);
|
||||
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetWriteWildcards();
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
TranStationSubtitleFormat();
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,90 +34,49 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "subtitle_format_ttxt.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "ass_time.h"
|
||||
#include "compat.h"
|
||||
#include "main.h"
|
||||
#include "subtitle_format_ttxt.h"
|
||||
|
||||
DEFINE_SIMPLE_EXCEPTION(TTXTParseError, SubtitleFormatParseError, "subtitle_io/parse/ttxt")
|
||||
|
||||
/// @brief Get format name
|
||||
/// @return
|
||||
///
|
||||
wxString TTXTSubtitleFormat::GetName() {
|
||||
return "MPEG-4 Streaming Text";
|
||||
TTXTSubtitleFormat::TTXTSubtitleFormat()
|
||||
: SubtitleFormat("MPEG-4 Streaming Text")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString TTXTSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString TTXTSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("ttxt");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get write wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString TTXTSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString TTXTSubtitleFormat::GetWriteWildcards() const {
|
||||
return GetReadWildcards();
|
||||
//return wxArrayString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can read a file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool TTXTSubtitleFormat::CanReadFile(wxString filename) {
|
||||
return (filename.Right(5).Lower() == ".ttxt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write a file?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool TTXTSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
//return false;
|
||||
return (filename.Right(5).Lower() == ".ttxt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Read a file
|
||||
/// @param filename
|
||||
/// @param forceEncoding
|
||||
///
|
||||
void TTXTSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) {
|
||||
// Load default
|
||||
void TTXTSubtitleFormat::ReadFile(wxString const& filename, wxString const& forceEncoding) {
|
||||
LoadDefault(false);
|
||||
|
||||
// Load XML document
|
||||
wxXmlDocument doc;
|
||||
if (!doc.Load(filename)) throw "Failed loading TTXT XML file.";
|
||||
if (!doc.Load(filename)) throw TTXTParseError("Failed loading TTXT XML file.", 0);
|
||||
|
||||
// Check root node name
|
||||
if (doc.GetRoot()->GetName() != "TextStream") throw "Invalid TTXT file.";
|
||||
if (doc.GetRoot()->GetName() != "TextStream") throw TTXTParseError("Invalid TTXT file.", 0);
|
||||
|
||||
// Check version
|
||||
wxString verStr = doc.GetRoot()->GetAttribute("version","");
|
||||
wxString verStr = doc.GetRoot()->GetAttribute("version", "");
|
||||
version = -1;
|
||||
if (verStr == "1.0") version = 0;
|
||||
else if (verStr == "1.1") version = 1;
|
||||
else throw wxString("Unknown TTXT version: " + verStr);
|
||||
else throw TTXTParseError("Unknown TTXT version: " + STD_STR(verStr), 0);
|
||||
|
||||
// Get children
|
||||
diag = NULL;
|
||||
|
@ -149,15 +108,9 @@ void TTXTSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Process a dialogue line
|
||||
/// @param node
|
||||
/// @return
|
||||
///
|
||||
bool TTXTSubtitleFormat::ProcessLine(wxXmlNode *node) {
|
||||
// Get time
|
||||
wxString sampleTime = node->GetAttribute("sampleTime","00:00:00.000");
|
||||
wxString sampleTime = node->GetAttribute("sampleTime", "00:00:00.000");
|
||||
AssTime time;
|
||||
time.ParseASS(sampleTime);
|
||||
|
||||
|
@ -167,7 +120,7 @@ bool TTXTSubtitleFormat::ProcessLine(wxXmlNode *node) {
|
|||
|
||||
// Get text
|
||||
wxString text;
|
||||
if (version == 0) text = node->GetAttribute("text","");
|
||||
if (version == 0) text = node->GetAttribute("text", "");
|
||||
else text = node->GetNodeContent();
|
||||
|
||||
// Create line
|
||||
|
@ -199,8 +152,8 @@ bool TTXTSubtitleFormat::ProcessLine(wxXmlNode *node) {
|
|||
|
||||
// Process text for 1.1
|
||||
else {
|
||||
text.Replace("\r","");
|
||||
text.Replace("\n","\\N");
|
||||
text.Replace("\r", "");
|
||||
text.Replace("\n", "\\N");
|
||||
diag->Text = text;
|
||||
}
|
||||
|
||||
|
@ -212,30 +165,19 @@ bool TTXTSubtitleFormat::ProcessLine(wxXmlNode *node) {
|
|||
else return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Process the header
|
||||
/// @param node
|
||||
///
|
||||
void TTXTSubtitleFormat::ProcessHeader(wxXmlNode *node) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write a file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void TTXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
||||
void TTXTSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
// Convert to TTXT
|
||||
CreateCopy();
|
||||
ConvertToTTXT();
|
||||
|
||||
// Create XML structure
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode *root = new wxXmlNode(NULL,wxXML_ELEMENT_NODE,"TextStream");
|
||||
root->AddAttribute("version","1.1");
|
||||
wxXmlNode *root = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, "TextStream");
|
||||
root->AddAttribute("version", "1.1");
|
||||
doc.SetRoot(root);
|
||||
|
||||
// Create header
|
||||
|
@ -248,10 +190,11 @@ void TTXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
|||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||
AssDialogue *current = dynamic_cast<AssDialogue*>(*cur);
|
||||
if (current && !current->Comment) {
|
||||
WriteLine(root,current);
|
||||
WriteLine(root, current);
|
||||
i++;
|
||||
}
|
||||
else throw "Unexpected line type in TTXT file";
|
||||
else
|
||||
throw TTXTParseError("Unexpected line type in TTXT file", 0);
|
||||
}
|
||||
|
||||
// Save XML
|
||||
|
@ -262,82 +205,71 @@ void TTXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) {
|
|||
ClearCopy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write header
|
||||
/// @param root
|
||||
///
|
||||
void TTXTSubtitleFormat::WriteHeader(wxXmlNode *root) {
|
||||
// Write stream header
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE,"TextStreamHeader");
|
||||
node->AddAttribute("width","400");
|
||||
node->AddAttribute("height","60");
|
||||
node->AddAttribute("layer","0");
|
||||
node->AddAttribute("translation_x","0");
|
||||
node->AddAttribute("translation_y","0");
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextStreamHeader");
|
||||
node->AddAttribute("width", "400");
|
||||
node->AddAttribute("height", "60");
|
||||
node->AddAttribute("layer", "0");
|
||||
node->AddAttribute("translation_x", "0");
|
||||
node->AddAttribute("translation_y", "0");
|
||||
root->AddChild(node);
|
||||
root = node;
|
||||
|
||||
// Write sample description
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"TextSampleDescription");
|
||||
node->AddAttribute("horizontalJustification","center");
|
||||
node->AddAttribute("verticalJustification","bottom");
|
||||
node->AddAttribute("backColor","0 0 0 0");
|
||||
node->AddAttribute("verticalText","no");
|
||||
node->AddAttribute("fillTextRegion","no");
|
||||
node->AddAttribute("continuousKaraoke","no");
|
||||
node->AddAttribute("scroll","None");
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSampleDescription");
|
||||
node->AddAttribute("horizontalJustification", "center");
|
||||
node->AddAttribute("verticalJustification", "bottom");
|
||||
node->AddAttribute("backColor", "0 0 0 0");
|
||||
node->AddAttribute("verticalText", "no");
|
||||
node->AddAttribute("fillTextRegion", "no");
|
||||
node->AddAttribute("continuousKaraoke", "no");
|
||||
node->AddAttribute("scroll", "None");
|
||||
root->AddChild(node);
|
||||
root = node;
|
||||
|
||||
// Write font table
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"FontTable");
|
||||
wxXmlNode *subNode = new wxXmlNode(wxXML_ELEMENT_NODE,"FontTableEntry");
|
||||
subNode->AddAttribute("fontName","Sans");
|
||||
subNode->AddAttribute("fontID","1");
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "FontTable");
|
||||
wxXmlNode *subNode = new wxXmlNode(wxXML_ELEMENT_NODE, "FontTableEntry");
|
||||
subNode->AddAttribute("fontName", "Sans");
|
||||
subNode->AddAttribute("fontID", "1");
|
||||
node->AddChild(subNode);
|
||||
root->AddChild(node);
|
||||
|
||||
// Write text box
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"TextBox");
|
||||
node->AddAttribute("top","0");
|
||||
node->AddAttribute("left","0");
|
||||
node->AddAttribute("bottom","60");
|
||||
node->AddAttribute("right","400");
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextBox");
|
||||
node->AddAttribute("top", "0");
|
||||
node->AddAttribute("left", "0");
|
||||
node->AddAttribute("bottom", "60");
|
||||
node->AddAttribute("right", "400");
|
||||
root->AddChild(node);
|
||||
|
||||
// Write style
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"Style");
|
||||
node->AddAttribute("styles","Normal");
|
||||
node->AddAttribute("fontID","1");
|
||||
node->AddAttribute("fontSize","18");
|
||||
node->AddAttribute("color","ff ff ff ff");
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "Style");
|
||||
node->AddAttribute("styles", "Normal");
|
||||
node->AddAttribute("fontID", "1");
|
||||
node->AddAttribute("fontSize", "18");
|
||||
node->AddAttribute("color", "ff ff ff ff");
|
||||
root->AddChild(node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write line
|
||||
/// @param root
|
||||
/// @param line
|
||||
///
|
||||
void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *line) {
|
||||
// If it doesn't start at the end of previous, add blank
|
||||
wxXmlNode *node,*subNode;
|
||||
wxXmlNode *node, *subNode;
|
||||
if (prev && prev->End != line->Start) {
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"TextSample");
|
||||
node->AddAttribute("sampleTime","0" + prev->End.GetASSFormated(true));
|
||||
node->AddAttribute("xml:space","preserve");
|
||||
subNode = new wxXmlNode(wxXML_TEXT_NODE,"","");
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample");
|
||||
node->AddAttribute("sampleTime", "0" + prev->End.GetASSFormated(true));
|
||||
node->AddAttribute("xml:space", "preserve");
|
||||
subNode = new wxXmlNode(wxXML_TEXT_NODE, "", "");
|
||||
node->AddChild(subNode);
|
||||
root->AddChild(node);
|
||||
}
|
||||
|
||||
// Generate and insert node
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE,"TextSample");
|
||||
node->AddAttribute("sampleTime","0" + line->Start.GetASSFormated(true));
|
||||
node->AddAttribute("xml:space","preserve");
|
||||
subNode = new wxXmlNode(wxXML_TEXT_NODE,"",line->Text);
|
||||
node = new wxXmlNode(wxXML_ELEMENT_NODE, "TextSample");
|
||||
node->AddAttribute("sampleTime", "0" + line->Start.GetASSFormated(true));
|
||||
node->AddAttribute("xml:space", "preserve");
|
||||
subNode = new wxXmlNode(wxXML_TEXT_NODE, "", line->Text);
|
||||
node->AddChild(subNode);
|
||||
root->AddChild(node);
|
||||
|
||||
|
@ -345,17 +277,12 @@ void TTXTSubtitleFormat::WriteLine(wxXmlNode *root, AssDialogue *line) {
|
|||
prev = line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Converts whole file to TTXT
|
||||
///
|
||||
void TTXTSubtitleFormat::ConvertToTTXT () {
|
||||
// Convert
|
||||
SortLines();
|
||||
StripComments();
|
||||
RecombineOverlaps();
|
||||
MergeIdentical();
|
||||
ConvertTags(1,"\r\n");
|
||||
ConvertTags(1, "\r\n");
|
||||
|
||||
// Find last line
|
||||
AssTime lastTime;
|
||||
|
@ -376,5 +303,3 @@ void TTXTSubtitleFormat::ConvertToTTXT () {
|
|||
diag->Comment = false;
|
||||
Line->push_back(diag);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,18 +34,14 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#include <wx/xml/xml.h>
|
||||
#endif
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "subtitle_format.h"
|
||||
|
||||
class AssDialogue;
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class TTXTSubtitleFormat
|
||||
|
@ -53,8 +49,6 @@
|
|||
///
|
||||
/// DOCME
|
||||
class TTXTSubtitleFormat : public SubtitleFormat {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
int version;
|
||||
|
||||
|
@ -68,20 +62,15 @@ private:
|
|||
void ProcessHeader(wxXmlNode *node);
|
||||
|
||||
void WriteHeader(wxXmlNode *root);
|
||||
void WriteLine(wxXmlNode *root,AssDialogue *line);
|
||||
void WriteLine(wxXmlNode *root, AssDialogue *line);
|
||||
|
||||
void ConvertToTTXT();
|
||||
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
wxArrayString GetWriteWildcards();
|
||||
TTXTSubtitleFormat();
|
||||
wxArrayString GetReadWildcards() const;
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
|
||||
bool CanWriteFile(wxString filename);
|
||||
void WriteFile(wxString filename,wxString encoding);
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,114 +34,70 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "subtitle_format_txt.h"
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "compat.h"
|
||||
#include "dialog_text_import.h"
|
||||
#include "main.h"
|
||||
#include "subtitle_format_txt.h"
|
||||
#include "text_file_reader.h"
|
||||
#include "text_file_writer.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
/// @brief Can read?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool TXTSubtitleFormat::CanReadFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".txt");
|
||||
TXTSubtitleFormat::TXTSubtitleFormat()
|
||||
: SubtitleFormat("Plain-Text")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can write?
|
||||
/// @param filename
|
||||
/// @return
|
||||
///
|
||||
bool TXTSubtitleFormat::CanWriteFile(wxString filename) {
|
||||
return (filename.Right(4).Lower() == ".txt" && filename.Right(11).Lower() != ".encore.txt" && filename.Right(16).Lower() != ".transtation.txt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get name
|
||||
/// @return
|
||||
///
|
||||
wxString TXTSubtitleFormat::GetName() {
|
||||
return "Plain-Text";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get read wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString TXTSubtitleFormat::GetReadWildcards() {
|
||||
wxArrayString TXTSubtitleFormat::GetReadWildcards() const {
|
||||
wxArrayString formats;
|
||||
formats.Add("txt");
|
||||
return formats;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get write wildcards
|
||||
/// @return
|
||||
///
|
||||
wxArrayString TXTSubtitleFormat::GetWriteWildcards() {
|
||||
wxArrayString TXTSubtitleFormat::GetWriteWildcards() const {
|
||||
return GetReadWildcards();
|
||||
}
|
||||
|
||||
bool TXTSubtitleFormat::CanWriteFile(wxString const& filename) const {
|
||||
return (filename.Right(4).Lower() == ".txt" && filename.Right(11).Lower() != ".encore.txt" && filename.Right(16).Lower() != ".transtation.txt");
|
||||
}
|
||||
|
||||
|
||||
/// @brief Read file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
/// @return
|
||||
///
|
||||
void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using namespace std;
|
||||
// Import options
|
||||
void TXTSubtitleFormat::ReadFile(wxString const& filename, wxString const& encoding) {
|
||||
using namespace std;
|
||||
DialogTextImport dlg;
|
||||
if (dlg.ShowModal() == wxID_CANCEL) return;
|
||||
|
||||
// Reader
|
||||
TextFileReader file(filename,encoding,false);
|
||||
TextFileReader file(filename, encoding, false);
|
||||
|
||||
// Default
|
||||
LoadDefault(false);
|
||||
|
||||
// Data
|
||||
wxString actor;
|
||||
wxString separator = lagi_wxString(OPT_GET("Tool/Import/Text/Actor Separator")->GetString());
|
||||
wxString comment = lagi_wxString(OPT_GET("Tool/Import/Text/Comment Starter")->GetString());
|
||||
bool isComment = false;
|
||||
int lines = 0;
|
||||
|
||||
// Parse file
|
||||
AssDialogue *line = NULL;
|
||||
while (file.HasMoreLines()) {
|
||||
// Reads line
|
||||
wxString value = file.ReadLineFromFile();
|
||||
if(value.IsEmpty()) continue;
|
||||
if(value.empty()) continue;
|
||||
|
||||
// Check if this isn't a timecodes file
|
||||
if (value.StartsWith("# timecode")) {
|
||||
throw "File is a timecode file, cannot load as subtitles.";
|
||||
}
|
||||
if (value.StartsWith("# timecode"))
|
||||
throw SubtitleFormatParseError("File is a timecode file, cannot load as subtitles.", 0);
|
||||
|
||||
// Read comment data
|
||||
isComment = false;
|
||||
if (comment != "" && value.Left(comment.Length()) == comment) {
|
||||
bool isComment = false;
|
||||
if (!comment.empty() && value.StartsWith(comment)) {
|
||||
isComment = true;
|
||||
value = value.Mid(comment.Length());
|
||||
value = value.Mid(comment.size());
|
||||
}
|
||||
|
||||
// Read actor data
|
||||
if (!isComment && separator != "") {
|
||||
if (!isComment && !separator.empty()) {
|
||||
if (value[0] != ' ' && value[0] != '\t') {
|
||||
int pos = value.Find(separator);
|
||||
if (pos != wxNOT_FOUND) {
|
||||
|
@ -149,7 +105,6 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na
|
|||
actor.Trim(false);
|
||||
actor.Trim(true);
|
||||
value = value.Mid(pos+1);
|
||||
value.Trim(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,16 +112,14 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na
|
|||
// Trim spaces at start
|
||||
value.Trim(false);
|
||||
|
||||
if (value.empty())
|
||||
isComment = true;
|
||||
|
||||
// Sets line up
|
||||
line = new AssDialogue;
|
||||
AssDialogue *line = new AssDialogue;
|
||||
line->group = "[Events]";
|
||||
line->Style = "Default";
|
||||
if (isComment) line->Actor = "";
|
||||
else line->Actor = actor;
|
||||
if (value.IsEmpty()) {
|
||||
line->Actor = "";
|
||||
isComment = true;
|
||||
}
|
||||
line->Actor = isComment ? "" : line->Actor;
|
||||
line->Comment = isComment;
|
||||
line->Text = value;
|
||||
line->Start.SetMS(0);
|
||||
|
@ -179,7 +132,7 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na
|
|||
|
||||
// No lines?
|
||||
if (lines == 0) {
|
||||
line = new AssDialogue;
|
||||
AssDialogue *line = new AssDialogue;
|
||||
line->group = "[Events]";
|
||||
line->Style = "Default";
|
||||
line->Start.SetMS(0);
|
||||
|
@ -188,21 +141,15 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Write file
|
||||
/// @param filename
|
||||
/// @param encoding
|
||||
///
|
||||
void TXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) { using namespace std;
|
||||
void TXTSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||
size_t num_actor_names = 0, num_dialogue_lines = 0;
|
||||
|
||||
// Detect number of lines with Actor field filled out
|
||||
for (list<AssEntry*>::iterator l = Line->begin(); l != Line->end(); ++l) {
|
||||
for (std::list<AssEntry*>::iterator l = Line->begin(); l != Line->end(); ++l) {
|
||||
AssDialogue *dia = dynamic_cast<AssDialogue*>(*l);
|
||||
if (dia && !dia->Comment) {
|
||||
num_dialogue_lines++;
|
||||
if (!dia->Actor.IsEmpty())
|
||||
if (!dia->Actor.empty())
|
||||
num_actor_names++;
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +162,7 @@ void TXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) { using n
|
|||
file.WriteLineToFile(wxString("# Exported by Aegisub ") + GetAegisubShortVersionString());
|
||||
|
||||
// Write the file
|
||||
for (list<AssEntry*>::iterator l = Line->begin(); l != Line->end(); ++l) {
|
||||
for (std::list<AssEntry*>::iterator l = Line->begin(); l != Line->end(); ++l) {
|
||||
AssDialogue *dia = dynamic_cast<AssDialogue*>(*l);
|
||||
|
||||
if (dia) {
|
||||
|
@ -244,7 +191,7 @@ void TXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) { using n
|
|||
}
|
||||
out_line += out_text;
|
||||
|
||||
if (!out_text.IsEmpty()) {
|
||||
if (!out_text.empty()) {
|
||||
file.WriteLineToFile(out_line);
|
||||
}
|
||||
}
|
||||
|
@ -255,5 +202,3 @@ void TXTSubtitleFormat::WriteFile(wxString filename,wxString encoding) { using n
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,36 +34,20 @@
|
|||
/// @ingroup subtitle_io
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "subtitle_format.h"
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AssDialogue;
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class TXTSubtitleFormat
|
||||
/// @brief DOCME
|
||||
///
|
||||
/// DOCME
|
||||
class TXTSubtitleFormat : public SubtitleFormat {
|
||||
private:
|
||||
|
||||
public:
|
||||
wxString GetName();
|
||||
wxArrayString GetReadWildcards();
|
||||
wxArrayString GetWriteWildcards();
|
||||
TXTSubtitleFormat();
|
||||
wxArrayString GetReadWildcards() const;
|
||||
wxArrayString GetWriteWildcards() const;
|
||||
|
||||
bool CanReadFile(wxString filename);
|
||||
bool CanWriteFile(wxString filename);
|
||||
void ReadFile(wxString filename,wxString forceEncoding);
|
||||
void WriteFile(wxString filename, wxString encoding = "");
|
||||
bool CanWriteFile(wxString const& filename) const;
|
||||
void ReadFile(wxString const& filename, wxString const& forceEncoding);
|
||||
void WriteFile(wxString const& filename, wxString const& encoding);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue