Tidy up HMSF handling in a few places.
[dcpomatic.git] / src / lib / dcpomatic_time.h
index 5f00807bdf2c3c4da605e577e3c18f7214d90391..00a31a7a7057ab5ece9f7ba4b26984bf0735f91d 100644 (file)
 #include "frame_rate_change.h"
 #include "dcpomatic_assert.h"
 #include <boost/optional.hpp>
-#include <boost/foreach.hpp>
 #include <stdint.h>
 #include <cmath>
 #include <ostream>
 #include <iomanip>
 #include <cstdio>
 
+struct dcpomatic_time_ceil_test;
+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, ContentTime and DCPTime, and we want it to be impossible to
+ *  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
  *  sure if it's the best way to do it.
  *
@@ -63,6 +87,16 @@ public:
        /* Explicit conversion from type O */
        Time (Time<O, S> 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;
        }
@@ -113,16 +147,24 @@ public:
                return *this;
        }
 
+       Time<S, O> operator/ (int o) const {
+               return Time<S, O> (_t / o);
+       }
+
        /** Round up to the nearest sampling interval
         *  at some sampling rate.
         *  @param r Sampling rate.
         */
-       Time<S, O> ceil (float r) const {
-               return Time<S, O> (llrint (HZ * frames_ceil(r) / double(r)));
+       Time<S, O> ceil (double r) const {
+               return Time<S, O> (llrint (HZ * frames_ceil(r) / r));
+       }
+
+       Time<S, O> floor (double r) const {
+               return Time<S, O> (llrint (HZ * frames_floor(r) / r));
        }
 
-       Time<S, O> floor (float r) const {
-               return Time<S, O> (llrint (HZ * frames_floor(r) / double(r)));
+       Time<S, O> round (double r) const {
+               return Time<S, O> (llrint (HZ * frames_round(r) / r));
        }
 
        double seconds () const {
@@ -158,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 <typename T>
-       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<int> (ff);
+               hmsf.f = static_cast<int> (ff);
+               return hmsf;
        }
 
        template <typename T>
        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;
        }
 
@@ -217,12 +254,13 @@ public:
                return Time<S, O> (INT64_MAX);
        }
 
+       static const int HZ = 96000;
+
 private:
-       friend struct dcpomatic_time_ceil_test;
-       friend struct dcpomatic_time_floor_test;
+       friend struct ::dcpomatic_time_ceil_test;
+       friend struct ::dcpomatic_time_floor_test;
 
        Type _t;
-       static const int HZ = 96000;
 };
 
 class ContentTimeDifferentiator {};
@@ -305,9 +343,9 @@ std::list<TimePeriod<T> > subtract (TimePeriod<T> A, std::list<TimePeriod<T> > c
        std::list<TimePeriod<T> > result;
        result.push_back (A);
 
-       BOOST_FOREACH (TimePeriod<T> i, B) {
+       for (auto i: B) {
                std::list<TimePeriod<T> > new_result;
-               BOOST_FOREACH (TimePeriod<T> j, result) {
+               for (auto j: result) {
                        boost::optional<TimePeriod<T> > ov = i.overlap (j);
                        if (ov) {
                                if (*ov == i) {
@@ -348,4 +386,6 @@ std::string to_string (ContentTime t);
 std::string to_string (DCPTime t);
 std::string to_string (DCPTimePeriod p);
 
+}
+
 #endif