Put Time types in dcpomatic namespace.
[dcpomatic.git] / src / lib / film.cc
index 9be048b65d8caa23c6434d1fe4ff8cfebcc66efc..efc89e0eb6be3b27c6a7c04a31b82ee32c68f54b 100644 (file)
@@ -99,6 +99,7 @@ using boost::dynamic_pointer_cast;
 using boost::optional;
 using boost::is_any_of;
 using dcp::raw_convert;
+using namespace dcpomatic;
 
 string const Film::metadata_file = "metadata.xml";
 
@@ -403,6 +404,14 @@ Film::metadata (bool with_content_paths) const
        root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0");
        root->add_child("ReencodeJ2K")->add_child_text (_reencode_j2k ? "1" : "0");
        root->add_child("UserExplicitVideoFrameRate")->add_child_text(_user_explicit_video_frame_rate ? "1" : "0");
+       for (map<dcp::Marker, DCPTime>::const_iterator i = _markers.begin(); i != _markers.end(); ++i) {
+               xmlpp::Element* m = root->add_child("Marker");
+               m->set_attribute("Type", dcp::marker_to_string(i->first));
+               m->add_child_text(raw_convert<string>(i->second.get()));
+       }
+       BOOST_FOREACH (dcp::Rating i, _ratings) {
+               i.as_xml (root->add_child("Rating"));
+       }
        _playlist->as_xml (root->add_child ("Playlist"), with_content_paths);
 
        return doc;
@@ -478,6 +487,7 @@ Film::read_metadata (optional<boost::filesystem::path> path)
                _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
        }
 
+
        {
                optional<string> c = f.optional_string_child ("DCPContentType");
                if (c) {
@@ -530,8 +540,15 @@ Film::read_metadata (optional<boost::filesystem::path> path)
        _reencode_j2k = f.optional_bool_child("ReencodeJ2K").get_value_or(false);
        _user_explicit_video_frame_rate = f.optional_bool_child("UserExplicitVideoFrameRate").get_value_or(false);
 
+       BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Marker")) {
+               _markers[dcp::marker_from_string(i->string_attribute("Type"))] = DCPTime(dcp::raw_convert<DCPTime::Type>(i->content()));
+       }
+
+       BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Rating")) {
+               _ratings.push_back (dcp::Rating(i));
+       }
+
        list<string> notes;
-       /* This method is the only one that can return notes (so far) */
        _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
 
        /* Write backtraces to this film's directory, until another film is loaded */
@@ -722,36 +739,49 @@ Film::isdcf_name (bool if_created_now) const
 
        if (!dm.audio_language.empty ()) {
                d += "_" + dm.audio_language;
-               if (!dm.subtitle_language.empty()) {
 
-                       /* I'm not clear on the precise details of the convention for CCAP labelling;
-                          for now I'm just appending -CCAP if we have any closed captions.
-                       */
+               /* I'm not clear on the precise details of the convention for CCAP labelling;
+                  for now I'm just appending -CCAP if we have any closed captions.
+               */
 
-                       bool burnt_in = true;
-                       bool ccap = false;
-                       BOOST_FOREACH (shared_ptr<Content> i, content()) {
-                               BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
-                                       if (j->type() == TEXT_OPEN_SUBTITLE && j->use() && !j->burn()) {
+               optional<string> subtitle_language;
+               bool burnt_in = true;
+               bool ccap = false;
+               BOOST_FOREACH (shared_ptr<Content> i, content()) {
+                       BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
+                               if (j->type() == TEXT_OPEN_SUBTITLE && j->use()) {
+                                       subtitle_language = j->language ();
+                                       if (!j->burn()) {
                                                burnt_in = false;
-                                       } else if (j->type() == TEXT_CLOSED_CAPTION) {
-                                               ccap = true;
                                        }
+                               } else if (j->type() == TEXT_CLOSED_CAPTION && j->use()) {
+                                       ccap = true;
                                }
                        }
+               }
 
-                       string language = dm.subtitle_language;
-                       if (burnt_in && language != "XX") {
-                               transform (language.begin(), language.end(), language.begin(), ::tolower);
+               if (dm.subtitle_language) {
+                       /* Subtitle language is overridden in ISDCF metadata, primarily to handle
+                          content with pre-burnt subtitles.
+                       */
+                       d += "-" + *dm.subtitle_language;
+                       if (ccap) {
+                               d += "-CCAP";
+                       }
+               } else if (subtitle_language) {
+                       /* Language is worked out from the content */
+                       if (burnt_in && *subtitle_language != "XX") {
+                               transform (subtitle_language->begin(), subtitle_language->end(), subtitle_language->begin(), ::tolower);
                        } else {
-                               transform (language.begin(), language.end(), language.begin(), ::toupper);
+                               transform (subtitle_language->begin(), subtitle_language->end(), subtitle_language->begin(), ::toupper);
                        }
 
-                       d += "-" + language;
+                       d += "-" + *subtitle_language;
                        if (ccap) {
                                d += "-CCAP";
                        }
                } else {
+                       /* No subtitles */
                        d += "-XX";
                }
        }
@@ -1354,26 +1384,25 @@ Film::make_kdm (
 
        map<shared_ptr<const dcp::ReelMXF>, dcp::Key> keys;
 
-       BOOST_FOREACH(shared_ptr<const dcp::ReelAsset> i, cpl->reel_assets ()) {
-               shared_ptr<const dcp::ReelMXF> mxf = boost::dynamic_pointer_cast<const dcp::ReelMXF> (i);
-               if (!mxf || !mxf->key_id()) {
+       BOOST_FOREACH(shared_ptr<const dcp::ReelMXF> i, cpl->reel_mxfs()) {
+               if (!i->key_id()) {
                        continue;
                }
 
                /* Get any imported key for this ID */
                bool done = false;
                BOOST_FOREACH (dcp::DecryptedKDMKey j, imported_keys) {
-                       if (j.id() == mxf->key_id().get()) {
-                               LOG_GENERAL ("Using imported key for %1", mxf->key_id().get());
-                               keys[mxf] = j.key();
+                       if (j.id() == i->key_id().get()) {
+                               LOG_GENERAL ("Using imported key for %1", i->key_id().get());
+                               keys[i] = j.key();
                                done = true;
                        }
                }
 
                if (!done) {
                        /* No imported key; it must be an asset that we encrypted */
-                       LOG_GENERAL ("Using our own key for %1", mxf->key_id().get());
-                       keys[mxf] = key();
+                       LOG_GENERAL ("Using our own key for %1", i->key_id().get());
+                       keys[i] = key();
                }
        }
 
@@ -1672,3 +1701,34 @@ Film::closed_caption_tracks () const
 
        return tt;
 }
+
+void
+Film::set_marker (dcp::Marker type, DCPTime time)
+{
+       ChangeSignaller<Film> ch (this, MARKERS);
+       _markers[type] = time;
+}
+
+void
+Film::unset_marker (dcp::Marker type)
+{
+       ChangeSignaller<Film> ch (this, MARKERS);
+       _markers.erase (type);
+}
+
+void
+Film::set_ratings (vector<dcp::Rating> r)
+{
+       ChangeSignaller<Film> ch (this, RATINGS);
+       _ratings = r;
+}
+
+optional<DCPTime>
+Film::marker (dcp::Marker type) const
+{
+       map<dcp::Marker, DCPTime>::const_iterator i = _markers.find (type);
+       if (i == _markers.end()) {
+               return optional<DCPTime>();
+       }
+       return i->second;
+}