Add Time::all_as_seconds().
[libsub.git] / src / sub_time.cc
1 /*
2     Copyright (C) 2014-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 #include "sub_time.h"
21 #include "exceptions.h"
22 #include <cmath>
23 #include <iomanip>
24
25 using std::ostream;
26 using std::cout;
27 using std::setw;
28 using std::setfill;
29 using boost::optional;
30 using namespace sub;
31
32 bool
33 sub::operator< (sub::Time const & a, sub::Time const & b)
34 {
35         if (a._seconds != b._seconds) {
36                 return a._seconds < b._seconds;
37         }
38
39         if (!a._rate && !b._rate) {
40                 /* Can compare if neither has a specified frame rate */
41                 return a._frames < b._frames;
42         }
43
44         if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
45                 throw UnknownFrameRateError ();
46         }
47         
48         return (a._frames * a._rate.get().numerator * b._rate.get().denominator) < (b._frames * b._rate.get().numerator * a._rate.get().denominator);
49 }
50
51 bool
52 sub::operator> (sub::Time const & a, sub::Time const & b)
53 {
54         if (a._seconds != b._seconds) {
55                 return a._seconds > b._seconds;
56         }
57
58         if (!a._rate && !b._rate) {
59                 /* Can compare if neither has a specified frame rate */
60                 return a._frames > b._frames;
61         }
62
63         if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
64                 throw UnknownFrameRateError ();
65         }
66         
67         return (a._frames * a._rate.get().numerator * b._rate.get().denominator) > (b._frames * b._rate.get().numerator * a._rate.get().denominator);
68 }
69
70 bool
71 sub::operator== (sub::Time const & a, sub::Time const & b)
72 {
73         if (!a._rate && !b._rate) {
74                 /* Can compare if neither has a specified frame rate */
75                 return (a._seconds == b._seconds && a._frames == b._frames);
76         }
77
78         if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
79                 throw UnknownFrameRateError ();
80         }
81
82         if (a._seconds != b._seconds) {
83                 return false;
84         }
85
86         return (a._frames * a._rate.get().numerator * b._rate.get().denominator) == (b._frames * b._rate.get().numerator * a._rate.get().denominator);
87 }
88
89 bool
90 sub::operator!= (sub::Time const & a, sub::Time const & b)
91 {
92         return !(a == b);
93 }
94
95 ostream&
96 sub::operator<< (ostream& s, Time const & t)
97 {
98         s << setw (2) << setfill('0') << t.hours() << ":"
99           << setw (2) << setfill('0') << t.minutes() << ":"
100           << setw (2) << setfill('0') << t.seconds() << ":"
101           << t._frames;
102
103         if (t._rate) {
104                 s << " @ " << t._rate.get().numerator << "/" << t._rate.get().denominator;
105         }
106
107         return s;
108 }
109
110 int
111 Time::hours () const
112 {
113         return _seconds / 3600;
114 }
115
116 int
117 Time::minutes () const
118 {
119         return (_seconds - hours() * 3600) / 60;
120 }
121
122 int
123 Time::seconds () const
124 {
125         return (_seconds - hours() * 3600 - minutes() * 60);
126 }
127
128 int
129 Time::frames_at (Rational rate) const
130 {
131         if (!_rate) {
132                 throw UnknownFrameRateError ();
133         }
134         
135         return rint (double (_frames) * _rate.get().denominator * rate.numerator / (_rate.get().numerator * rate.denominator));
136 }
137
138 int
139 Time::milliseconds () const
140 {
141         return frames_at (Rational (1000, 1));
142 }
143
144 Time
145 Time::from_hmsf (int h, int m, int s, int f, optional<Rational> rate)
146 {
147         return Time (h * 3600 + m * 60 + s, f, rate);
148 }
149
150 Time
151 Time::from_hms (int h, int m, int s, int ms)
152 {
153         return Time (h * 3600 + m * 60 + s, ms, Rational (1000, 1));
154 }
155
156 double
157 Time::all_as_seconds () const
158 {
159         if (!_rate) {
160                 throw UnknownFrameRateError ();
161         }
162         
163         return _seconds + double (_frames) / _rate.get().fraction ();
164 }