#include "dcp.h"
#include "sound_mxf.h"
#include "picture_mxf.h"
-#include "subtitle_content.h"
+#include "interop_subtitle_content.h"
+#include "smpte_subtitle_content.h"
#include "mono_picture_mxf.h"
#include "stereo_picture_mxf.h"
#include "util.h"
if (root == "CompositionPlaylist") {
_assets.push_back (shared_ptr<CPL> (new CPL (path)));
} else if (root == "DCSubtitle") {
- _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path, false)));
+ _assets.push_back (shared_ptr<InteropSubtitleContent> (new InteropSubtitleContent (path)));
}
} else if (boost::algorithm::ends_with (path.string(), ".mxf")) {
ASDCP::EssenceType_t type;
_assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (path)));
break;
case ASDCP::ESS_TIMED_TEXT:
- _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path, true)));
+ _assets.push_back (shared_ptr<SMPTESubtitleContent> (new SMPTESubtitleContent (path)));
break;
default:
throw DCPReadError ("Unknown MXF essence type");
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "interop_load_font.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::optional;
+using namespace dcp;
+
+InteropLoadFont::InteropLoadFont (shared_ptr<const cxml::Node> node)
+{
+ optional<string> x = node->optional_string_attribute ("Id");
+ if (!x) {
+ x = node->optional_string_attribute ("ID");
+ }
+ id = x.get_value_or ("");
+
+ uri = node->string_attribute ("URI");
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class InteropLoadFont
+{
+public:
+ InteropLoadFont () {}
+ InteropLoadFont (boost::shared_ptr<const cxml::Node> node);
+
+ std::string id;
+ std::string uri;
+};
+
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "interop_subtitle_content.h"
+#include "interop_load_font.h"
+#include "xml.h"
+#include "raw_convert.h"
+#include "font.h"
+
+using std::list;
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+InteropSubtitleContent::InteropSubtitleContent (boost::filesystem::path file)
+ : SubtitleContent (file)
+{
+ shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
+ xml->read_file (file);
+ _id = xml->string_child ("SubtitleID");
+
+ _movie_title = xml->string_child ("MovieTitle");
+
+ _load_font_nodes = type_children<dcp::InteropLoadFont> (xml, "LoadFont");
+ list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (xml, "Font");
+
+ parse_common (xml, font_nodes);
+}
+
+InteropSubtitleContent::InteropSubtitleContent (string movie_title, string language)
+ : _movie_title (movie_title)
+{
+ _language = language;
+}
+
+struct SubtitleSorter {
+ bool operator() (SubtitleString const & a, SubtitleString const & b) {
+ if (a.in() != b.in()) {
+ return a.in() < b.in();
+ }
+ return a.v_position() < b.v_position();
+ }
+};
+
+Glib::ustring
+InteropSubtitleContent::xml_as_string () const
+{
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
+ root->set_attribute ("Version", "1.0");
+
+ root->add_child("SubtitleID")->add_child_text (_id);
+ root->add_child("MovieTitle")->add_child_text (_movie_title);
+ root->add_child("ReelNumber")->add_child_text (raw_convert<string> (_reel_number));
+ root->add_child("Language")->add_child_text (_language);
+
+ if (_load_font_nodes.size() > 1) {
+ boost::throw_exception (MiscError ("multiple LoadFont nodes not supported"));
+ }
+
+ if (!_load_font_nodes.empty ()) {
+ xmlpp::Element* load_font = root->add_child("LoadFont");
+ load_font->set_attribute ("Id", _load_font_nodes.front()->id);
+ load_font->set_attribute ("URI", _load_font_nodes.front()->uri);
+ }
+
+ list<SubtitleString> sorted = _subtitles;
+ sorted.sort (SubtitleSorter ());
+
+ /* XXX: multiple fonts not supported */
+ /* XXX: script, underlined, weight not supported */
+
+ bool italic = false;
+ Color color;
+ int size = 0;
+ Effect effect = NONE;
+ Color effect_color;
+ int spot_number = 1;
+ Time last_in;
+ Time last_out;
+ Time last_fade_up_time;
+ Time last_fade_down_time;
+
+ xmlpp::Element* font = 0;
+ xmlpp::Element* subtitle = 0;
+
+ for (list<SubtitleString>::iterator i = sorted.begin(); i != sorted.end(); ++i) {
+
+ /* We will start a new <Font>...</Font> whenever some font property changes.
+ I suppose we should really make an optimal hierarchy of <Font> tags, but
+ that seems hard.
+ */
+
+ bool const font_changed =
+ italic != i->italic() ||
+ color != i->color() ||
+ size != i->size() ||
+ effect != i->effect() ||
+ effect_color != i->effect_color();
+
+ if (font_changed) {
+ italic = i->italic ();
+ color = i->color ();
+ size = i->size ();
+ effect = i->effect ();
+ effect_color = i->effect_color ();
+ }
+
+ if (!font || font_changed) {
+ font = root->add_child ("Font");
+ string id = "theFontId";
+ if (!_load_font_nodes.empty()) {
+ id = _load_font_nodes.front()->id;
+ }
+ font->set_attribute ("Id", id);
+ font->set_attribute ("Italic", italic ? "yes" : "no");
+ font->set_attribute ("Color", color.to_argb_string());
+ font->set_attribute ("Size", raw_convert<string> (size));
+ font->set_attribute ("Effect", effect_to_string (effect));
+ font->set_attribute ("EffectColor", effect_color.to_argb_string());
+ font->set_attribute ("Script", "normal");
+ font->set_attribute ("Underlined", "no");
+ font->set_attribute ("Weight", "normal");
+ }
+
+ if (!subtitle || font_changed ||
+ (last_in != i->in() ||
+ last_out != i->out() ||
+ last_fade_up_time != i->fade_up_time() ||
+ last_fade_down_time != i->fade_down_time()
+ )) {
+
+ subtitle = font->add_child ("Subtitle");
+ subtitle->set_attribute ("SpotNumber", raw_convert<string> (spot_number++));
+ subtitle->set_attribute ("TimeIn", i->in().to_string());
+ subtitle->set_attribute ("TimeOut", i->out().to_string());
+ subtitle->set_attribute ("FadeUpTime", raw_convert<string> (i->fade_up_time().to_ticks()));
+ subtitle->set_attribute ("FadeDownTime", raw_convert<string> (i->fade_down_time().to_ticks()));
+
+ last_in = i->in ();
+ last_out = i->out ();
+ last_fade_up_time = i->fade_up_time ();
+ last_fade_down_time = i->fade_down_time ();
+ }
+
+ xmlpp::Element* text = subtitle->add_child ("Text");
+ text->set_attribute ("VAlign", valign_to_string (i->v_align()));
+ text->set_attribute ("VPosition", raw_convert<string> (i->v_position()));
+ text->add_child_text (i->text());
+ }
+
+ return doc.write_to_string_formatted ("UTF-8");
+}
+
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "subtitle_content.h"
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class InteropLoadFont;
+
+class InteropSubtitleContent : public SubtitleContent
+{
+public:
+ InteropSubtitleContent (std::string movie_title, std::string language);
+ InteropSubtitleContent (boost::filesystem::path file);
+
+ Glib::ustring xml_as_string () const;
+
+private:
+ std::string _movie_title;
+ std::list<boost::shared_ptr<InteropLoadFont> > _load_font_nodes;
+};
+
+}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 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 "load_font.h"
-#include <libcxml/cxml.h>
-
-using std::string;
-using boost::shared_ptr;
-using boost::optional;
-using namespace dcp;
-
-LoadFont::LoadFont (boost::shared_ptr<const cxml::Node> node)
-{
- optional<string> x = node->optional_string_attribute ("Id");
- if (!x) {
- x = node->optional_string_attribute ("ID");
- }
- id = x.get_value_or ("");
-
- uri = node->optional_string_attribute ("URI");
-}
+++ /dev/null
-/*
- Copyright (C) 2012-2014 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 <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-
-namespace cxml {
- class Node;
-}
-
-namespace dcp {
-
-class LoadFont
-{
-public:
- LoadFont () {}
- LoadFont (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- boost::optional<std::string> uri;
-};
-
-}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "smpte_load_font.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+SMPTELoadFont::SMPTELoadFont (shared_ptr<const cxml::Node> node)
+{
+ id = node->string_attribute ("ID");
+ urn = node->content().substr (9);
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class SMPTELoadFont
+{
+public:
+ SMPTELoadFont () {}
+ SMPTELoadFont (boost::shared_ptr<const cxml::Node> node);
+
+ std::string id;
+ std::string urn;
+};
+
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "smpte_subtitle_content.h"
+#include "smpte_load_font.h"
+#include "font.h"
+#include "exceptions.h"
+#include "xml.h"
+#include "AS_DCP.h"
+#include "KM_util.h"
+
+using std::string;
+using std::list;
+using std::stringstream;
+using boost::shared_ptr;
+using namespace dcp;
+
+SMPTESubtitleContent::SMPTESubtitleContent (boost::filesystem::path file)
+ : SubtitleContent (file)
+{
+ ASDCP::TimedText::MXFReader reader;
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str ());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file, r));
+ }
+
+ string s;
+ reader.ReadTimedTextResource (s, 0, 0);
+ shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
+ stringstream t;
+ t << s;
+ xml->read_stream (t);
+
+ ASDCP::WriterInfo info;
+ reader.FillWriterInfo (info);
+
+ char buffer[64];
+ Kumu::bin2UUIDhex (info.AssetUUID, ASDCP::UUIDlen, buffer, sizeof (buffer));
+ _id = buffer;
+
+ _load_font_nodes = type_children<dcp::SMPTELoadFont> (xml, "LoadFont");
+
+ shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList");
+ list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (subtitle_list, "Font");
+
+ parse_common (xml, font_nodes);
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2014 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 "subtitle_content.h"
+
+namespace dcp {
+
+class SMPTELoadFont;
+
+class SMPTESubtitleContent : public SubtitleContent
+{
+public:
+ /** @param file MXF file */
+ SMPTESubtitleContent (boost::filesystem::path file);
+
+private:
+ std::list<boost::shared_ptr<SMPTELoadFont> > _load_font_nodes;
+};
+
+}
#include "xml.h"
#include "font.h"
#include "text.h"
-#include "load_font.h"
#include "subtitle_string.h"
#include "AS_DCP.h"
#include "KM_util.h"
using boost::optional;
using namespace dcp;
-SubtitleContent::SubtitleContent (boost::filesystem::path file, bool mxf)
+SubtitleContent::SubtitleContent (boost::filesystem::path file)
: Content (file)
{
- shared_ptr<cxml::Document> xml;
-
- if (mxf) {
- ASDCP::TimedText::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (file.string().c_str ());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", file, r));
- }
-
- string s;
- reader.ReadTimedTextResource (s, 0, 0);
- xml.reset (new cxml::Document ("SubtitleReel"));
- stringstream t;
- t << s;
- xml->read_stream (t);
-
- ASDCP::WriterInfo info;
- reader.FillWriterInfo (info);
-
- char buffer[64];
- Kumu::bin2UUIDhex (info.AssetUUID, ASDCP::UUIDlen, buffer, sizeof (buffer));
- _id = buffer;
-
- } else {
- xml.reset (new cxml::Document ("DCSubtitle"));
- xml->read_file (file);
- _id = xml->string_child ("SubtitleID");
- }
- /* XXX: hacks aplenty in here; probably need separate parsers for DCSubtitle and SubtitleReel */
+}
- _movie_title = xml->optional_string_child ("MovieTitle");
+void
+SubtitleContent::parse_common (shared_ptr<cxml::Document> xml, list<shared_ptr<dcp::Font> > font_nodes)
+{
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
- xml->ignore_child ("LoadFont");
-
- list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (xml, "Font");
- _load_font_nodes = type_children<dcp::LoadFont> (xml, "LoadFont");
-
/* Now make Subtitle objects to represent the raw XML nodes
in a sane way.
*/
- shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList");
- if (subtitle_list) {
- list<shared_ptr<dcp::Font> > font = type_children<dcp::Font> (subtitle_list, "Font");
- copy (font.begin(), font.end(), back_inserter (font_nodes));
- }
-
ParseState parse_state;
examine_font_nodes (xml, font_nodes, parse_state);
}
-SubtitleContent::SubtitleContent (string movie_title, string language)
- : _movie_title (movie_title)
- , _reel_number ("1")
- , _language (language)
-{
-
-}
-
void
SubtitleContent::examine_font_nodes (
shared_ptr<const cxml::Node> xml,
_subtitles.push_back (
SubtitleString (
- font_id_to_name (effective_font.id),
+ effective_font.id,
effective_font.italic.get(),
effective_font.color.get(),
effective_font.size,
return s;
}
-std::string
-SubtitleContent::font_id_to_name (string id) const
-{
- list<shared_ptr<dcp::LoadFont> >::const_iterator i = _load_font_nodes.begin();
- while (i != _load_font_nodes.end() && (*i)->id != id) {
- ++i;
- }
-
- if (i == _load_font_nodes.end ()) {
- return "";
- }
-
- if ((*i)->uri && (*i)->uri.get() == "arial.ttf") {
- return "Arial";
- }
-
- return "";
-}
-
void
SubtitleContent::add (SubtitleString s)
{
_subtitles.push_back (s);
}
-struct SubtitleSorter {
- bool operator() (SubtitleString const & a, SubtitleString const & b) {
- if (a.in() != b.in()) {
- return a.in() < b.in();
- }
- return a.v_position() < b.v_position();
- }
-};
-
void
SubtitleContent::write_xml (boost::filesystem::path p) const
{
_file = p;
}
-Glib::ustring
-SubtitleContent::xml_as_string () const
-{
- xmlpp::Document doc;
- xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
- root->set_attribute ("Version", "1.0");
-
- root->add_child("SubtitleID")->add_child_text (_id);
- if (_movie_title) {
- root->add_child("MovieTitle")->add_child_text (_movie_title.get ());
- }
- root->add_child("ReelNumber")->add_child_text (raw_convert<string> (_reel_number));
- root->add_child("Language")->add_child_text (_language);
-
- if (_load_font_nodes.size() > 1) {
- boost::throw_exception (MiscError ("multiple LoadFont nodes not supported"));
- }
-
- if (!_load_font_nodes.empty ()) {
- xmlpp::Element* load_font = root->add_child("LoadFont");
- load_font->set_attribute ("Id", _load_font_nodes.front()->id);
- if (_load_font_nodes.front()->uri) {
- load_font->set_attribute ("URI", _load_font_nodes.front()->uri.get ());
- }
- }
-
- list<SubtitleString> sorted = _subtitles;
- sorted.sort (SubtitleSorter ());
-
- /* XXX: multiple fonts not supported */
- /* XXX: script, underlined, weight not supported */
-
- bool italic = false;
- Color color;
- int size = 0;
- Effect effect = NONE;
- Color effect_color;
- int spot_number = 1;
- Time last_in;
- Time last_out;
- Time last_fade_up_time;
- Time last_fade_down_time;
-
- xmlpp::Element* font = 0;
- xmlpp::Element* subtitle = 0;
-
- for (list<SubtitleString>::iterator i = sorted.begin(); i != sorted.end(); ++i) {
-
- /* We will start a new <Font>...</Font> whenever some font property changes.
- I suppose we should really make an optimal hierarchy of <Font> tags, but
- that seems hard.
- */
-
- bool const font_changed =
- italic != i->italic() ||
- color != i->color() ||
- size != i->size() ||
- effect != i->effect() ||
- effect_color != i->effect_color();
-
- if (font_changed) {
- italic = i->italic ();
- color = i->color ();
- size = i->size ();
- effect = i->effect ();
- effect_color = i->effect_color ();
- }
-
- if (!font || font_changed) {
- font = root->add_child ("Font");
- string id = "theFontId";
- if (!_load_font_nodes.empty()) {
- id = _load_font_nodes.front()->id;
- }
- font->set_attribute ("Id", id);
- font->set_attribute ("Italic", italic ? "yes" : "no");
- font->set_attribute ("Color", color.to_argb_string());
- font->set_attribute ("Size", raw_convert<string> (size));
- font->set_attribute ("Effect", effect_to_string (effect));
- font->set_attribute ("EffectColor", effect_color.to_argb_string());
- font->set_attribute ("Script", "normal");
- font->set_attribute ("Underlined", "no");
- font->set_attribute ("Weight", "normal");
- }
-
- if (!subtitle || font_changed ||
- (last_in != i->in() ||
- last_out != i->out() ||
- last_fade_up_time != i->fade_up_time() ||
- last_fade_down_time != i->fade_down_time()
- )) {
-
- subtitle = font->add_child ("Subtitle");
- subtitle->set_attribute ("SpotNumber", raw_convert<string> (spot_number++));
- subtitle->set_attribute ("TimeIn", i->in().to_string());
- subtitle->set_attribute ("TimeOut", i->out().to_string());
- subtitle->set_attribute ("FadeUpTime", raw_convert<string> (i->fade_up_time().to_ticks()));
- subtitle->set_attribute ("FadeDownTime", raw_convert<string> (i->fade_down_time().to_ticks()));
-
- last_in = i->in ();
- last_out = i->out ();
- last_fade_up_time = i->fade_up_time ();
- last_fade_down_time = i->fade_down_time ();
- }
-
- xmlpp::Element* text = subtitle->add_child ("Text");
- text->set_attribute ("VAlign", valign_to_string (i->v_align()));
- text->set_attribute ("VPosition", raw_convert<string> (i->v_position()));
- text->add_child_text (i->text());
- }
-
- return doc.write_to_string_formatted ("UTF-8");
-}
-
Time
SubtitleContent::latest_subtitle_out () const
{
class Font;
class Text;
class Subtitle;
-class LoadFont;
/** @class SubtitleContent
- * @brief A representation of an XML or MXF file containing subtitles.
- *
- * XXX: perhaps this should inhert from MXF, or there should be different
- * classes for XML and MXF subs.
+ * @brief A parent for classes representing a file containing subtitles.
*/
class SubtitleContent : public Content
{
public:
- /** Construct a SubtitleContent.
- * @param file Filename.
- * @param mxf true if the file is an MXF file, false for XML.
- */
- SubtitleContent (boost::filesystem::path file, bool mxf);
- SubtitleContent (std::string movie_title, std::string language);
+ SubtitleContent () {}
+ SubtitleContent (boost::filesystem::path file);
bool equals (
boost::shared_ptr<const Asset>,
void add (SubtitleString);
void write_xml (boost::filesystem::path) const;
- Glib::ustring xml_as_string () const;
+ virtual Glib::ustring xml_as_string () const {
+ /* XXX: this should be pure virtual when SMPTE writing is implemented */
+ return "";
+ }
Time latest_subtitle_out () const;
protected:
+ void parse_common (boost::shared_ptr<cxml::Document> xml, std::list<boost::shared_ptr<dcp::Font> > font_nodes);
+
std::string pkl_type (Standard) const {
return "text/xml";
}
return "Subtitle";
}
-private:
- std::string font_id_to_name (std::string id) const;
+ /* strangely, this is sometimes a string */
+ std::string _reel_number;
+ std::string _language;
+
+ std::list<SubtitleString> _subtitles;
+private:
struct ParseState {
std::list<boost::shared_ptr<Font> > font_nodes;
std::list<boost::shared_ptr<Text> > text_nodes;
std::list<boost::shared_ptr<Text> > const & text_nodes,
ParseState& parse_state
);
-
- boost::optional<std::string> _movie_title;
- /* strangely, this is sometimes a string */
- std::string _reel_number;
- std::string _language;
- std::list<boost::shared_ptr<LoadFont> > _load_font_nodes;
-
- std::list<SubtitleString> _subtitles;
};
}
using std::string;
using std::ostream;
+using boost::optional;
using namespace dcp;
SubtitleString::SubtitleString (
- string font,
+ optional<string> font,
bool italic,
Color color,
int size,
{
s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
<< "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
- << "font " << sub.font() << ", ";
+ << "font " << sub.font().get_value_or ("[default]") << ", ";
if (sub.italic()) {
s << "italic";
#include "types.h"
#include "dcp_time.h"
+#include <boost/optional.hpp>
#include <string>
namespace dcp {
{
public:
SubtitleString (
- std::string font,
+ boost::optional<std::string> font,
bool italic,
Color color,
int size,
Time fade_down_time
);
- /** @return font name */
- std::string font () const {
+ /** @return font ID */
+ boost::optional<std::string> font () const {
return _font;
}
}
private:
- /** font name */
- std::string _font;
+ /** font ID */
+ boost::optional<std::string> _font;
/** true if the text is italic */
bool _italic;
/** text colour */
font.cc
gamma_lut.cc
image.cc
+ interop_load_font.cc
+ interop_subtitle_content.cc
key.cc
- load_font.cc
local_time.cc
metadata.cc
mono_picture_mxf.cc
reel_subtitle_asset.cc
rgb_xyz.cc
signer.cc
+ smpte_load_font.cc
+ smpte_subtitle_content.cc
sound_mxf.cc
sound_mxf_writer.cc
sound_frame.cc
+/*
+ Copyright (C) 2012-2014 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 "interop_subtitle_content.h"
#include <iostream>
-#include "subtitle_content.h"
using namespace std;
exit (EXIT_FAILURE);
}
- dcp::SubtitleContent s (argv[1], false);
+ dcp::InteropSubtitleContent s (argv[1]);
cout << s.xml_as_string ();
return 0;
}
*/
-#include "subtitle_content.h"
+#include "interop_subtitle_content.h"
#include "subtitle_string.h"
#include <boost/test/unit_test.hpp>
using std::list;
+using std::string;
using boost::shared_ptr;
/* Load some subtitle content from XML and check that it is read correctly */
BOOST_AUTO_TEST_CASE (subtitles1)
{
- dcp::SubtitleContent subs ("test/data/subs1.xml", false);
+ dcp::InteropSubtitleContent subs ("test/data/subs1.xml");
BOOST_CHECK_EQUAL (subs.language(), "French");
list<dcp::SubtitleString> s = subs.subtitles_at (dcp::Time (0, 0, 6, 1));
BOOST_CHECK_EQUAL (s.size(), 1);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFontId"),
false,
dcp::Color (255, 255, 255),
39,
s = subs.subtitles_at (dcp::Time (0, 0, 7, 190));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFontId"),
true,
dcp::Color (255, 255, 255),
39,
dcp::Time (0, 0, 0, 1)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFontId"),
false,
dcp::Color (255, 255, 255),
39,
s = subs.subtitles_at (dcp::Time (0, 0, 11, 95));
BOOST_CHECK_EQUAL (s.size(), 1);
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFontId"),
false,
dcp::Color (255, 255, 255),
39,
s = subs.subtitles_at (dcp::Time (0, 0, 14, 42));
BOOST_CHECK_EQUAL (s.size(), 1);
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFontId"),
false,
dcp::Color (255, 255, 255),
39,
/** And similarly for another one */
BOOST_AUTO_TEST_CASE (subtitles2)
{
- dcp::SubtitleContent subs ("test/data/subs2.xml", false);
+ dcp::InteropSubtitleContent subs ("test/data/subs2.xml");
list<dcp::SubtitleString> s = subs.subtitles_at (dcp::Time (0, 0, 42, 100));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 0, 50, 50));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 2, 300));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 15, 50));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 27, 200));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 42, 300));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 45, 200));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 1, 47, 249));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
false,
dcp::Color (255, 255, 255),
42,
s = subs.subtitles_at (dcp::Time (0, 2, 6, 210));
BOOST_CHECK_EQUAL (s.size(), 2);
BOOST_CHECK_EQUAL (s.front(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
dcp::Time (0, 0, 0, 0)
));
BOOST_CHECK_EQUAL (s.back(), dcp::SubtitleString (
- "Arial",
+ string ("theFont"),
true,
dcp::Color (255, 255, 255),
42,
for (list<SubtitleString>::const_iterator k = subs.begin(); k != subs.end(); ++k) {
cout << " " << k->text() << "\n";
cout << " "
- << "font:" << k->font() << "; "
+ << "font:" << k->font().get_value_or("[default]") << "; "
<< "italic:" << k->italic() << "; "
<< "color:" << k->color() << "; "
<< "in:" << k->in() << "; "