diff --git a/aegisub/src/ass_time.cpp b/aegisub/src/ass_time.cpp index 0090c66fd..7ea235f98 100644 --- a/aegisub/src/ass_time.cpp +++ b/aegisub/src/ass_time.cpp @@ -251,20 +251,10 @@ int AssTime::GetTimeMiliseconds() { return (time % 1000); } /// int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; } -FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe) -: num(numerator) -, den(denominator) +FractionalTime::FractionalTime(agi::vfr::Framerate fps, bool dropframe) +: fps(fps) , drop(dropframe) { - if (drop) { - // no dropframe for any other framerates - num = 30000; - den = 1001; - } - - // fractions < 1 are not welcome here - if ((num <= 0 || den <= 0) || (num < den)) - throw "FractionalTime: nonsensical enumerator or denominator"; } wxString FractionalTime::FromAssTime(AssTime time, char sep) { @@ -273,7 +263,7 @@ wxString FractionalTime::FromAssTime(AssTime time, char sep) { 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 + int fn = fps.FrameAtTime(msec); // return 00:00:00:00 if (msec <= 0) { @@ -302,7 +292,7 @@ wxString FractionalTime::FromMillisecs(int64_t msec, char sep) { DEATH TO SMPTE */ - int fps_approx = floor((double(num)/double(den))+0.5); + int fps_approx = floor(fps.FPS() + 0.5); int frames_per_h = 3600*fps_approx; int frames_per_m = 60*fps_approx; int frames_per_s = fps_approx; diff --git a/aegisub/src/ass_time.h b/aegisub/src/ass_time.h index 1f67c3b38..83a78f0a7 100644 --- a/aegisub/src/ass_time.h +++ b/aegisub/src/ass_time.h @@ -42,6 +42,8 @@ #include #endif +#include + /// DOCME /// @class AssTime /// @brief DOCME @@ -87,20 +89,17 @@ AssTime operator - (const AssTime &t1, const AssTime &t2); /// /// DOCME class FractionalTime { - int time; ///< Time in miliseconds - int num; ///< Numerator - int den; ///< Denominator + agi::vfr::Framerate fps; bool drop; ///< Enable SMPTE dropframe handling /// 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); + FractionalTime(agi::vfr::Framerate fps, bool dropframe = false); - int Numerator() const { return num; } - int Denominator() const { return den; } bool IsDrop() const { return drop; } + agi::vfr::Framerate const& FPS() const { return fps; } /// Convert an AssTime to a SMPTE timecode wxString FromAssTime(AssTime time, char sep=':'); diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index a3ef9a6e9..a3f1682a8 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -112,8 +112,6 @@ void SubtitleFormat::AddLine(wxString data, wxString group, int &version, wxStri FractionalTime SubtitleFormat::AskForFPS(bool showSMPTE) { wxArrayString choices; bool drop = false; - int num; - int den; // Video FPS VideoContext *context = VideoContext::Get(); @@ -142,10 +140,12 @@ FractionalTime SubtitleFormat::AskForFPS(bool showSMPTE) { choices.Add(_("119.880 FPS (NTSC x4)")); choices.Add(_("120.000 FPS")); + using agi::vfr::Framerate; + Framerate fps; // Ask int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"), _("FPS"), choices); if (choice == -1) - return FractionalTime(0, 0); + return FractionalTime(fps); // Get FPS from choice if (vidLoaded) choice--; @@ -153,22 +153,22 @@ FractionalTime SubtitleFormat::AskForFPS(bool showSMPTE) { 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; + case -1: fps = context->FPS(); break; // VIDEO + case 0: fps = Framerate(15, 1); break; + case 1: fps = Framerate(24000, 1001); break; + case 2: fps = Framerate(24, 1); break; + case 3: fps = Framerate(25, 1); break; + case 4: fps = Framerate(30000, 1001); break; + case 5: fps = Framerate(30000, 1001); drop = true; break; + case 6: fps = Framerate(30, 1); break; + case 7: fps = Framerate(50, 1); break; + case 8: fps = Framerate(60000, 1001); break; + case 9: fps = Framerate(60, 1); break; + case 10: fps = Framerate(120000, 1001); break; + case 11: fps = Framerate(120, 1); break; } - return FractionalTime(num, den, drop); + return FractionalTime(fps, drop); } void SubtitleFormat::SortLines() { diff --git a/aegisub/src/subtitle_format_encore.cpp b/aegisub/src/subtitle_format_encore.cpp index a496b42a2..4d029dc32 100644 --- a/aegisub/src/subtitle_format_encore.cpp +++ b/aegisub/src/subtitle_format_encore.cpp @@ -54,7 +54,7 @@ wxArrayString EncoreSubtitleFormat::GetWriteWildcards() const { void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { FractionalTime ft = AskForFPS(true); - if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return; + if (!ft.FPS().IsLoaded()) return; TextFileWriter file(filename, encoding); diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index 746e1676c..d91b1e0e4 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -107,12 +107,8 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const& } // If it wasn't an fps line, ask the user for it - 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(); + fps = AskForFPS().FPS(); + if (!fps.IsLoaded()) return; } text.Replace("|", "\\N"); @@ -129,16 +125,9 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const& } void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { - agi::vfr::Framerate fps; + agi::vfr::Framerate fps = AskForFPS().FPS(); + if (!fps.IsLoaded()) return; - 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.Numerator(), fps_rat.Denominator()); - - // Convert file CreateCopy(); SortLines(); StripComments(); diff --git a/aegisub/src/subtitle_format_transtation.cpp b/aegisub/src/subtitle_format_transtation.cpp index 510853a34..80efe6ed8 100644 --- a/aegisub/src/subtitle_format_transtation.cpp +++ b/aegisub/src/subtitle_format_transtation.cpp @@ -61,7 +61,7 @@ wxArrayString TranStationSubtitleFormat::GetWriteWildcards() const { void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) { FractionalTime ft = AskForFPS(true); - if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return; + if (!ft.FPS().IsLoaded()) return; TextFileWriter file(filename, encoding); @@ -119,7 +119,7 @@ wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, Fractional // 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*ft->Denominator())/ft->Numerator())); + end.SetMS(ft->FPS().TimeAtFrame(ft->FPS().FrameAtTime(end.GetMS(), agi::vfr::END) - 1, agi::vfr::END)); wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft->FromAssTime(start) + ">" + ft->FromAssTime(end) + "]\r\n";