summaryrefslogtreecommitdiff
path: root/src/sub_time.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-01-14 17:39:32 +0000
committerCarl Hetherington <cth@carlh.net>2015-01-20 11:20:25 +0000
commit3f630fb8334238ab8a58fbe1a0f513ae2c00de80 (patch)
tree4b773b91029d6374bfd4f2194053d3e249d597cd /src/sub_time.cc
parent49cafda01b3e07c47e3b20dd5ee91e1426446aea (diff)
Simplify time representation; better in-tree DCP subtitle parser.
Diffstat (limited to 'src/sub_time.cc')
-rw-r--r--src/sub_time.cc154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/sub_time.cc b/src/sub_time.cc
new file mode 100644
index 0000000..e304310
--- /dev/null
+++ b/src/sub_time.cc
@@ -0,0 +1,154 @@
+/*
+ Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "sub_time.h"
+#include "exceptions.h"
+#include <cmath>
+#include <iomanip>
+
+using std::ostream;
+using std::cout;
+using std::setw;
+using std::setfill;
+using boost::optional;
+using namespace sub;
+
+bool
+sub::operator< (sub::Time const & a, sub::Time const & b)
+{
+ if (a._seconds != b._seconds) {
+ return a._seconds < b._seconds;
+ }
+
+ if (!a._rate && !b._rate) {
+ /* Can compare if neither has a specified frame rate */
+ return a._frames < b._frames;
+ }
+
+ if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
+ throw UnknownFrameRateError ();
+ }
+
+ return (a._frames * a._rate.get().numerator * b._rate.get().denominator) < (b._frames * b._rate.get().numerator * a._rate.get().denominator);
+}
+
+bool
+sub::operator> (sub::Time const & a, sub::Time const & b)
+{
+ if (a._seconds != b._seconds) {
+ return a._seconds > b._seconds;
+ }
+
+ if (!a._rate && !b._rate) {
+ /* Can compare if neither has a specified frame rate */
+ return a._frames > b._frames;
+ }
+
+ if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
+ throw UnknownFrameRateError ();
+ }
+
+ return (a._frames * a._rate.get().numerator * b._rate.get().denominator) > (b._frames * b._rate.get().numerator * a._rate.get().denominator);
+}
+
+bool
+sub::operator== (sub::Time const & a, sub::Time const & b)
+{
+ if (!a._rate && !b._rate) {
+ /* Can compare if neither has a specified frame rate */
+ return (a._seconds == b._seconds && a._frames == b._frames);
+ }
+
+ if ((a._rate && !b._rate) || (!a._rate && b._rate)) {
+ throw UnknownFrameRateError ();
+ }
+
+ if (a._seconds != b._seconds) {
+ return false;
+ }
+
+ return (a._frames * a._rate.get().numerator * b._rate.get().denominator) == (b._frames * b._rate.get().numerator * a._rate.get().denominator);
+}
+
+bool
+sub::operator!= (sub::Time const & a, sub::Time const & b)
+{
+ return !(a == b);
+}
+
+ostream&
+sub::operator<< (ostream& s, Time const & t)
+{
+ s << setw (2) << setfill('0') << t.hours() << ":"
+ << setw (2) << setfill('0') << t.minutes() << ":"
+ << setw (2) << setfill('0') << t.seconds() << ":"
+ << t._frames;
+
+ if (t._rate) {
+ s << " @ " << t._rate.get().numerator << "/" << t._rate.get().denominator;
+ }
+
+ return s;
+}
+
+int
+Time::hours () const
+{
+ return _seconds / 3600;
+}
+
+int
+Time::minutes () const
+{
+ return (_seconds - hours() * 3600) / 60;
+}
+
+int
+Time::seconds () const
+{
+ return (_seconds - hours() * 3600 - minutes() * 60);
+}
+
+int
+Time::frames_at (Rational rate) const
+{
+ if (!_rate) {
+ throw UnknownFrameRateError ();
+ }
+
+ return rint (double (_frames) * _rate.get().denominator * rate.numerator / (_rate.get().numerator * rate.denominator));
+}
+
+int
+Time::milliseconds () const
+{
+ return frames_at (Rational (1000, 1));
+}
+
+Time
+Time::from_hmsf (int h, int m, int s, int f, optional<Rational> rate)
+{
+ return Time (h * 3600 + m * 60 + s, f, rate);
+}
+
+Time
+Time::from_hms (int h, int m, int s, int ms)
+{
+ return Time (h * 3600 + m * 60 + s, ms, Rational (1000, 1));
+}