Make sure at least one position change event is emitted after
[dcpomatic.git] / src / lib / film.cc
index f1d066f34e369a178a8cd380606ffb5ad7e0e7a3..c70e82cdacb0c2890d993777779fb370d4c522ba 100644 (file)
@@ -92,6 +92,7 @@ using std::runtime_error;
 using std::copy;
 using std::back_inserter;
 using std::map;
+using std::exception;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -477,6 +478,13 @@ Film::read_metadata (optional<boost::filesystem::path> path)
                _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
        }
 
+       list<string> notes;
+
+       if (_isdcf_metadata.has_subtitle_language) {
+               notes.push_back(_("This film had a subtitle language, configured within the ISDCF metadata dialogue, which will be ignored by this version of DCP-o-matic.  "
+                                 "Please set the language for each piece of subtitle or closed-caption content in the film."));
+       }
+
        {
                optional<string> c = f.optional_string_child ("DCPContentType");
                if (c) {
@@ -529,8 +537,6 @@ 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);
 
-       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 */
@@ -721,32 +727,35 @@ 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 (subtitle_language) {
+                       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";
                        }
@@ -1037,7 +1046,16 @@ Film::j2c_path (int reel, Frame frame, Eyes eyes, bool tmp) const
        return file (p);
 }
 
-/** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs */
+static
+bool
+cpl_summary_compare (CPLSummary const & a, CPLSummary const & b)
+{
+       return a.last_write_time > b.last_write_time;
+}
+
+/** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs.
+ *  The list will be returned in reverse order of timestamp (i.e. most recent first).
+ */
 vector<CPLSummary>
 Film::cpls () const
 {
@@ -1055,23 +1073,15 @@ Film::cpls () const
                        ) {
 
                        try {
-                               dcp::DCP dcp (*i);
-                               dcp.read ();
-                               DCPOMATIC_ASSERT (dcp.cpls().front()->file());
-                               out.push_back (
-                                       CPLSummary (
-                                               i->path().leaf().string(),
-                                               dcp.cpls().front()->id(),
-                                               dcp.cpls().front()->annotation_text(),
-                                               dcp.cpls().front()->file().get()
-                                               )
-                                       );
+                               out.push_back (CPLSummary(*i));
                        } catch (...) {
 
                        }
                }
        }
 
+       sort (out.begin(), out.end(), cpl_summary_compare);
+
        return out;
 }
 
@@ -1660,7 +1670,7 @@ Film::closed_caption_tracks () const
        list<DCPTextTrack> tt;
        BOOST_FOREACH (shared_ptr<Content> i, content()) {
                BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
-                       /* XXX: Empty DCPTextTrack ends up being a magic value here */
+                       /* XXX: Empty DCPTextTrack ends up being a magic value here - the "unknown" or "not specified" track */
                        DCPTextTrack dtt = j->dcp_track().get_value_or(DCPTextTrack());
                        if (j->type() == TEXT_CLOSED_CAPTION && find(tt.begin(), tt.end(), dtt) == tt.end()) {
                                tt.push_back (dtt);