Merge remote-tracking branch 'origin/master' into 1.0
[dcpomatic.git] / src / lib / dcpomatic_time.h
index 59986e6d892994787301325b7a4fc15316d89911..a0bbad06aeaeeed6530d214551fcbd82ab3a4d4d 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <cmath>
 #include <ostream>
+#include <sstream>
+#include <iomanip>
 #include <stdint.h>
 #include "frame_rate_change.h"
 
@@ -37,13 +39,15 @@ public:
                : _t (0)
        {}
 
-       explicit Time (int64_t t)
+       typedef int64_t Type;
+
+       explicit Time (Type t)
                : _t (t)
        {}
 
        virtual ~Time () {}
 
-       int64_t get () const {
+       Type get () const {
                return _t;
        }
 
@@ -56,10 +60,46 @@ 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;
        
-       int64_t _t;
+       Type _t;
        static const int HZ = 96000;
 };
 
@@ -69,8 +109,8 @@ class ContentTime : public Time
 {
 public:
        ContentTime () : Time () {}
-       explicit ContentTime (int64_t t) : Time (t) {}
-       ContentTime (int64_t n, int64_t d) : Time (n * HZ / d) {}
+       explicit ContentTime (Type t) : Time (t) {}
+       ContentTime (Type n, Type d) : Time (n * HZ / d) {}
        ContentTime (DCPTime d, FrameRateChange f);
 
        bool operator< (ContentTime const & o) const {
@@ -124,8 +164,8 @@ public:
         *  @param r Sampling rate.
         */
        ContentTime round_up (float r) {
-               int64_t const n = rint (HZ / r);
-               int64_t const a = _t + n - 1;
+               Type const n = rint (HZ / r);
+               Type const a = _t + n - 1;
                return ContentTime (a - (a % n));
        }
 
@@ -135,6 +175,7 @@ public:
 
        template <class T>
        static ContentTime from_frames (int64_t f, T r) {
+               assert (r > 0);
                return ContentTime (f * HZ / r);
        }
 
@@ -145,11 +186,31 @@ public:
 
 std::ostream& operator<< (std::ostream& s, ContentTime t);
 
+class ContentTimePeriod
+{
+public:
+       ContentTimePeriod () {}
+       ContentTimePeriod (ContentTime f, ContentTime t)
+               : from (f)
+               , to (t)
+       {}
+
+       ContentTime from;
+       ContentTime to;
+
+       ContentTimePeriod operator+ (ContentTime const & o) const {
+               return ContentTimePeriod (from + o, to + o);
+       }
+
+       bool overlaps (ContentTimePeriod const & o) const;
+       bool contains (ContentTime const & o) const;
+};
+
 class DCPTime : public Time
 {
 public:
        DCPTime () : Time () {}
-       explicit DCPTime (int64_t t) : Time (t) {}
+       explicit DCPTime (Type t) : Time (t) {}
        DCPTime (ContentTime t, FrameRateChange c) : Time (rint (t.get() / c.speed_up)) {}
 
        bool operator< (DCPTime const & o) const {
@@ -185,6 +246,10 @@ public:
                return *this;
        }
 
+       DCPTime operator- () const {
+               return DCPTime (-_t);
+       }
+
        DCPTime operator- (DCPTime const & o) const {
                return DCPTime (_t - o._t);
        }
@@ -199,8 +264,8 @@ public:
         *  @param r Sampling rate.
         */
        DCPTime round_up (float r) {
-               int64_t const n = rint (HZ / r);
-               int64_t const a = _t + n - 1;
+               Type const n = rint (HZ / r);
+               Type const a = _t + n - 1;
                return DCPTime (a - (a % n));
        }
 
@@ -214,6 +279,7 @@ public:
 
        template <class T>
        static DCPTime from_frames (int64_t f, T r) {
+               assert (r > 0);
                return DCPTime (f * HZ / r);
        }