diff --git a/aegisub/src/ass_time.cpp b/aegisub/src/ass_time.cpp index 1f56afab9..47b77a8c4 100644 --- a/aegisub/src/ass_time.cpp +++ b/aegisub/src/ass_time.cpp @@ -251,11 +251,10 @@ int AssTime::GetTimeMiliseconds() { return (time % 1000); } /// int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; } -FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe, char sep) +FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe) : num(numerator) , den(denominator) , drop(dropframe) -, sep(sep) { if (drop) { // no dropframe for any other framerates @@ -268,7 +267,7 @@ FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe, c throw "FractionalTime: nonsensical enumerator or denominator"; } -int FractionalTime::ToMillisecs(wxString text) { +int FractionalTime::ToMillisecs(wxString text, char sep) { text.Trim(false); text.Trim(true); @@ -318,15 +317,15 @@ int FractionalTime::ToMillisecs(wxString text) { return msecs_f; } -AssTime FractionalTime::ToAssTime(wxString text) { - return AssTime(ToMillisecs(text)); +AssTime FractionalTime::ToAssTime(wxString text, char sep) { + return AssTime(ToMillisecs(text, sep)); } -wxString FractionalTime::FromAssTime(AssTime time) { - return FromMillisecs(time.GetMS()); +wxString FractionalTime::FromAssTime(AssTime time, char sep) { + return FromMillisecs(time.GetMS(), sep); } -wxString FractionalTime::FromMillisecs(int64_t msec) { +wxString FractionalTime::FromMillisecs(int64_t msec, char sep) { int h=0, m=0, s=0, f=0; // hours, minutes, seconds, fractions int fn = (msec*(int64_t)num) / (1000*den); // frame number diff --git a/aegisub/src/ass_time.h b/aegisub/src/ass_time.h index b98326c97..716f1ece7 100644 --- a/aegisub/src/ass_time.h +++ b/aegisub/src/ass_time.h @@ -91,21 +91,24 @@ class FractionalTime { int num; ///< Numerator int den; ///< Denominator bool drop; ///< Enable SMPTE dropframe handling - char sep; ///< Timecode component separator /// How often to drop frames when enabled static const int frames_per_period = 17982; public: - FractionalTime(int numerator=30, int denominator=1, bool dropframe=false, char sep=':'); + FractionalTime(int numerator=30, int denominator=1, bool dropframe=false); + + int Numerator() const { return num; } + int Denominator() const { return den; } + bool IsDrop() const { return drop; } /// Parse a SMPTE timecode, returning an AssTime - AssTime ToAssTime(wxString fractime); + AssTime ToAssTime(wxString fractime, char sep=':'); /// Parse a SMPTE timecode, returning milliseconds - int ToMillisecs(wxString fractime); + int ToMillisecs(wxString fractime, char sep=':'); /// Convert an AssTime to a SMPTE timecode - wxString FromAssTime(AssTime time); + wxString FromAssTime(AssTime time, char sep=':'); /// Convert milliseconds to a SMPTE timecode - wxString FromMillisecs(int64_t msec); + wxString FromMillisecs(int64_t msec, char sep=':'); }; diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index a43775704..a3ef9a6e9 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -109,19 +109,22 @@ void SubtitleFormat::AddLine(wxString data, wxString group, int &version, wxStri } /// @brief Ask the user to enter the FPS -SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) { +FractionalTime SubtitleFormat::AskForFPS(bool showSMPTE) { wxArrayString choices; - FPSRational fps_rat; - fps_rat.smpte_dropframe = false; // ensure it's false by default + bool drop = false; + int num; + int den; // Video FPS VideoContext *context = VideoContext::Get(); bool vidLoaded = context->TimecodesLoaded(); if (vidLoaded) { wxString vidFPS; - if (context->FPS().IsVFR()) vidFPS = "VFR"; - else vidFPS = wxString::Format("%.3f", context->FPS().FPS()); - choices.Add(wxString::Format("From video (%s)", vidFPS)); + if (context->FPS().IsVFR()) + vidFPS = "VFR"; + else + vidFPS = wxString::Format("%.3f", context->FPS().FPS()); + choices.Add(wxString::Format(_("From video (%s)"), vidFPS)); } // Standard FPS values @@ -141,51 +144,31 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) { // Ask int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"), _("FPS"), choices); - if (choice == -1) { - fps_rat.num = 0; - fps_rat.den = 0; - - return fps_rat; - } + if (choice == -1) + return FractionalTime(0, 0); // Get FPS from choice if (vidLoaded) choice--; // dropframe was displayed, that means all choices >4 are bumped up by 1 - if (showSMPTE) { - switch (choice) { - case -1: fps_rat.num = -1; fps_rat.den = 1; break; // VIDEO - case 0: fps_rat.num = 15; fps_rat.den = 1; break; - case 1: fps_rat.num = 24000; fps_rat.den = 1001; break; - case 2: fps_rat.num = 24; fps_rat.den = 1; break; - case 3: fps_rat.num = 25; fps_rat.den = 1; break; - case 4: fps_rat.num = 30000; fps_rat.den = 1001; break; - case 5: fps_rat.num = 30000; fps_rat.den = 1001; fps_rat.smpte_dropframe = true; break; - case 6: fps_rat.num = 30; fps_rat.den = 1; break; - case 7: fps_rat.num = 50; fps_rat.den = 1; break; - case 8: fps_rat.num = 60000; fps_rat.den = 1001; break; - case 9: fps_rat.num = 60; fps_rat.den = 1; break; - case 10: fps_rat.num = 120000; fps_rat.den = 1001; break; - case 11: fps_rat.num = 120; fps_rat.den = 1; break; - } - return fps_rat; - } else { - // dropframe wasn't displayed - switch (choice) { - case -1: fps_rat.num = -1; fps_rat.den = 1; break; // VIDEO - case 0: fps_rat.num = 15; fps_rat.den = 1; break; - case 1: fps_rat.num = 24000; fps_rat.den = 1001; break; - case 2: fps_rat.num = 24; fps_rat.den = 1; break; - case 3: fps_rat.num = 25; fps_rat.den = 1; break; - case 4: fps_rat.num = 30000; fps_rat.den = 1001; break; - case 5: fps_rat.num = 30; fps_rat.den = 1; break; - case 6: fps_rat.num = 50; fps_rat.den = 1; break; - case 7: fps_rat.num = 60000; fps_rat.den = 1001; break; - case 8: fps_rat.num = 60; fps_rat.den = 1; break; - case 9: fps_rat.num = 120000; fps_rat.den = 1001; break; - case 10: fps_rat.num = 120; fps_rat.den = 1; break; - } - return fps_rat; + if (!showSMPTE && choice > 4) ++choice; + + switch (choice) { + case -1: num = -1; den = 1; break; // VIDEO + case 0: num = 15; den = 1; break; + case 1: num = 24000; den = 1001; break; + case 2: num = 24; den = 1; break; + case 3: num = 25; den = 1; break; + case 4: num = 30000; den = 1001; break; + case 5: num = 30000; den = 1001; drop = true; break; + case 6: num = 30; den = 1; break; + case 7: num = 50; den = 1; break; + case 8: num = 60000; den = 1001; break; + case 9: num = 60; den = 1; break; + case 10: num = 120000; den = 1001; break; + case 11: num = 120; den = 1; break; } + + return FractionalTime(num, den, drop); } void SubtitleFormat::SortLines() { diff --git a/aegisub/src/subtitle_format.h b/aegisub/src/subtitle_format.h index 8fe157983..6e274c5ee 100644 --- a/aegisub/src/subtitle_format.h +++ b/aegisub/src/subtitle_format.h @@ -47,6 +47,7 @@ class AssFile; class AssEntry; +class FractionalTime; /// DOCME /// @class SubtitleFormat @@ -67,12 +68,6 @@ class SubtitleFormat { static std::list formats; protected: - struct FPSRational { - int num; - int den; - bool smpte_dropframe; - }; - std::list *Line; /// Copy the input subtitles file; must be called before making any changes @@ -112,7 +107,7 @@ protected: 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); + FractionalTime AskForFPS(bool showSMPTE=false); public: /// Constructor diff --git a/aegisub/src/subtitle_format_encore.cpp b/aegisub/src/subtitle_format_encore.cpp index b7b635fbe..a496b42a2 100644 --- a/aegisub/src/subtitle_format_encore.cpp +++ b/aegisub/src/subtitle_format_encore.cpp @@ -53,8 +53,8 @@ wxArrayString EncoreSubtitleFormat::GetWriteWildcards() const { } void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { - FPSRational fps_rat = AskForFPS(true); - if (fps_rat.num <= 0 || fps_rat.den <= 0) return; + FractionalTime ft = AskForFPS(true); + if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return; TextFileWriter file(filename, encoding); @@ -71,12 +71,12 @@ void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& e int i = 0; // Encore wants ; instead of : if we're dealing with NTSC dropframe stuff - FractionalTime ft(fps_rat.num, fps_rat.den, fps_rat.smpte_dropframe, fps_rat.smpte_dropframe ? ';' : ':'); + char sep = ft.IsDrop() ? ';' : ':'; for (std::list::iterator cur=Line->begin();cur!=Line->end();cur++) { if (AssDialogue *current = dynamic_cast(*cur)) { ++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, sep), ft.FromAssTime(current->End, sep), current->Text)); } } diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index a873e24da..746e1676c 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -107,10 +107,10 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const& } // If it wasn't an fps line, ask the user for it - FPSRational fps_rat = AskForFPS(); - if (fps_rat.num == 0) return; - else if (fps_rat.num > 0) - fps = agi::vfr::Framerate(fps_rat.num, fps_rat.den); + FractionalTime fps_rat = AskForFPS(); + if (fps_rat.Numerator() == 0) return; + else if (fps_rat.Numerator() > 0) + fps = agi::vfr::Framerate(fps_rat.Numerator(), fps_rat.Denominator()); else fps = VideoContext::Get()->FPS(); } @@ -131,12 +131,12 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const& void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { agi::vfr::Framerate fps; - FPSRational fps_rat = AskForFPS(); - if (fps_rat.num == 0 || fps_rat.den == 0) return; - if (fps_rat.num < 0 || fps_rat.den < 0) + FractionalTime fps_rat = AskForFPS(); + if (fps_rat.Numerator() == 0 || fps_rat.Denominator() == 0) return; + if (fps_rat.Numerator() < 0 || fps_rat.Denominator() < 0) fps = VideoContext::Get()->FPS(); else - fps = agi::vfr::Framerate(fps_rat.num, fps_rat.den); + fps = agi::vfr::Framerate(fps_rat.Numerator(), fps_rat.Denominator()); // Convert file CreateCopy(); diff --git a/aegisub/src/subtitle_format_transtation.cpp b/aegisub/src/subtitle_format_transtation.cpp index 77cd62526..510853a34 100644 --- a/aegisub/src/subtitle_format_transtation.cpp +++ b/aegisub/src/subtitle_format_transtation.cpp @@ -60,8 +60,8 @@ wxArrayString TranStationSubtitleFormat::GetWriteWildcards() const { } void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { - FPSRational fps_rat = AskForFPS(true); - if (fps_rat.num <= 0 || fps_rat.den <= 0) return; + FractionalTime ft = AskForFPS(true); + if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return; TextFileWriter file(filename, encoding); @@ -77,7 +77,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con AssDialogue *cur = dynamic_cast(*it); if (prev && cur) { - file.WriteLineToFile(ConvertLine(prev, &fps_rat, cur->Start.GetMS())); + file.WriteLineToFile(ConvertLine(prev, &ft, cur->Start.GetMS())); file.WriteLineToFile(""); } @@ -87,7 +87,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con // flush last line if (prev) - file.WriteLineToFile(ConvertLine(prev, &fps_rat, -1)); + file.WriteLineToFile(ConvertLine(prev, &ft, -1)); // Every file must end with this line file.WriteLineToFile("SUB["); @@ -95,7 +95,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con ClearCopy(); } -wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRational *fps_rat, int nextl_start) { +wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FractionalTime *ft, int nextl_start) { int valign = 0; const char *halign = " "; // default is centered const char *type = "N"; // no special style @@ -119,10 +119,9 @@ wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRationa // start of next one, since the end timestamp is inclusive and the lines // would overlap if left as is. if (nextl_start > 0 && end.GetMS() == nextl_start) - end.SetMS(end.GetMS() - ((1000*fps_rat->den)/fps_rat->num)); + end.SetMS(end.GetMS() - ((1000*ft->Denominator())/ft->Numerator())); - FractionalTime ft(fps_rat->num, fps_rat->den, fps_rat->smpte_dropframe); - wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n"; + wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft->FromAssTime(start) + ">" + ft->FromAssTime(end) + "]\r\n"; // Process text wxString lineEnd = "\r\n"; diff --git a/aegisub/src/subtitle_format_transtation.h b/aegisub/src/subtitle_format_transtation.h index 7dca80133..122a2cea5 100644 --- a/aegisub/src/subtitle_format_transtation.h +++ b/aegisub/src/subtitle_format_transtation.h @@ -44,7 +44,7 @@ class AssDialogue; /// /// DOCME class TranStationSubtitleFormat : public SubtitleFormat { - wxString ConvertLine(AssDialogue *line, FPSRational *fps_rat, int nextl_start); + wxString ConvertLine(AssDialogue *line, FractionalTime *ft, int nextl_start); public: TranStationSubtitleFormat();