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