More enum class additions.
[dcpomatic.git] / src / lib / content.cc
index b288580cb11d94f461f66c600a00c99c21ba62ae..40790bdc09ca84a82d97614c38e056c5a0f4daa2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -48,10 +48,11 @@ using std::cout;
 using std::vector;
 using std::max;
 using std::pair;
-using boost::shared_ptr;
+using std::shared_ptr;
 using boost::optional;
 using dcp::raw_convert;
 using dcp::locale_convert;
+using namespace dcpomatic;
 
 int const ContentProperty::PATH = 400;
 int const ContentProperty::POSITION = 401;
@@ -90,10 +91,9 @@ Content::Content (boost::filesystem::path p)
 Content::Content (cxml::ConstNodePtr node)
        : _change_signals_frequent (false)
 {
-       list<cxml::NodePtr> path_children = node->node_children ("Path");
-       BOOST_FOREACH (cxml::NodePtr i, path_children) {
+       for (auto i: node->node_children("Path")) {
                _paths.push_back (i->content());
-               optional<time_t> const mod = i->optional_number_attribute<time_t>("mtime");
+               auto const mod = i->optional_number_attribute<time_t>("mtime");
                if (mod) {
                        _last_write_times.push_back (*mod);
                } else if (boost::filesystem::exists(i->content())) {
@@ -168,7 +168,7 @@ string
 Content::calculate_digest () const
 {
        boost::mutex::scoped_lock lm (_mutex);
-       vector<boost::filesystem::path> p = _paths;
+       auto p = _paths;
        lm.unlock ();
 
        /* Some content files are very big, so we use a poor man's
@@ -185,13 +185,13 @@ Content::examine (shared_ptr<const Film>, shared_ptr<Job> job)
                job->sub (_("Computing digest"));
        }
 
-       string const d = calculate_digest ();
+       auto const d = calculate_digest ();
 
        boost::mutex::scoped_lock lm (_mutex);
        _digest = d;
 
        _last_write_times.clear ();
-       BOOST_FOREACH (boost::filesystem::path i, _paths) {
+       for (auto i: _paths) {
                _last_write_times.push_back (boost::filesystem::last_write_time(i));
        }
 }
@@ -200,18 +200,18 @@ void
 Content::signal_change (ChangeType c, int p)
 {
        try {
-               if (c == CHANGE_TYPE_PENDING || c == CHANGE_TYPE_CANCELLED) {
+               if (c == ChangeType::PENDING || c == ChangeType::CANCELLED) {
                        Change (c, shared_from_this(), p, _change_signals_frequent);
                } else {
                        emit (boost::bind (boost::ref(Change), c, shared_from_this(), p, _change_signals_frequent));
                }
-       } catch (boost::bad_weak_ptr) {
+       } catch (std::bad_weak_ptr &) {
                /* This must be during construction; never mind */
        }
 }
 
 void
-Content::set_position (shared_ptr<const Film> film, DCPTime p)
+Content::set_position (shared_ptr<const Film> film, DCPTime p, bool force_emit)
 {
        /* video and audio content can modify its position */
 
@@ -219,7 +219,13 @@ Content::set_position (shared_ptr<const Film> film, DCPTime p)
                video->modify_position (film, p);
        }
 
-       if (audio) {
+       /* Only allow the audio to modify if we have no video;
+          sometimes p can't be on an integer video AND audio frame,
+          and in these cases we want the video constraint to be
+          satisfied since (I think) the audio code is better able to
+          cope.
+       */
+       if (!video && audio) {
                audio->modify_position (film, p);
        }
 
@@ -227,7 +233,7 @@ Content::set_position (shared_ptr<const Film> film, DCPTime p)
 
        {
                boost::mutex::scoped_lock lm (_mutex);
-               if (p == _position) {
+               if (p == _position && !force_emit) {
                        cc.abort ();
                        return;
                }
@@ -245,7 +251,8 @@ Content::set_trim_start (ContentTime t)
                video->modify_trim_start (t);
        }
 
-       if (audio) {
+       /* See note in ::set_position */
+       if (!video && audio) {
                audio->modify_trim_start (t);
        }
 
@@ -274,7 +281,7 @@ Content::clone () const
 {
        /* This is a bit naughty, but I can't think of a compelling reason not to do it ... */
        xmlpp::Document doc;
-       xmlpp::Node* node = doc.create_root_node ("Content");
+       auto node = doc.create_root_node ("Content");
        as_xml (node, true);
 
        /* notes is unused here (we assume) */
@@ -285,7 +292,7 @@ Content::clone () const
 string
 Content::technical_summary () const
 {
-       string s = String::compose ("%1 %2 %3", path_summary(), digest(), position().seconds());
+       auto s = String::compose ("%1 %2 %3", path_summary(), digest(), position().seconds());
        if (_video_frame_rate) {
                s += String::compose(" %1", *_video_frame_rate);
        }
@@ -295,7 +302,11 @@ Content::technical_summary () const
 DCPTime
 Content::length_after_trim (shared_ptr<const Film> film) const
 {
-       return max (DCPTime(), full_length(film) - DCPTime(trim_start() + trim_end(), film->active_frame_rate_change(position())));
+       auto length = max(DCPTime(), full_length(film) - DCPTime(trim_start() + trim_end(), film->active_frame_rate_change(position())));
+       if (video) {
+               length = length.round(film->video_frame_rate());
+       }
+       return length;
 }
 
 /** @return string which changes when something about this content changes which affects
@@ -315,7 +326,7 @@ Content::identifier () const
 bool
 Content::paths_valid () const
 {
-       BOOST_FOREACH (boost::filesystem::path i, _paths) {
+       for (auto i: _paths) {
                if (!boost::filesystem::exists (i)) {
                        return false;
                }
@@ -333,7 +344,7 @@ Content::set_paths (vector<boost::filesystem::path> paths)
                boost::mutex::scoped_lock lm (_mutex);
                _paths = paths;
                _last_write_times.clear ();
-               BOOST_FOREACH (boost::filesystem::path i, _paths) {
+               for (auto i: _paths) {
                        _last_write_times.push_back (boost::filesystem::last_write_time(i));
                }
        }
@@ -346,7 +357,7 @@ Content::path_summary () const
 
        DCPOMATIC_ASSERT (number_of_paths ());
 
-       string s = path(0).filename().string ();
+       auto s = path(0).filename().string();
        if (number_of_paths() > 1) {
                s += " ...";
        }
@@ -461,8 +472,8 @@ Content::take_settings_from (shared_ptr<const Content> c)
                audio->take_settings_from (c->audio);
        }
 
-       list<shared_ptr<TextContent> >::iterator i = text.begin ();
-       list<shared_ptr<TextContent> >::const_iterator j = c->text.begin ();
+       auto i = text.begin ();
+       auto j = c->text.begin ();
        while (i != text.end() && j != c->text.end()) {
                (*i)->take_settings_from (*j);
                ++i;
@@ -483,7 +494,7 @@ Content::only_text () const
 shared_ptr<TextContent>
 Content::text_of_original_type (TextType type) const
 {
-       BOOST_FOREACH (shared_ptr<TextContent> i, text) {
+       for (auto i: text) {
                if (i->original_type() == type) {
                        return i;
                }