+ throw XMLError ("unexpected node " + node->get_name());
+ }
+
+ xmlpp::Node::NodeList c = node->get_children ();
+ for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
+ xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i);
+ if (v) {
+ maybe_add_subtitle (v->get_content(), state, standard);
+ }
+ xmlpp::Element const * e = dynamic_cast<xmlpp::Element const *> (*i);
+ if (e) {
+ parse_subtitles (e, state, tcr, standard);
+ }
+ }
+
+ state.pop_back ();
+}
+
+void
+SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, Standard standard)
+{
+ if (empty_or_white_space (text)) {
+ return;
+ }
+
+ ParseState ps;
+ BOOST_FOREACH (ParseState const & i, parse_state) {
+ if (i.font_id) {
+ ps.font_id = i.font_id.get();
+ }
+ if (i.size) {
+ ps.size = i.size.get();
+ }
+ if (i.aspect_adjust) {
+ ps.aspect_adjust = i.aspect_adjust.get();
+ }
+ if (i.italic) {
+ ps.italic = i.italic.get();
+ }
+ if (i.bold) {
+ ps.bold = i.bold.get();
+ }
+ if (i.underline) {
+ ps.underline = i.underline.get();
+ }
+ if (i.colour) {
+ ps.colour = i.colour.get();
+ }
+ if (i.effect) {
+ ps.effect = i.effect.get();
+ }
+ if (i.effect_colour) {
+ ps.effect_colour = i.effect_colour.get();
+ }
+ if (i.h_position) {
+ ps.h_position = i.h_position.get();
+ }
+ if (i.h_align) {
+ ps.h_align = i.h_align.get();
+ }
+ if (i.v_position) {
+ ps.v_position = i.v_position.get();
+ }
+ if (i.v_align) {
+ ps.v_align = i.v_align.get();
+ }
+ if (i.direction) {
+ ps.direction = i.direction.get();
+ }
+ if (i.in) {
+ ps.in = i.in.get();
+ }
+ if (i.out) {
+ ps.out = i.out.get();
+ }
+ if (i.fade_up_time) {
+ ps.fade_up_time = i.fade_up_time.get();
+ }
+ if (i.fade_down_time) {
+ ps.fade_down_time = i.fade_down_time.get();
+ }
+ if (i.type) {
+ ps.type = i.type.get();
+ }
+ }
+
+ if (!ps.in || !ps.out) {
+ /* We're not in a <Subtitle> node; just ignore this content */
+ return;
+ }
+
+ DCP_ASSERT (ps.type);
+
+ switch (ps.type.get()) {
+ case ParseState::TEXT:
+ _subtitles.push_back (
+ shared_ptr<Subtitle> (
+ new SubtitleString (
+ ps.font_id,
+ ps.italic.get_value_or (false),
+ ps.bold.get_value_or (false),
+ ps.underline.get_value_or (false),
+ ps.colour.get_value_or (dcp::Colour (255, 255, 255)),
+ ps.size.get_value_or (42),
+ ps.aspect_adjust.get_value_or (1.0),
+ ps.in.get(),
+ ps.out.get(),
+ ps.h_position.get_value_or(0),
+ ps.h_align.get_value_or(HALIGN_CENTER),
+ ps.v_position.get_value_or(0),
+ ps.v_align.get_value_or(VALIGN_CENTER),
+ ps.direction.get_value_or (DIRECTION_LTR),
+ text,
+ ps.effect.get_value_or (NONE),
+ ps.effect_colour.get_value_or (dcp::Colour (0, 0, 0)),
+ ps.fade_up_time.get_value_or(Time()),
+ ps.fade_down_time.get_value_or(Time())
+ )
+ )
+ );
+ break;
+ case ParseState::IMAGE:
+ /* Add a subtitle with no image data and we'll fill that in later */
+ _subtitles.push_back (
+ shared_ptr<Subtitle> (
+ new SubtitleImage (
+ ArrayData (),
+ standard == INTEROP ? text.substr(0, text.size() - 4) : text,
+ ps.in.get(),
+ ps.out.get(),
+ ps.h_position.get_value_or(0),
+ ps.h_align.get_value_or(HALIGN_CENTER),
+ ps.v_position.get_value_or(0),
+ ps.v_align.get_value_or(VALIGN_CENTER),
+ ps.fade_up_time.get_value_or(Time()),
+ ps.fade_down_time.get_value_or(Time())
+ )
+ )
+ );
+ break;
+ }
+}
+
+vector<shared_ptr<Subtitle>>
+SubtitleAsset::subtitles_during (Time from, Time to, bool starting) const
+{
+ vector<shared_ptr<Subtitle> > s;
+ BOOST_FOREACH (shared_ptr<Subtitle> i, _subtitles) {
+ if ((starting && from <= i->in() && i->in() < to) || (!starting && i->out() >= from && i->in() <= to)) {
+ s.push_back (i);
+ }