summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-06-14 00:20:06 +0100
committerCarl Hetherington <cth@carlh.net>2016-06-14 00:20:06 +0100
commit8837fe70049bd5ed7ab583c06d6c9a620a01b351 (patch)
tree798e86e707bfecc147a54d999fe826f4bc5dd3a8 /src
parent937e4352072486832372fc8ebdb83583be9b8a2a (diff)
Tighten up time parsing, and also allow the previously
unsupported Interop HH:MM:SS.sss format for times.
Diffstat (limited to 'src')
-rw-r--r--src/dcp_time.cc82
-rw-r--r--src/dcp_time.h3
-rw-r--r--src/font_node.cc4
-rw-r--r--src/font_node.h4
-rw-r--r--src/interop_subtitle_asset.cc4
-rw-r--r--src/subtitle_node.cc9
-rw-r--r--src/subtitle_node.h6
-rw-r--r--src/text_node.cc4
-rw-r--r--src/text_node.h4
9 files changed, 92 insertions, 28 deletions
diff --git a/src/dcp_time.cc b/src/dcp_time.cc
index 7425df2c..401abb3c 100644
--- a/src/dcp_time.cc
+++ b/src/dcp_time.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -38,7 +38,9 @@
#include "raw_convert.h"
#include "dcp_time.h"
#include "exceptions.h"
+#include "compose.hpp"
#include <boost/algorithm/string.hpp>
+#include <boost/optional.hpp>
#include <iostream>
#include <vector>
#include <cmath>
@@ -91,20 +93,80 @@ Time::set (double seconds, int tcr_)
}
}
-/** @param time String of the form HH:MM:SS:EE[E] */
-Time::Time (string time, int tcr_)
- : tcr (tcr_)
+/** @param time String of the form
+ * HH:MM:SS:EE for SMPTE
+ * HH:MM:SS:E[E[E]] or HH:MM:SS.s[s[s]] for Interop
+ * where HH are hours, MM minutes, SS seconds, EE editable units and
+ * sss millseconds.
+ *
+ * @param tcr_ Timecode rate if this is a SMPTE time, otherwise empty for an Interop time.
+ */
+Time::Time (string time, optional<int> tcr_)
{
vector<string> b;
split (b, time, is_any_of (":"));
- if (b.size() != 4) {
- boost::throw_exception (DCPReadError ("unrecognised time specification"));
+
+ if (b.size() < 3 || b[0].empty() || b[1].empty() || b[0].length() > 2 || b[1].length() > 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1", time)));
}
- h = raw_convert<int> (b[0]);
- m = raw_convert<int> (b[1]);
- s = raw_convert<int> (b[2]);
- e = raw_convert<int> (b[3]);
+ if (!tcr_) {
+ /* Interop */
+ if (b.size() == 3) {
+ /* HH:MM:SS.s[s[s]] */
+ vector<string> bs;
+ split (bs, b[2], is_any_of ("."));
+ if (bs.size() != 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1", time)));
+ }
+
+ h = raw_convert<int> (b[0]);
+ m = raw_convert<int> (b[1]);
+ if (bs[0].empty() || bs[0].length() > 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, bs[0])));
+ }
+ s = raw_convert<int> (bs[0]);
+ if (bs[1].empty() || bs[1].length() > 3) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, bs[1])));
+ }
+ e = raw_convert<int> (bs[1]);
+ tcr = 1000;
+ } else if (b.size() == 4) {
+ /* HH:MM:SS:EE[E] */
+ h = raw_convert<int> (b[0]);
+ m = raw_convert<int> (b[1]);
+ if (b[2].empty() || b[2].length() > 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[2])));
+ }
+ s = raw_convert<int> (b[2]);
+ if (b[3].empty() || b[3].length() > 3) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[3])));
+ }
+ e = raw_convert<int> (b[3]);
+ tcr = 250;
+ } else {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1", time)));
+ }
+
+ } else {
+ /* SMPTE: HH:MM:SS:EE */
+ split (b, time, is_any_of (":"));
+ if (b.size() != 4) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; does not have 4 parts", time)));
+ }
+
+ h = raw_convert<int> (b[0]);
+ m = raw_convert<int> (b[1]);
+ if (b[2].empty() || b[2].length() > 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[2])));
+ }
+ s = raw_convert<int> (b[2]);
+ if (b[3].empty() || b[3].length() > 2) {
+ boost::throw_exception (DCPReadError (String::compose ("unrecognised time specification %1; %2 has bad length", time, b[3])));
+ }
+ e = raw_convert<int> (b[3]);
+ tcr = tcr_.get();
+ }
}
bool
diff --git a/src/dcp_time.h b/src/dcp_time.h
index e8724614..2a9f13d8 100644
--- a/src/dcp_time.h
+++ b/src/dcp_time.h
@@ -39,6 +39,7 @@
#define LIBDCP_TIME_H
#include "types.h"
+#include <boost/optional.hpp>
#include <stdint.h>
#include <string>
#include <iostream>
@@ -78,7 +79,7 @@ public:
Time (double seconds, int tcr);
- Time (std::string time, int tcr);
+ Time (std::string time, boost::optional<int> tcr);
int h; ///< hours
int m; ///< minutes
diff --git a/src/font_node.cc b/src/font_node.cc
index 77d58aaf..6dd6e58f 100644
--- a/src/font_node.cc
+++ b/src/font_node.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -45,7 +45,7 @@ using boost::shared_ptr;
using boost::optional;
using namespace dcp;
-FontNode::FontNode (cxml::ConstNodePtr node, int tcr, string font_id_attribute)
+FontNode::FontNode (cxml::ConstNodePtr node, optional<int> tcr, string font_id_attribute)
{
text = node->content ();
diff --git a/src/font_node.h b/src/font_node.h
index 72c1553e..8f7cc2aa 100644
--- a/src/font_node.h
+++ b/src/font_node.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -54,7 +54,7 @@ public:
: size (0)
{}
- FontNode (cxml::ConstNodePtr node, int tcr, std::string font_id_attribute);
+ FontNode (cxml::ConstNodePtr node, boost::optional<int> tcr, std::string font_id_attribute);
explicit FontNode (std::list<boost::shared_ptr<FontNode> > const & font_nodes);
std::string text;
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index 33d76e89..b32ac790 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -68,12 +68,12 @@ InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file)
list<shared_ptr<dcp::FontNode> > font_nodes;
BOOST_FOREACH (cxml::NodePtr const & i, xml->node_children ("Font")) {
- font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, 250, "Id")));
+ font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, optional<int>(), "Id")));
}
list<shared_ptr<dcp::SubtitleNode> > subtitle_nodes;
BOOST_FOREACH (cxml::NodePtr const & i, xml->node_children ("Subtitle")) {
- subtitle_nodes.push_back (shared_ptr<SubtitleNode> (new SubtitleNode (i, 250, "Id")));
+ subtitle_nodes.push_back (shared_ptr<SubtitleNode> (new SubtitleNode (i, optional<int>(), "Id")));
}
parse_subtitles (xml, font_nodes, subtitle_nodes);
diff --git a/src/subtitle_node.cc b/src/subtitle_node.cc
index bd689aa2..44c32e26 100644
--- a/src/subtitle_node.cc
+++ b/src/subtitle_node.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -45,7 +45,8 @@ using boost::shared_ptr;
using boost::lexical_cast;
using namespace dcp;
-SubtitleNode::SubtitleNode (boost::shared_ptr<const cxml::Node> node, int tcr, string font_id_attribute)
+/** @param tcr Timecode rate for SMPTE, or empty for Interop */
+SubtitleNode::SubtitleNode (boost::shared_ptr<const cxml::Node> node, optional<int> tcr, string font_id_attribute)
{
in = Time (node->string_attribute ("TimeIn"), tcr);
out = Time (node->string_attribute ("TimeOut"), tcr);
@@ -65,7 +66,7 @@ SubtitleNode::SubtitleNode (boost::shared_ptr<const cxml::Node> node, int tcr, s
}
Time
-SubtitleNode::fade_time (shared_ptr<const cxml::Node> node, string name, int tcr)
+SubtitleNode::fade_time (shared_ptr<const cxml::Node> node, string name, optional<int> tcr)
{
string const u = node->optional_string_attribute (name).get_value_or ("");
Time t;
@@ -75,7 +76,7 @@ SubtitleNode::fade_time (shared_ptr<const cxml::Node> node, string name, int tcr
} else if (u.find (":") != string::npos) {
t = Time (u, tcr);
} else {
- t = Time (0, 0, 0, lexical_cast<int> (u), tcr);
+ t = Time (0, 0, 0, lexical_cast<int> (u), tcr.get_value_or(250));
}
if (t > Time (0, 0, 8, 0, 250)) {
diff --git a/src/subtitle_node.h b/src/subtitle_node.h
index 28e410e3..37d41f01 100644
--- a/src/subtitle_node.h
+++ b/src/subtitle_node.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -52,7 +52,7 @@ class SubtitleNode
{
public:
SubtitleNode () {}
- SubtitleNode (boost::shared_ptr<const cxml::Node> node, int tcr, std::string font_id_attribute);
+ SubtitleNode (boost::shared_ptr<const cxml::Node> node, boost::optional<int> tcr, std::string font_id_attribute);
Time in;
Time out;
@@ -62,7 +62,7 @@ public:
std::list<boost::shared_ptr<TextNode> > text_nodes;
private:
- Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name, int tcr);
+ Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name, boost::optional<int> tcr);
};
}
diff --git a/src/text_node.cc b/src/text_node.cc
index 03777c75..cfd0557f 100644
--- a/src/text_node.cc
+++ b/src/text_node.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -51,7 +51,7 @@ using namespace dcp;
* in this object's member variables.
* @param node Node to read.
*/
-TextNode::TextNode (boost::shared_ptr<const cxml::Node> node, int tcr, string font_id_attribute)
+TextNode::TextNode (boost::shared_ptr<const cxml::Node> node, optional<int> tcr, string font_id_attribute)
: h_position (0)
, h_align (HALIGN_CENTER)
, v_position (0)
diff --git a/src/text_node.h b/src/text_node.h
index 8624a178..313bdbcb 100644
--- a/src/text_node.h
+++ b/src/text_node.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
@@ -63,7 +63,7 @@ public:
, direction (DIRECTION_LTR)
{}
- TextNode (boost::shared_ptr<const cxml::Node> node, int tcr, std::string font_id_attribute);
+ TextNode (boost::shared_ptr<const cxml::Node> node, boost::optional<int> tcr, std::string font_id_attribute);
float h_position;
HAlign h_align;