Some include tidying.
[dcpomatic.git] / src / lib / dcpomatic_time.h
1 /*
2     Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef DCPOMATIC_TIME_H
21 #define DCPOMATIC_TIME_H
22
23 #include "frame_rate_change.h"
24 #include "safe_stringstream.h"
25 #include <stdint.h>
26 #include <cmath>
27 #include <ostream>
28 #include <sstream>
29 #include <iomanip>
30
31 class dcpomatic_round_up_test;
32
33 class Time;
34
35 /** A time in seconds, expressed as a number scaled up by Time::HZ. */
36 class Time
37 {
38 public:
39         Time ()
40                 : _t (0)
41         {}
42
43         typedef int64_t Type;
44
45         explicit Time (Type t)
46                 : _t (t)
47         {}
48
49         virtual ~Time () {}
50
51         Type get () const {
52                 return _t;
53         }
54
55         double seconds () const {
56                 return double (_t) / HZ;
57         }
58
59         template <typename T>
60         int64_t frames (T r) const {
61                 return rint (_t * r / HZ);
62         }
63
64         /** @param r Frames per second */
65         template <typename T>
66         void split (T r, int& h, int& m, int& s, int& f) const
67         {
68                 /* Do this calculation with frames so that we can round
69                    to a frame boundary at the start rather than the end.
70                 */
71                 int64_t ff = frames (r);
72                 
73                 h = ff / (3600 * r);
74                 ff -= h * 3600 * r;
75                 m = ff / (60 * r);
76                 ff -= m * 60 * r;
77                 s = ff / r;
78                 ff -= s * r;
79
80                 f = static_cast<int> (ff);
81         }
82
83         template <typename T>
84         std::string timecode (T r) const {
85                 int h;
86                 int m;
87                 int s;
88                 int f;
89                 split (r, h, m, s, f);
90
91                 SafeStringStream o;
92                 o.width (2);
93                 o.fill ('0');
94                 o << std::setw(2) << std::setfill('0') << h << ":"
95                   << std::setw(2) << std::setfill('0') << m << ":"
96                   << std::setw(2) << std::setfill('0') << s << ":"
97                   << std::setw(2) << std::setfill('0') << f;
98                 return o.str ();
99         }
100
101 protected:
102         friend struct dcptime_round_up_test;
103         
104         Type _t;
105         static const int HZ = 96000;
106 };
107
108 class DCPTime;
109
110 class ContentTime : public Time
111 {
112 public:
113         ContentTime () : Time () {}
114         explicit ContentTime (Type t) : Time (t) {}
115         ContentTime (Type n, Type d) : Time (n * HZ / d) {}
116         ContentTime (DCPTime d, FrameRateChange f);
117
118         bool operator< (ContentTime const & o) const {
119                 return _t < o._t;
120         }
121
122         bool operator<= (ContentTime const & o) const {
123                 return _t <= o._t;
124         }
125
126         bool operator== (ContentTime const & o) const {
127                 return _t == o._t;
128         }
129
130         bool operator!= (ContentTime const & o) const {
131                 return _t != o._t;
132         }
133
134         bool operator>= (ContentTime const & o) const {
135                 return _t >= o._t;
136         }
137
138         bool operator> (ContentTime const & o) const {
139                 return _t > o._t;
140         }
141
142         ContentTime operator+ (ContentTime const & o) const {
143                 return ContentTime (_t + o._t);
144         }
145
146         ContentTime & operator+= (ContentTime const & o) {
147                 _t += o._t;
148                 return *this;
149         }
150
151         ContentTime operator- () const {
152                 return ContentTime (-_t);
153         }
154
155         ContentTime operator- (ContentTime const & o) const {
156                 return ContentTime (_t - o._t);
157         }
158
159         ContentTime & operator-= (ContentTime const & o) {
160                 _t -= o._t;
161                 return *this;
162         }
163
164         /** Round up to the nearest sampling interval
165          *  at some sampling rate.
166          *  @param r Sampling rate.
167          */
168         ContentTime round_up (float r) {
169                 Type const n = rint (HZ / r);
170                 Type const a = _t + n - 1;
171                 return ContentTime (a - (a % n));
172         }
173
174         static ContentTime from_seconds (double s) {
175                 return ContentTime (s * HZ);
176         }
177
178         template <class T>
179         static ContentTime from_frames (int64_t f, T r) {
180                 assert (r > 0);
181                 return ContentTime (f * HZ / r);
182         }
183
184         static ContentTime max () {
185                 return ContentTime (INT64_MAX);
186         }
187 };
188
189 std::ostream& operator<< (std::ostream& s, ContentTime t);
190
191 class ContentTimePeriod
192 {
193 public:
194         ContentTimePeriod () {}
195         ContentTimePeriod (ContentTime f, ContentTime t)
196                 : from (f)
197                 , to (t)
198         {}
199
200         ContentTime from;
201         ContentTime to;
202
203         ContentTimePeriod operator+ (ContentTime const & o) const {
204                 return ContentTimePeriod (from + o, to + o);
205         }
206
207         bool overlaps (ContentTimePeriod const & o) const;
208         bool contains (ContentTime const & o) const;
209 };
210
211 class DCPTime : public Time
212 {
213 public:
214         DCPTime () : Time () {}
215         explicit DCPTime (Type t) : Time (t) {}
216         DCPTime (ContentTime t, FrameRateChange c) : Time (rint (t.get() / c.speed_up)) {}
217
218         bool operator< (DCPTime const & o) const {
219                 return _t < o._t;
220         }
221
222         bool operator<= (DCPTime const & o) const {
223                 return _t <= o._t;
224         }
225
226         bool operator== (DCPTime const & o) const {
227                 return _t == o._t;
228         }
229
230         bool operator!= (DCPTime const & o) const {
231                 return _t != o._t;
232         }
233
234         bool operator>= (DCPTime const & o) const {
235                 return _t >= o._t;
236         }
237
238         bool operator> (DCPTime const & o) const {
239                 return _t > o._t;
240         }
241
242         DCPTime operator+ (DCPTime const & o) const {
243                 return DCPTime (_t + o._t);
244         }
245
246         DCPTime & operator+= (DCPTime const & o) {
247                 _t += o._t;
248                 return *this;
249         }
250
251         DCPTime operator- () const {
252                 return DCPTime (-_t);
253         }
254
255         DCPTime operator- (DCPTime const & o) const {
256                 return DCPTime (_t - o._t);
257         }
258
259         DCPTime & operator-= (DCPTime const & o) {
260                 _t -= o._t;
261                 return *this;
262         }
263
264         /** Round up to the nearest sampling interval
265          *  at some sampling rate.
266          *  @param r Sampling rate.
267          */
268         DCPTime round_up (float r) {
269                 Type const n = rint (HZ / r);
270                 Type const a = _t + n - 1;
271                 return DCPTime (a - (a % n));
272         }
273
274         DCPTime abs () const {
275                 return DCPTime (std::abs (_t));
276         }
277
278         static DCPTime from_seconds (double s) {
279                 return DCPTime (s * HZ);
280         }
281
282         template <class T>
283         static DCPTime from_frames (int64_t f, T r) {
284                 assert (r > 0);
285                 return DCPTime (f * HZ / r);
286         }
287
288         static DCPTime delta () {
289                 return DCPTime (1);
290         }
291
292         static DCPTime max () {
293                 return DCPTime (INT64_MAX);
294         }
295 };
296
297 DCPTime min (DCPTime a, DCPTime b);
298 std::ostream& operator<< (std::ostream& s, DCPTime t);
299
300 #endif