2 Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
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.
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.
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.
21 #include "sub_assert.h"
22 #include "exceptions.h"
31 using boost::optional;
35 sub::operator< (sub::Time const & a, sub::Time const & b)
37 if (a._seconds != b._seconds) {
38 return a._seconds < b._seconds;
41 if (!a._rate && !b._rate) {
42 /* Can compare if neither has a specified frame rate */
43 return a._frames < b._frames;
46 if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
47 throw UnknownFrameRateError ();
50 return (a._frames * a._rate.get().numerator * b._rate.get().denominator) < (b._frames * b._rate.get().numerator * a._rate.get().denominator);
54 sub::operator> (sub::Time const & a, sub::Time const & b)
56 if (a._seconds != b._seconds) {
57 return a._seconds > b._seconds;
60 if (!a._rate && !b._rate) {
61 /* Can compare if neither has a specified frame rate */
62 return a._frames > b._frames;
65 if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
66 throw UnknownFrameRateError ();
69 return (a._frames * a._rate.get().numerator * b._rate.get().denominator) > (b._frames * b._rate.get().numerator * a._rate.get().denominator);
73 sub::operator== (sub::Time const & a, sub::Time const & b)
75 if (!a._rate && !b._rate) {
76 /* Can compare if neither has a specified frame rate */
77 return (a._seconds == b._seconds && a._frames == b._frames);
80 if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
81 throw UnknownFrameRateError ();
84 if (a._seconds != b._seconds) {
88 return (a._frames * a._rate.get().numerator * b._rate.get().denominator) == (b._frames * b._rate.get().numerator * a._rate.get().denominator);
92 sub::operator!= (sub::Time const & a, sub::Time const & b)
98 sub::operator<< (ostream& s, Time const & t)
100 s << setw (2) << setfill('0') << t.hours() << ":"
101 << setw (2) << setfill('0') << t.minutes() << ":"
102 << setw (2) << setfill('0') << t.seconds() << ":"
106 s << " @ " << t._rate.get().numerator << "/" << t._rate.get().denominator;
115 return _seconds / 3600;
119 Time::minutes () const
121 return (_seconds - hours() * 3600) / 60;
125 Time::seconds () const
127 return (_seconds - hours() * 3600 - minutes() * 60);
131 Time::frames_at (Rational rate) const
134 throw UnknownFrameRateError ();
137 return rint (double (_frames) * _rate.get().denominator * rate.numerator / (_rate.get().numerator * rate.denominator));
141 Time::milliseconds () const
143 return frames_at (Rational (1000, 1));
147 Time::from_hmsf (int h, int m, int s, int f, optional<Rational> rate)
149 return Time (h * 3600 + m * 60 + s, f, rate);
153 Time::from_hms (int h, int m, int s, int ms)
155 return Time (h * 3600 + m * 60 + s, ms, Rational (1000, 1));
158 /** Create a Time from a number of frames.
159 * rate must be integer.
162 Time::from_frames (int f, Rational rate)
164 SUB_ASSERT (rate.denominator != 0);
165 SUB_ASSERT (rate.integer ());
166 return Time (f / rate.integer_fraction(), f % rate.integer_fraction(), rate);
170 Time::all_as_seconds () const
172 return _seconds + double(milliseconds()) / 1000;
175 /** Add a time to this one. Both *this and t must have a specified _rate */
180 SUB_ASSERT (t._rate);
182 Rational result_rate = max (*_rate, *t._rate);
183 *this = Time::from_frames((all_as_seconds() + t.all_as_seconds()) * result_rate.fraction(), result_rate);
187 Time::scale (float f)
190 SUB_ASSERT (_rate->denominator != 0);
191 SUB_ASSERT (_rate->integer ());
193 double const s = Time::all_as_seconds() * f;
194 _seconds = floor (s);
195 _frames = rint ((s - _seconds) * _rate->fraction());