From 39225db7c85d3857e423168a856ab1b39a906570 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Mon, 27 Feb 2006 00:06:46 +0000 Subject: [PATCH] New subtitle load system implemented Originally committed to SVN as r181. --- core/ass_file.cpp | 163 ++------------------------------ core/ass_file.h | 4 +- core/subtitle_format_ass.cpp | 93 ++++++++++++++++++ core/subtitle_format_ass.h | 58 ++++++++++++ core/subtitle_format_reader.cpp | 40 ++++++++ core/subtitle_format_reader.h | 4 + core/subtitle_format_txt.cpp | 125 ++++++++++++++++++++++++ core/subtitle_format_txt.h | 58 ++++++++++++ 8 files changed, 387 insertions(+), 158 deletions(-) create mode 100644 core/subtitle_format_ass.cpp create mode 100644 core/subtitle_format_ass.h create mode 100644 core/subtitle_format_txt.cpp create mode 100644 core/subtitle_format_txt.h diff --git a/core/ass_file.cpp b/core/ass_file.cpp index 361fc4003..43877057c 100644 --- a/core/ass_file.cpp +++ b/core/ass_file.cpp @@ -48,7 +48,7 @@ #include "text_file_reader.h" #include "text_file_writer.h" #include "version.h" -#include "subtitle_format_srt.h" +#include "subtitle_format_reader.h" ////////////////////// AssFile ////////////////////// @@ -87,47 +87,21 @@ void AssFile::Load (const wxString _filename,const wxString charset) { else enc = charset; TextFileReader::EnsureValid(enc); - // Get extension - int i = 0; - for (i=(int)_filename.size();--i>=0;) { - if (_filename[i] == _T('.')) break; - } - wxString extension = _filename.substr(i+1); - extension.Lower(); - // Generic preparation Clear(); IsASS = false; - // ASS - if (extension == _T("ass")) { - LoadASS(_filename,enc,false); - } - - // SRT - else if (extension == _T("srt")) { - //LoadSRT(_filename,enc); - SRTSubtitleFormatReader srt; - srt.SetTarget(this); - srt.ReadFile(_filename,enc); - } + // Get proper format reader + SubtitleFormatReader *reader = SubtitleFormatReader::GetReader(_filename); - // SSA - else if (extension == _T("ssa")) { - LoadASS(_filename,enc,true); - } - - // TXT - else if (extension == _T("txt")) { - LoadTXT(_filename,enc); + // Read file + if (reader) { + reader->SetTarget(this); + reader->ReadFile(_filename,enc); } // Couldn't find a type - else { - wxString error = _T("Unknown file type: "); - error += extension; - throw error; - } + else throw _T("Unknown file type."); } // String error @@ -162,127 +136,6 @@ void AssFile::Load (const wxString _filename,const wxString charset) { } -/////////////////////////// -// Load Ass file from disk -void AssFile::LoadASS (const wxString _filename,const wxString encoding,bool IsSSA) { - using namespace std; - - // Reader - TextFileReader file(_filename,encoding); - - // Parse file - wxString curgroup; - int lasttime = -1; - while (file.HasMoreLines()) { - // Reads line - wxString wxbuffer = file.ReadLineFromFile(); - - // Convert v4 styles to v4+ styles - if (wxbuffer.Lower() == _T("[v4 styles]")) { - wxbuffer = _T("[V4+ Styles]"); - } - - // Set group - if (wxbuffer[0] == _T('[')) { - curgroup = wxbuffer; - } - - // Add line - try { - lasttime = AddLine(wxbuffer,curgroup,lasttime,IsSSA); - } - catch (wchar_t *err) { - Clear(); - throw wxString(_T("Error processing line: ")) + wxbuffer + _T(": ") + wxString(err); - } - catch (...) { - Clear(); - throw wxString(_T("Error processing line: ")) + wxbuffer; - } - } - - // Set ASS - IsASS = !IsSSA; -} - - -//////////////////////////// -// Loads TXT subs from disk -void AssFile::LoadTXT (wxString _filename,wxString encoding) { - using namespace std; - - // Reader - TextFileReader file(_filename,encoding,false); - - // Default - LoadDefault(false); - IsASS = false; - - // Data - wxString actor; - wxString separator = Options.AsText(_T("Text actor separator")); - wxString comment = Options.AsText(_T("Text comment starter")); - bool isComment = false; - - // Parse file - AssDialogue *line = NULL; - while (file.HasMoreLines()) { - // Reads line - wxString value = file.ReadLineFromFile(); - - // Check if this isn't a timecodes file - if (value.Left(10) == _T("# timecode")) { - throw _T("File is a timecode file, cannot load as subtitles."); - } - - // Read comment data - isComment = false; - if (comment != _T("") && value.Left(comment.Length()) == comment) { - isComment = true; - value = value.Mid(comment.Length()); - } - - // Read actor data - if (!isComment && separator != _T("")) { - if (value[0] != _T(' ') && value[0] != _T('\t')) { - size_t pos = value.Find(separator); - if (pos != -1) { - actor = value.Left(pos); - actor.Trim(false); - actor.Trim(true); - value = value.Mid(pos+1); - value.Trim(false); - } - } - } - - // Trim spaces at start - value.Trim(false); - - // Sets line up - line = new AssDialogue(); - line->group = _T("[Events]"); - line->Style = _T("Default"); - if (isComment) line->Actor = _T(""); - else line->Actor = actor; - if (value.IsEmpty()) { - line->Actor = _T(""); - isComment = true; - } - line->Comment = isComment; - line->Text = value; - line->StartMS = 0; - line->Start.SetMS(0); - line->End.SetMS(0); - line->UpdateData(); - //line->ParseASSTags(); - - // Adds line - Line.push_back(line); - } -} - - ///////////////////////////// // Chooses format to save in void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) { diff --git a/core/ass_file.h b/core/ass_file.h index 6405c3f88..010b83d9e 100644 --- a/core/ass_file.h +++ b/core/ass_file.h @@ -68,14 +68,11 @@ private: static void StackClear(); // I/O operations - void LoadASS(const wxString file,const wxString encoding,bool IsSSA=false); - void LoadTXT(const wxString file,const wxString encoding); void SaveASS(const wxString file,bool setfilename,const wxString encoding=_T("")); void SaveSSA(const wxString file,const wxString encoding=_T("")); void SaveSRT(const wxString file,const wxString encoding=_T("")); // Manipulation operations - int AddLine(wxString data,wxString group,int lasttime,bool &IsSSA); void ConvertToSRT(); void DialogueToSRT(AssDialogue *current,std::list::iterator prev); @@ -111,6 +108,7 @@ public: wxString GetScriptInfo(const wxString key); // Returns the value in a [Script Info] key. void SetScriptInfo(const wxString key,const wxString value); // Sets the value of a [Script Info] key. Adds it if it doesn't exist. void AddComment(const wxString comment); // Adds a ";" comment under [Script Info]. + int AddLine(wxString data,wxString group,int lasttime,bool &IsSSA); static void StackPop(); // Pop subs from stack and sets 'top' to it static void StackRedo(); // Redoes action on stack diff --git a/core/subtitle_format_ass.cpp b/core/subtitle_format_ass.cpp new file mode 100644 index 000000000..fc80628b2 --- /dev/null +++ b/core/subtitle_format_ass.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +/////////// +// Headers +#include "subtitle_format_ass.h" +#include "text_file_reader.h" +#include "ass_dialogue.h" + + +///////////// +// Can read? +bool ASSSubtitleFormatReader::CanReadFile(wxString filename) { + return (filename.Right(4).Lower() == _T(".ass") || filename.Right(4).Lower() == _T(".ssa")); +} + + +///////////// +// Read file +void ASSSubtitleFormatReader::ReadFile(wxString filename,wxString encoding) { + using namespace std; + + // Reader + TextFileReader file(filename,encoding); + bool IsSSA = filename.Right(4).Lower() == _T(".ssa"); + + // Parse file + wxString curgroup; + int lasttime = -1; + while (file.HasMoreLines()) { + // Reads line + wxString wxbuffer = file.ReadLineFromFile(); + + // Convert v4 styles to v4+ styles + if (wxbuffer.Lower() == _T("[v4 styles]")) { + wxbuffer = _T("[V4+ Styles]"); + } + + // Set group + if (wxbuffer[0] == _T('[')) { + curgroup = wxbuffer; + } + + // Add line + try { + lasttime = AddLine(wxbuffer,curgroup,lasttime,IsSSA); + } + catch (wchar_t *err) { + Clear(); + throw wxString(_T("Error processing line: ")) + wxbuffer + _T(": ") + wxString(err); + } + catch (...) { + Clear(); + throw wxString(_T("Error processing line: ")) + wxbuffer; + } + } + + // Set ASS + SetIsASS(!IsSSA); +} diff --git a/core/subtitle_format_ass.h b/core/subtitle_format_ass.h new file mode 100644 index 000000000..7a174d406 --- /dev/null +++ b/core/subtitle_format_ass.h @@ -0,0 +1,58 @@ +// Copyright (c) 2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +#pragma once + + +/////////// +// Headers +#include "subtitle_format_reader.h" + + +////////////// +// Prototypes +class AssDialogue; + + +////////////// +// SRT reader +class ASSSubtitleFormatReader : public SubtitleFormatReader { +private: + +public: + bool CanReadFile(wxString filename); + void ReadFile(wxString filename,wxString forceEncoding); +}; diff --git a/core/subtitle_format_reader.cpp b/core/subtitle_format_reader.cpp index 4ac0e3a72..5bdc1bdb0 100644 --- a/core/subtitle_format_reader.cpp +++ b/core/subtitle_format_reader.cpp @@ -37,6 +37,9 @@ /////////// // Headers #include "subtitle_format_reader.h" +#include "subtitle_format_ass.h" +#include "subtitle_format_srt.h" +#include "subtitle_format_txt.h" #include "ass_file.h" @@ -67,11 +70,13 @@ void SubtitleFormatReader::SetTarget(AssFile *file) { //////// // List std::list SubtitleFormatReader::readers; +bool SubtitleFormatReader::loaded = false; ///////////////////////////// // Get an appropriate reader SubtitleFormatReader *SubtitleFormatReader::GetReader(wxString filename) { + LoadReaders(); std::list::iterator cur; SubtitleFormatReader *reader; for (cur=readers.begin();cur!=readers.end();cur++) { @@ -125,3 +130,38 @@ void SubtitleFormatReader::LoadDefault() { void SubtitleFormatReader::SetIsASS(bool isASS) { assFile->IsASS = isASS; } + + +//////////// +// Add line +int SubtitleFormatReader::AddLine(wxString data,wxString group,int lasttime,bool &IsSSA) { + return assFile->AddLine(data,group,lasttime,IsSSA); +} + + +/////////////// +// Add loaders +void SubtitleFormatReader::LoadReaders () { + if (!loaded) { + new ASSSubtitleFormatReader(); + new SRTSubtitleFormatReader(); + new TXTSubtitleFormatReader(); + } + loaded = true; +} + + +/////////////////// +// Destroy loaders +void SubtitleFormatReader::DestroyReaders () { + SubtitleFormatReader *reader; + std::list::iterator cur,next; + for (cur=readers.begin();cur!=readers.end();cur = next) { + next = cur; + next++; + reader = *cur; + readers.erase(cur); + delete reader; + } + readers.clear(); +} diff --git a/core/subtitle_format_reader.h b/core/subtitle_format_reader.h index a95f7bea2..116cb5e4a 100644 --- a/core/subtitle_format_reader.h +++ b/core/subtitle_format_reader.h @@ -56,6 +56,7 @@ private: void Register(); void Remove(); static std::list readers; + static bool loaded; AssFile *assFile; protected: @@ -72,6 +73,9 @@ public: void Clear(); void LoadDefault(); void SetIsASS(bool isASS); + int AddLine(wxString data,wxString group,int lasttime,bool &IsSSA); static SubtitleFormatReader *GetReader(wxString filename); + static void LoadReaders(); + static void DestroyReaders(); }; diff --git a/core/subtitle_format_txt.cpp b/core/subtitle_format_txt.cpp new file mode 100644 index 000000000..0fea461bc --- /dev/null +++ b/core/subtitle_format_txt.cpp @@ -0,0 +1,125 @@ +// Copyright (c) 2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +/////////// +// Headers +#include "subtitle_format_txt.h" +#include "text_file_reader.h" +#include "ass_dialogue.h" +#include "options.h" + + +///////////// +// Can read? +bool TXTSubtitleFormatReader::CanReadFile(wxString filename) { + return (filename.Right(4).Lower() == _T(".txt")); +} + + +///////////// +// Read file +void TXTSubtitleFormatReader::ReadFile(wxString filename,wxString encoding) { using namespace std; + + // Reader + TextFileReader file(filename,encoding,false); + + // Default + LoadDefault(); + SetIsASS(false); + + // Data + wxString actor; + wxString separator = Options.AsText(_T("Text actor separator")); + wxString comment = Options.AsText(_T("Text comment starter")); + bool isComment = false; + + // Parse file + AssDialogue *line = NULL; + while (file.HasMoreLines()) { + // Reads line + wxString value = file.ReadLineFromFile(); + + // Check if this isn't a timecodes file + if (value.Left(10) == _T("# timecode")) { + throw _T("File is a timecode file, cannot load as subtitles."); + } + + // Read comment data + isComment = false; + if (comment != _T("") && value.Left(comment.Length()) == comment) { + isComment = true; + value = value.Mid(comment.Length()); + } + + // Read actor data + if (!isComment && separator != _T("")) { + if (value[0] != _T(' ') && value[0] != _T('\t')) { + size_t pos = value.Find(separator); + if (pos != -1) { + actor = value.Left(pos); + actor.Trim(false); + actor.Trim(true); + value = value.Mid(pos+1); + value.Trim(false); + } + } + } + + // Trim spaces at start + value.Trim(false); + + // Sets line up + line = new AssDialogue(); + line->group = _T("[Events]"); + line->Style = _T("Default"); + if (isComment) line->Actor = _T(""); + else line->Actor = actor; + if (value.IsEmpty()) { + line->Actor = _T(""); + isComment = true; + } + line->Comment = isComment; + line->Text = value; + line->StartMS = 0; + line->Start.SetMS(0); + line->End.SetMS(0); + line->UpdateData(); + //line->ParseASSTags(); + + // Adds line + Line->push_back(line); + } +} diff --git a/core/subtitle_format_txt.h b/core/subtitle_format_txt.h new file mode 100644 index 000000000..4eefa4313 --- /dev/null +++ b/core/subtitle_format_txt.h @@ -0,0 +1,58 @@ +// Copyright (c) 2006, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + + +#pragma once + + +/////////// +// Headers +#include "subtitle_format_reader.h" + + +////////////// +// Prototypes +class AssDialogue; + + +////////////// +// TXT reader +class TXTSubtitleFormatReader : public SubtitleFormatReader { +private: + +public: + bool CanReadFile(wxString filename); + void ReadFile(wxString filename,wxString forceEncoding); +};