From ee5aea601c61e9f246328f77c666c5b3b16a249d Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Mon, 18 Jun 2007 04:03:58 +0000 Subject: [PATCH] Added full read-write support for MicroDVD subtitles, including reading of fps from first line, or asking user for one, including that of video. Originally committed to SVN as r1245. --- aegisub/changelog.txt | 2 + aegisub/subtitle_format.cpp | 54 ++++++++ aegisub/subtitle_format.h | 1 + aegisub/subtitle_format_microdvd.cpp | 196 +++++++++++++++++++++++++++ aegisub/subtitle_format_microdvd.h | 58 ++++++++ aegisub/subtitle_format_ttxt.cpp | 1 + aegisub/subtitle_format_ttxt.h | 1 - 7 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 aegisub/subtitle_format_microdvd.cpp create mode 100644 aegisub/subtitle_format_microdvd.h diff --git a/aegisub/changelog.txt b/aegisub/changelog.txt index fa8acf88e..75d70b0b7 100644 --- a/aegisub/changelog.txt +++ b/aegisub/changelog.txt @@ -82,6 +82,8 @@ Please visit http://aegisub.net to download latest version o Added support for reading ASS, SSA and SRT softsubs directly from Matroska files. (AMZ) o Fixed loading of SRT and TXT files, which were causing an empty line to appear at the start of the file. (AMZ) o Added support for reading v4.00++ (ASS2) files. (AMZ) + o Added very basic reading support for MPEG-4 Streaming Text (TTXT) subtitles. (AMZ) + o Added full read-write support for MicroDVD subtitles. (AMZ) - Changes to main menu: o There are now new options, and most were moved around to have better organization. (AMZ/jfs) o General tweaks changes, such as better icons, and fixing of flickering and slowness. (AMZ) diff --git a/aegisub/subtitle_format.cpp b/aegisub/subtitle_format.cpp index 9f103ad78..1cde061c8 100644 --- a/aegisub/subtitle_format.cpp +++ b/aegisub/subtitle_format.cpp @@ -42,7 +42,9 @@ #include "subtitle_format_txt.h" #include "subtitle_format_ttxt.h" #include "subtitle_format_mkv.h" +#include "subtitle_format_microdvd.h" #include "ass_file.h" +#include "vfr.h" /////////////// @@ -125,6 +127,7 @@ void SubtitleFormat::LoadFormats () { new SRTSubtitleFormat(); new TXTSubtitleFormat(); new TTXTSubtitleFormat(); + new MicroDVDSubtitleFormat(); new MKVSubtitleFormat(); } loaded = true; @@ -260,3 +263,54 @@ wxString SubtitleFormat::GetWildcards(int mode) { // Return final list return final; } + + +///////////////////////////////// +// Ask the user to enter the FPS +double SubtitleFormat::AskForFPS() { + wxArrayString choices; + + // Video FPS + bool vidLoaded = VFR_Output.IsLoaded(); + if (vidLoaded) { + wxString vidFPS; + if (VFR_Output.GetFrameRateType() == VFR) vidFPS = _T("VFR"); + else vidFPS = wxString::Format(_T("%.3f"),VFR_Output.GetAverage()); + choices.Add(wxString::Format(_T("From video (%s)"),vidFPS.c_str())); + } + + // Standard FPS values + choices.Add(_("15.000 FPS")); + choices.Add(_("23.976 FPS (Decimated NTSC)")); + choices.Add(_("24.000 FPS (FILM)")); + choices.Add(_("25.000 FPS (PAL)")); + choices.Add(_("29.970 FPS (NTSC)")); + choices.Add(_("30.000 FPS")); + choices.Add(_("59.940 FPS (NTSC x2)")); + choices.Add(_("60.000 FPS")); + choices.Add(_("119.880 FPS (NTSC x4)")); + choices.Add(_("120.000 FPS")); + + // Ask + int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"),_("FPS"),choices); + if (choice == -1) return 0.0; + + // Get FPS from choice + if (vidLoaded) choice--; + switch (choice) { + case -1: return -1.0; break; // VIDEO + case 0: return 15.0; break; + case 1: return 24.0 / 1.001; break; + case 2: return 24.0; break; + case 3: return 25.0; break; + case 4: return 30.0 / 1.001; break; + case 5: return 30.0; break; + case 6: return 60.0 / 1.001; break; + case 7: return 60.0; break; + case 8: return 120.0 / 1.001; break; + case 9: return 120.0; break; + } + + // fubar + return 0.0; +} diff --git a/aegisub/subtitle_format.h b/aegisub/subtitle_format.h index 69e15e30e..05d4066b9 100644 --- a/aegisub/subtitle_format.h +++ b/aegisub/subtitle_format.h @@ -71,6 +71,7 @@ protected: void LoadDefault(bool defline=true); AssFile *GetAssFile() { return assFile; } int AddLine(wxString data,wxString group,int lasttime,int &version,wxString *outgroup=NULL); + double AskForFPS(); virtual wxString GetName()=0; virtual wxArrayString GetReadWildcards(); diff --git a/aegisub/subtitle_format_microdvd.cpp b/aegisub/subtitle_format_microdvd.cpp new file mode 100644 index 000000000..378960263 --- /dev/null +++ b/aegisub/subtitle_format_microdvd.cpp @@ -0,0 +1,196 @@ +// 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_microdvd.h" +#include "ass_dialogue.h" +#include "ass_time.h" +#include "text_file_reader.h" +#include "text_file_writer.h" +#include "vfr.h" +#include + + +/////////////////// +// Get format name +wxString MicroDVDSubtitleFormat::GetName() { + return _T("MicroDVD"); +} + + +////////////////////// +// Get read wildcards +wxArrayString MicroDVDSubtitleFormat::GetReadWildcards() { + wxArrayString formats; + formats.Add(_T("sub")); + return formats; +} + + +/////////////////////// +// Get write wildcards +wxArrayString MicroDVDSubtitleFormat::GetWriteWildcards() { + return GetReadWildcards(); +} + + +//////////////////// +// Can read a file? +bool MicroDVDSubtitleFormat::CanReadFile(wxString filename) { + // Return false immediately if extension is wrong + if (filename.Right(4).Lower() != _T(".sub")) return false; + + // Since there is an infinity of .sub formats, load first line and check if it's valid + TextFileReader file(filename); + if (file.HasMoreLines()) { + wxRegEx exp(_T("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$"),wxRE_ADVANCED); + return exp.Matches(file.ReadLineFromFile()); + } + + return false; +} + + +///////////////////// +// Can write a file? +bool MicroDVDSubtitleFormat::CanWriteFile(wxString filename) { + return (filename.Right(4).Lower() == _T(".sub")); +} + + +/////////////// +// Read a file +void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) { + // Load and prepare regexp + TextFileReader file(filename); + wxRegEx exp(_T("^[\\{\\[]([0-9]+)[\\}\\]][\\{\\[]([0-9]+)[\\}\\]](.*)$"),wxRE_ADVANCED); + + // Load default + LoadDefault(false); + + // Prepare conversion + FrameRate cfr; + FrameRate *rate = 𝔠 + + // Loop + bool isFirst = true; + double fps = 0.0; + while (file.HasMoreLines()) { + wxString line = file.ReadLineFromFile(); + if (exp.Matches(line)) { + // Parse + long f1,f2; + exp.GetMatch(line,1).ToLong(&f1); + exp.GetMatch(line,2).ToLong(&f2); + wxString text = exp.GetMatch(line,3); + + // If it's the first, check if it contains fps information + if (isFirst) { + if (f1 == 1 && f2 == 1) { + // Convert fps + try { + text.ToDouble(&fps); + } + catch (...) {} + } + isFirst = false; + + // If it wasn't an fps line, ask the user for it + if (fps == 0.0) { + fps = AskForFPS(); + if (fps == 0.0) return; + else if (fps > 0.0) cfr.SetCFR(fps); + else rate = &VFR_Output; + } + else continue; + } + + // Start and end times + int start,end; + start = rate->GetTimeAtFrame(f1,true); + end = rate->GetTimeAtFrame(f2,false); + + // Process text + text.Replace(_T("|"),_T("\\N")); + + // Create and insert line + AssDialogue *line = new AssDialogue(); + line->group = _T("[Events]"); + line->Style = _T("Default"); + line->StartMS = start; + line->Start.SetMS(start); + line->End.SetMS(end); + line->Text = text; + Line->push_back(line); + } + } +} + + +//////////////// +// Write a file +void MicroDVDSubtitleFormat::WriteFile(wxString filename,wxString encoding) { + // Set FPS + FrameRate cfr; + FrameRate *rate = 𝔠 + double fps = AskForFPS(); + if (fps == 0.0) return; + else if (fps > 0.0) cfr.SetCFR(fps); + else rate = &VFR_Output; + + // Open file + TextFileWriter file(filename,encoding); + + // Write FPS line + file.WriteLineToFile(wxString::Format(_T("{1}{1}%.6f"),fps)); + + // Write lines + using std::list; + for (list::iterator cur=Line->begin();cur!=Line->end();cur++) { + AssDialogue *current = AssEntry::GetAsDialogue(*cur); + if (current && !current->Comment) { + // Prepare data + int start = rate->GetFrameAtTime(current->Start.GetMS(),true); + int end = rate->GetFrameAtTime(current->End.GetMS(),false); + wxString text = current->Text; + text.Replace(_T("\\N"),_T("|")); + + // Write data + file.WriteLineToFile(wxString::Format(_T("{%i}{%i}%s"),start,end,text.c_str())); + } + } +} diff --git a/aegisub/subtitle_format_microdvd.h b/aegisub/subtitle_format_microdvd.h new file mode 100644 index 000000000..e6e215845 --- /dev/null +++ b/aegisub/subtitle_format_microdvd.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.h" + + +////////////////////////// +// MicroDVD reader/writer +class MicroDVDSubtitleFormat : public SubtitleFormat { +public: + wxString GetName(); + wxArrayString GetReadWildcards(); + wxArrayString GetWriteWildcards(); + + bool CanReadFile(wxString filename); + void ReadFile(wxString filename,wxString forceEncoding); + + bool CanWriteFile(wxString filename); + void WriteFile(wxString filename,wxString encoding); +}; diff --git a/aegisub/subtitle_format_ttxt.cpp b/aegisub/subtitle_format_ttxt.cpp index 3826b4dd7..0d3533e83 100644 --- a/aegisub/subtitle_format_ttxt.cpp +++ b/aegisub/subtitle_format_ttxt.cpp @@ -39,6 +39,7 @@ #include "subtitle_format_ttxt.h" #include "ass_dialogue.h" #include "ass_time.h" +#include /////////////////// diff --git a/aegisub/subtitle_format_ttxt.h b/aegisub/subtitle_format_ttxt.h index d190288ae..5342b8544 100644 --- a/aegisub/subtitle_format_ttxt.h +++ b/aegisub/subtitle_format_ttxt.h @@ -40,7 +40,6 @@ /////////// // Headers #include "subtitle_format.h" -#include //////////////////////