No-op: whitespace.
[libdcp.git] / src / dcp_time.cc
1 /*
2     Copyright (C) 2012-2015 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 /** @file  src/dcp_time.cc
21  *  @brief A representation of time within a DCP.
22  */
23
24 #include <iostream>
25 #include <vector>
26 #include <boost/algorithm/string.hpp>
27 #include <cmath>
28 #include "dcp_time.h"
29 #include "exceptions.h"
30 #include "raw_convert.h"
31
32 using namespace std;
33 using namespace boost;
34 using namespace libdcp;
35
36 Time::Time (int frame, int frames_per_second, int tcr_)
37         : h (0)
38         , m (0)
39         , s (0)
40         , e (0)
41         , tcr (tcr_)
42 {
43         set (double (frame) / frames_per_second, tcr);
44 }
45
46 /** @param s_ Seconds.
47  *  @param tcr Timecode rate.
48  */
49 void
50 Time::set (double seconds, int tcr_)
51 {
52         s = floor (seconds);
53         tcr = tcr_;
54
55         e = int (round ((seconds - s) * tcr));
56
57         if (s >= 60) {
58                 m = s / 60;
59                 s -= m * 60;
60         }
61
62         if (m >= 60) {
63                 h = m / 60;
64                 m -= h * 60;
65         }
66 }
67
68 Time::Time (string time, int tcr_)
69         : tcr (tcr_)
70 {
71         vector<string> b;
72         split (b, time, is_any_of (":"));
73         if (b.size() != 4) {
74                 boost::throw_exception (DCPReadError ("unrecognised time specification"));
75         }
76
77         h = raw_convert<int> (b[0]);
78         m = raw_convert<int> (b[1]);
79         s = raw_convert<int> (b[2]);
80         e = raw_convert<int> (b[3]);
81 }
82
83 bool
84 libdcp::operator== (Time const & a, Time const & b)
85 {
86         return (a.h == b.h && a.m == b.m && a.s == b.s && (a.e * b.tcr) == (b.e * a.tcr));
87 }
88
89 bool
90 libdcp::operator!= (Time const & a, Time const & b)
91 {
92         return !(a == b);
93 }
94
95 bool
96 libdcp::operator<= (Time const & a, Time const & b)
97 {
98         return a < b || a == b;
99 }
100
101 bool
102 libdcp::operator< (Time const & a, Time const & b)
103 {
104         if (a.h != b.h) {
105                 return a.h < b.h;
106         }
107
108         if (a.m != b.m) {
109                 return a.m < b.m;
110         }
111
112         if (a.s != b.s) {
113                 return a.s < b.s;
114         }
115
116         if ((a.e * b.tcr) != (b.e * a.tcr)) {
117                 return (a.e * b.tcr) < (b.e * a.tcr);
118         }
119
120         return true;
121 }
122
123 bool
124 libdcp::operator> (Time const & a, Time const & b)
125 {
126         if (a.h != b.h) {
127                 return a.h > b.h;
128         }
129
130         if (a.m != b.m) {
131                 return a.m > b.m;
132         }
133
134         if (a.s != b.s) {
135                 return a.s > b.s;
136         }
137
138         if ((a.e * b.tcr) != (b.e * a.tcr)) {
139                 return (a.e * b.tcr) > (b.e * a.tcr);
140         }
141
142         return true;
143 }
144
145 bool
146 libdcp::operator>= (Time const & a, Time const & b)
147 {
148         return a == b || a > b;
149 }
150
151 libdcp::Time
152 libdcp::operator+ (Time a, Time b)
153 {
154         Time r;
155
156         /* Make sure we have a common tcr */
157         if (a.tcr != b.tcr) {
158                 a.e *= b.tcr;
159                 b.e *= a.tcr;
160                 r.tcr = a.tcr * b.tcr;
161         } else {
162                 r.tcr = a.tcr;
163         }
164
165         r.e = a.e + b.e;
166         if (r.e >= r.tcr) {
167                 r.e -= r.tcr;
168                 r.s++;
169         }
170
171         r.s += a.s + b.s;
172         if (r.s >= 60) {
173                 r.s -= 60;
174                 r.m++;
175         }
176
177         r.m += a.m + b.m;
178         if (r.m >= 60) {
179                 r.m -= 60;
180                 r.h++;
181         }
182
183         r.h += a.h + b.h;
184
185         return r;
186 }
187
188 libdcp::Time
189 libdcp::operator- (Time a, Time b)
190 {
191         Time r;
192
193         /* Make sure we have a common tcr */
194         if (a.tcr != b.tcr) {
195                 a.e *= b.tcr;
196                 b.e *= a.tcr;
197                 r.tcr = a.tcr * b.tcr;
198         } else {
199                 r.tcr = a.tcr;
200         }
201
202         r.e = a.e - b.e;
203         if (r.e < 0) {
204                 r.e += a.tcr;
205                 r.s--;
206         }
207
208         r.s += (a.s - b.s);
209         if (r.s < 0) {
210                 r.s += 60;
211                 r.m--;
212         }
213
214         r.m += (a.m - b.m);
215         if (r.m < 0) {
216                 r.m += 60;
217                 r.h--;
218         }
219
220         r.h += (a.h - b.h);
221
222         return r;
223 }
224
225 float
226 libdcp::operator/ (Time a, Time const & b)
227 {
228         float const as = a.h * 3600 + a.m * 60 + a.s * float (a.e) / a.tcr;
229         float const bs = b.h * 3600 + b.m * 60 + b.s * float (b.e) / b.tcr;
230         return as / bs;
231 }
232
233 /** @return A string of the form h:m:s:e */
234 string
235 Time::to_string () const
236 {
237         stringstream str;
238         str << h << ":" << m << ":" << s << ":" << e;
239         return str.str ();
240 }
241
242 int64_t
243 Time::to_editable_units (int tcr_) const
244 {
245         return (int64_t(e) * float (tcr_ / tcr)) + int64_t(s) * tcr_ + int64_t(m) * 60 * tcr_ + int64_t(h) * 60 * 60 * tcr_;
246 }
247
248 ostream &
249 libdcp::operator<< (ostream& s, Time const & t)
250 {
251         s << t.to_string ();
252         return s;
253 }
254