Merge master.
[libdcp.git] / src / subtitle_content.cc
index f338517e407e35a4136eb1864d7db84b7f5bbd30..a622e7b09a2cce1b144c0e03763b0e5d7540fd6a 100644 (file)
@@ -17,6 +17,7 @@
 
 */
 
+#include "raw_convert.h"
 #include "subtitle_content.h"
 #include "util.h"
 #include "xml.h"
@@ -24,8 +25,9 @@
 #include "text.h"
 #include "load_font.h"
 #include "subtitle_string.h"
+#include "AS_DCP.h"
+#include "KM_util.h"
 #include <libxml++/nodes/element.h>
-#include <boost/lexical_cast.hpp>
 #include <boost/algorithm/string.hpp>
 #include <fstream>
 
@@ -36,19 +38,45 @@ using std::ofstream;
 using std::stringstream;
 using std::cout;
 using boost::shared_ptr;
-using boost::lexical_cast;
 using boost::optional;
 using namespace dcp;
 
-SubtitleContent::SubtitleContent (boost::filesystem::path file)
+SubtitleContent::SubtitleContent (boost::filesystem::path file, bool mxf)
        : Content (file)
        , _need_sort (false)
 {
-       shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
-       xml->read_file (file);
+       shared_ptr<cxml::Document> xml;
        
-       _id = xml->string_child ("SubtitleID");
-       _movie_title = xml->string_child ("MovieTitle");
+       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");
        _reel_number = xml->string_child ("ReelNumber");
        _language = xml->string_child ("Language");
 
@@ -60,6 +88,12 @@ SubtitleContent::SubtitleContent (boost::filesystem::path file)
        /* 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);
@@ -180,7 +214,7 @@ SubtitleContent::font_id_to_name (string id) const
                return "";
        }
 
-       if ((*i)->uri == "arial.ttf") {
+       if ((*i)->uri && (*i)->uri.get() == "arial.ttf") {
                return "Arial";
        }
 
@@ -220,8 +254,10 @@ SubtitleContent::xml_as_string () const
        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 (lexical_cast<string> (_reel_number));
+       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) {
@@ -230,8 +266,10 @@ SubtitleContent::xml_as_string () const
 
        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);
+               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<shared_ptr<SubtitleString> > sorted = _subtitles;
@@ -287,7 +325,7 @@ SubtitleContent::xml_as_string () const
                        font->set_attribute ("Id", id);
                        font->set_attribute ("Italic", italic ? "yes" : "no");
                        font->set_attribute ("Color", color.to_argb_string());
-                       font->set_attribute ("Size", lexical_cast<string> (size));
+                       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");
@@ -303,11 +341,11 @@ SubtitleContent::xml_as_string () const
                            )) {
 
                        subtitle = font->add_child ("Subtitle");
-                       subtitle->set_attribute ("SpotNumber", lexical_cast<string> (spot_number++));
+                       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", lexical_cast<string> ((*i)->fade_up_time().to_ticks()));
-                       subtitle->set_attribute ("FadeDownTime", lexical_cast<string> ((*i)->fade_down_time().to_ticks()));
+                       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 ();
@@ -317,7 +355,7 @@ SubtitleContent::xml_as_string () const
 
                xmlpp::Element* text = subtitle->add_child ("Text");
                text->set_attribute ("VAlign", valign_to_string ((*i)->v_align()));             
-               text->set_attribute ("VPosition", lexical_cast<string> ((*i)->v_position()));
+               text->set_attribute ("VPosition", raw_convert<string> ((*i)->v_position()));
                text->add_child_text ((*i)->text());
        }