From ef31a94cd00dcc88fc83093cbc709b5b79acc4b6 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 20 Mar 2021 10:19:46 +0100 Subject: [PATCH] Tidy up HMSF handling in a few places. --- src/lib/dcpomatic_time.h | 63 ++++++++++++++++++++++++++++------------ src/lib/reel_writer.cc | 5 ++-- src/lib/writer.cc | 15 +++++----- src/wx/content_view.cc | 9 +++--- src/wx/timecode.h | 59 +++++++++++++++---------------------- 5 files changed, 81 insertions(+), 70 deletions(-) diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h index 62d8a28cc..00a31a7a7 100644 --- a/src/lib/dcpomatic_time.h +++ b/src/lib/dcpomatic_time.h @@ -39,6 +39,26 @@ struct dcpomatic_time_floor_test; namespace dcpomatic { + +class HMSF +{ +public: + HMSF () {} + + HMSF (int h_, int m_, int s_, int f_) + : h(h_) + , m(m_) + , s(s_) + , f(f_) + {} + + int h = 0; + int m = 0; + int s = 0; + int f = 0; +}; + + /** A time in seconds, expressed as a number scaled up by Time::HZ. We want two different * versions of this class, dcpomatic::ContentTime and dcpomatic::DCPTime, and we want it to be impossible to * convert implicitly between the two. Hence there's this template hack. I'm not @@ -67,6 +87,16 @@ public: /* Explicit conversion from type O */ Time (Time d, FrameRateChange f); + /** @param hmsf Hours, minutes, seconds, frames. + * @param fps Frame rate + */ + Time (HMSF const& hmsf, float fps) { + *this = from_seconds (hmsf.h * 3600) + + from_seconds (hmsf.m * 60) + + from_seconds (hmsf.s) + + from_frames (hmsf.f, fps); + } + Type get () const { return _t; } @@ -170,39 +200,34 @@ public: /** Split a time into hours, minutes, seconds and frames. * @param r Frames per second. - * @param h Returned hours. - * @param m Returned minutes. - * @param s Returned seconds. - * @param f Returned frames. + * @return Split time. */ template - void split (T r, int& h, int& m, int& s, int& f) const + HMSF split (T r) const { /* Do this calculation with frames so that we can round to a frame boundary at the start rather than the end. */ - int64_t ff = frames_round (r); + auto ff = frames_round (r); + HMSF hmsf; - h = ff / (3600 * r); - ff -= h * 3600 * r; - m = ff / (60 * r); - ff -= m * 60 * r; - s = ff / r; - ff -= s * r; + hmsf.h = ff / (3600 * r); + ff -= hmsf.h * 3600 * r; + hmsf.m = ff / (60 * r); + ff -= hmsf.m * 60 * r; + hmsf.s = ff / r; + ff -= hmsf.s * r; - f = static_cast (ff); + hmsf.f = static_cast (ff); + return hmsf; } template std::string timecode (T r) const { - int h; - int m; - int s; - int f; - split (r, h, m, s, f); + auto hmsf = split (r); char buffer[128]; - snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d:%02d", h, m, s, f); + snprintf (buffer, sizeof(buffer), "%02d:%02d:%02d:%02d", hmsf.h, hmsf.m, hmsf.s, hmsf.f); return buffer; } diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 184707373..294c0b7b6 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -691,10 +691,9 @@ ReelWriter::create_reel_markers (shared_ptr reel) const if (!reel_markers.empty ()) { auto ma = make_shared(dcp::Fraction(film()->video_frame_rate(), 1), reel->duration(), 0); for (auto const& i: reel_markers) { - int h, m, s, f; DCPTime relative = i.second - _period.from; - relative.split (film()->video_frame_rate(), h, m, s, f); - ma->set (i.first, dcp::Time(h, m, s, f, film()->video_frame_rate())); + auto hmsf = relative.split (film()->video_frame_rate()); + ma->set (i.first, dcp::Time(hmsf.h, hmsf.m, hmsf.s, hmsf.f, film()->video_frame_rate())); } reel->add (ma); } diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 035fc2b1d..54e7473e8 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -733,15 +733,14 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp) } boost::algorithm::replace_all (text, "$AUDIO", description); - int h, m, s, fr; - film()->length().split(film()->video_frame_rate(), h, m, s, fr); + auto const hmsf = film()->length().split(film()->video_frame_rate()); string length; - if (h == 0 && m == 0) { - length = String::compose("%1s", s); - } else if (h == 0 && m > 0) { - length = String::compose("%1m%2s", m, s); - } else if (h > 0 && m > 0) { - length = String::compose("%1h%2m%3s", h, m, s); + if (hmsf.h == 0 && hmsf.m == 0) { + length = String::compose("%1s", hmsf.s); + } else if (hmsf.h == 0 && hmsf.m > 0) { + length = String::compose("%1m%2s", hmsf.m, hmsf.s); + } else if (hmsf.h > 0 && hmsf.m > 0) { + length = String::compose("%1h%2m%3s", hmsf.h, hmsf.m, hmsf.s); } boost::algorithm::replace_all (text, "$LENGTH", length); diff --git a/src/wx/content_view.cc b/src/wx/content_view.cc index 44e575d93..b3a66a7be 100644 --- a/src/wx/content_view.cc +++ b/src/wx/content_view.cc @@ -133,13 +133,12 @@ ContentView::add (shared_ptr content) wxListItem it; it.SetId(N); it.SetColumn(0); - DCPTime length = content->approximate_length (); - int h, m, s, f; - length.split (24, h, m, s, f); - it.SetText(wxString::Format("%02d:%02d:%02d", h, m, s)); + auto length = content->approximate_length (); + auto const hmsf = length.split (24); + it.SetText(wxString::Format("%02d:%02d:%02d", hmsf.h, hmsf.m, hmsf.s)); InsertItem(it); - shared_ptr dcp = dynamic_pointer_cast(content); + auto dcp = dynamic_pointer_cast(content); if (dcp && dcp->content_kind()) { it.SetId(N); it.SetColumn(1); diff --git a/src/wx/timecode.h b/src/wx/timecode.h index 3746b32cd..3fe35981d 100644 --- a/src/wx/timecode.h +++ b/src/wx/timecode.h @@ -67,56 +67,45 @@ public: void set (T t, float fps) { - int h; - int m; - int s; - int f; - t.split (fps, h, m, s, f); + auto const hmsf = t.split (fps); - checked_set (_hours, dcp::raw_convert(h)); - checked_set (_minutes, dcp::raw_convert(m)); - checked_set (_seconds, dcp::raw_convert(s)); - checked_set (_frames, dcp::raw_convert(f)); + checked_set (_hours, dcp::raw_convert(hmsf.h)); + checked_set (_minutes, dcp::raw_convert(hmsf.m)); + checked_set (_seconds, dcp::raw_convert(hmsf.s)); + checked_set (_frames, dcp::raw_convert(hmsf.f)); checked_set (_fixed, t.timecode (fps)); } void set_hint (T t, float fps) { - int h; - int m; - int s; - int f; - t.split (fps, h, m, s, f); - - _hours->SetHint (std_to_wx(dcp::raw_convert(h))); - _minutes->SetHint (std_to_wx(dcp::raw_convert(m))); - _seconds->SetHint (std_to_wx(dcp::raw_convert(s))); - _frames->SetHint (std_to_wx(dcp::raw_convert(f))); + auto hmsf = t.split (fps); + + _hours->SetHint (std_to_wx(dcp::raw_convert(hmsf.h))); + _minutes->SetHint (std_to_wx(dcp::raw_convert(hmsf.m))); + _seconds->SetHint (std_to_wx(dcp::raw_convert(hmsf.s))); + _frames->SetHint (std_to_wx(dcp::raw_convert(hmsf.f))); } T get (float fps) const { - T t; - auto value_or_hint = [](wxTextCtrl const * t) { - if (!t->GetValue().IsEmpty()) { - return wx_to_std (t->GetValue()); - } else { - return wx_to_std (t->GetHint()); + auto s = wx_to_std (t->GetValue().IsEmpty() ? t->GetHint() : t->GetValue()); + if (s.empty()) { + return 0; } + return dcp::raw_convert(s); }; - std::string const h = value_or_hint (_hours); - t += T::from_seconds (dcp::raw_convert(h.empty() ? "0" : h) * 3600); - std::string const m = value_or_hint (_minutes); - t += T::from_seconds (dcp::raw_convert(m.empty() ? "0" : m) * 60); - std::string const s = value_or_hint (_seconds); - t += T::from_seconds (dcp::raw_convert(s.empty() ? "0" : s)); - std::string const f = value_or_hint (_frames); - t += T::from_frames (dcp::raw_convert(f.empty() ? "0" : f), fps); - - return t; + return T ( + { + value_or_hint(_hours), + value_or_hint(_minutes), + value_or_hint(_seconds), + value_or_hint(_frames) + }, + fps + ); } }; -- 2.30.2