Add timecode methods to Time
authorCarl Hetherington <cth@carlh.net>
Fri, 20 Jun 2014 10:55:46 +0000 (11:55 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 20 Jun 2014 10:55:46 +0000 (11:55 +0100)
src/lib/dcpomatic_time.h
src/wx/timecode.cc
test/util_test.cc

index 1421040733f8c7d709723bc2085828a667354554..4afc9ab40623e09a226965ce8cdfb7e7a77d7784 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <cmath>
 #include <ostream>
+#include <sstream>
+#include <iomanip>
 #include <stdint.h>
 #include "frame_rate_change.h"
 
@@ -56,6 +58,42 @@ public:
                return rint (_t * r / HZ);
        }
 
+       template <typename T>
+       void split (T r, int& h, int& m, int& s, int& f) 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 (r);
+               
+               h = ff / (3600 * r);
+               ff -= h * 3600 * r;
+               m = ff / (60 * r);
+               ff -= m * 60 * r;
+               s = ff / r;
+               ff -= s * r;
+
+               f = static_cast<int> (ff);
+       }
+
+       template <typename T>
+       std::string timecode (T r) const {
+               int h;
+               int m;
+               int s;
+               int f;
+               split (r, h, m, s, f);
+
+               std::ostringstream o;
+               o.width (2);
+               o.fill ('0');
+               o << std::setw(2) << std::setfill('0') << h << ":"
+                 << std::setw(2) << std::setfill('0') << m << ":"
+                 << std::setw(2) << std::setfill('0') << s << ":"
+                 << std::setw(2) << std::setfill('0') << f;
+               return o.str ();
+       }
+
 protected:
        friend class dcptime_round_up_test;
        
index 1ab4b590b2b130b4f7d0c80cd21c766c6706ff41..86e1997e961ba31ad080b70bfe6fc6fbb7ac2de5 100644 (file)
@@ -85,24 +85,18 @@ Timecode::Timecode (wxWindow* parent)
 void
 Timecode::set (DCPTime t, int fps)
 {
-       /* Do this calculation with frames so that we can round
-          to a frame boundary at the start rather than the end.
-       */
-       int64_t f = rint (t.seconds() * fps);
-       
-       int const h = f / (3600 * fps);
-       f -= h * 3600 * fps;
-       int const m = f / (60 * fps);
-       f -= m * 60 * fps;
-       int const s = f / fps;
-       f -= s * fps;
+       int h;
+       int m;
+       int s;
+       int f;
+       t.split (fps, h, m, s, f);
 
        checked_set (_hours, lexical_cast<string> (h));
        checked_set (_minutes, lexical_cast<string> (m));
        checked_set (_seconds, lexical_cast<string> (s));
        checked_set (_frames, lexical_cast<string> (f));
 
-       _fixed->SetLabel (wxString::Format ("%02d:%02d:%02d.%02" wxLongLongFmtSpec "d", h, m, s, f));
+       _fixed->SetLabel (std_to_wx (t.timecode (fps)));
 }
 
 DCPTime
index 5eb3e27f185a70039edf090f39ee19160b131650..39cc0e6bf7df07956b56191e88af6465ee92db71 100644 (file)
@@ -88,3 +88,9 @@ BOOST_AUTO_TEST_CASE (divide_with_round_test)
 
        BOOST_CHECK_EQUAL (divide_with_round (1000, 500), 2);
 }
+
+BOOST_AUTO_TEST_CASE (timecode_test)
+{
+       DCPTime t = DCPTime::from_seconds (2 * 60 * 60 + 4 * 60 + 31) + DCPTime::from_frames (19, 24);
+       BOOST_CHECK_EQUAL (t.timecode (24), "02:04:31:19");
+}