Fix the build for older macOS.
[dcpomatic.git] / src / lib / writer.cc
index 81b77d5cea62a5219257368af0711660e69ccfcf..8b51eb58759a1364ed9af4fc80ff388401b164e1 100644 (file)
 
 using std::cout;
 using std::dynamic_pointer_cast;
-using std::list;
-using std::make_pair;
 using std::make_shared;
-using std::map;
 using std::max;
 using std::min;
-using std::pair;
 using std::shared_ptr;
 using std::string;
 using std::vector;
@@ -74,14 +70,6 @@ using dcp::ArrayData;
 using namespace dcpomatic;
 
 
-static
-void
-ignore_progress (float)
-{
-
-}
-
-
 /** @param j Job to report progress to, or 0.
  *  @param text_only true to enable only the text (subtitle/ccap) parts of the writer.
  */
@@ -393,6 +381,8 @@ void
 Writer::thread ()
 try
 {
+       start_of_thread ("Writer");
+
        while (true)
        {
                boost::mutex::scoped_lock lock (_state_mutex);
@@ -533,36 +523,9 @@ Writer::terminate_thread (bool can_throw)
 }
 
 
-/** @param output_dcp Path to DCP folder to write */
 void
-Writer::finish (boost::filesystem::path output_dcp)
+Writer::calculate_digests ()
 {
-       if (_thread.joinable()) {
-               LOG_GENERAL_NC ("Terminating writer thread");
-               terminate_thread (true);
-       }
-
-       LOG_GENERAL_NC ("Finishing ReelWriters");
-
-       for (auto& i: _reels) {
-               write_hanging_text (i);
-               i.finish (output_dcp);
-       }
-
-       LOG_GENERAL_NC ("Writing XML");
-
-       dcp::DCP dcp (output_dcp);
-
-       auto cpl = make_shared<dcp::CPL>(
-               film()->dcp_name(),
-               film()->dcp_content_type()->libdcp_kind(),
-               film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE
-               );
-
-       dcp.add (cpl);
-
-       /* Calculate digests for each reel in parallel */
-
        auto job = _job.lock ();
        if (job) {
                job->sub (_("Computing digests"));
@@ -573,17 +536,19 @@ Writer::finish (boost::filesystem::path output_dcp)
 
        auto work = make_shared<boost::asio::io_service::work>(service);
 
-       int const threads = max (1, Config::instance()->master_encoding_threads ());
+       int const threads = max (1, Config::instance()->master_encoding_threads());
 
        for (int i = 0; i < threads; ++i) {
                pool.create_thread (boost::bind (&boost::asio::io_service::run, &service));
        }
 
-       boost::function<void (float)> set_progress;
+       std::function<void (float)> set_progress;
        if (job) {
                set_progress = boost::bind (&Writer::set_digest_progress, this, job.get(), _1);
        } else {
-               set_progress = &ignore_progress;
+               set_progress = [](float) {
+                       boost::this_thread::interruption_point();
+               };
        }
 
        for (auto& i: _reels) {
@@ -592,8 +557,50 @@ Writer::finish (boost::filesystem::path output_dcp)
        service.post (boost::bind (&Writer::calculate_referenced_digests, this, set_progress));
 
        work.reset ();
-       pool.join_all ();
+
+       try {
+               pool.join_all ();
+       } catch (boost::thread_interrupted) {
+               /* join_all was interrupted, so we need to interrupt the threads
+                * in our pool then try again to join them.
+                */
+               pool.interrupt_all ();
+               pool.join_all ();
+       }
+
        service.stop ();
+}
+
+
+/** @param output_dcp Path to DCP folder to write */
+void
+Writer::finish (boost::filesystem::path output_dcp)
+{
+       if (_thread.joinable()) {
+               LOG_GENERAL_NC ("Terminating writer thread");
+               terminate_thread (true);
+       }
+
+       LOG_GENERAL_NC ("Finishing ReelWriters");
+
+       for (auto& i: _reels) {
+               write_hanging_text (i);
+               i.finish (output_dcp);
+       }
+
+       LOG_GENERAL_NC ("Writing XML");
+
+       dcp::DCP dcp (output_dcp);
+
+       auto cpl = make_shared<dcp::CPL>(
+               film()->dcp_name(),
+               film()->dcp_content_type()->libdcp_kind(),
+               film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE
+               );
+
+       dcp.add (cpl);
+
+       calculate_digests ();
 
        /* Add reels */
 
@@ -613,6 +620,9 @@ Writer::finish (boost::filesystem::path output_dcp)
                issuer = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
        }
 
+       cpl->set_creator (creator);
+       cpl->set_issuer (issuer);
+
        cpl->set_ratings (film()->ratings());
 
        vector<dcp::ContentVersion> cv;
@@ -640,6 +650,9 @@ Writer::finish (boost::filesystem::path output_dcp)
        if (film()->luminance()) {
                cpl->set_luminance (*film()->luminance());
        }
+       if (film()->sign_language_video_language()) {
+               cpl->set_sign_language_video_language (*film()->sign_language_video_language());
+       }
 
        auto ac = film()->mapped_audio_channels();
        dcp::MCASoundField field = (
@@ -707,9 +720,9 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp)
        boost::algorithm::replace_all (text, "$TYPE", film()->dcp_content_type()->pretty_name());
        boost::algorithm::replace_all (text, "$CONTAINER", film()->container()->container_nickname());
 
-       auto audio_languages = film()->audio_languages();
-       if (!audio_languages.empty()) {
-               boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", audio_languages.front().description());
+       auto audio_language = film()->audio_language();
+       if (audio_language) {
+               boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", audio_language->description());
        } else {
                boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", _("None"));
        }
@@ -930,12 +943,15 @@ Writer::set_digest_progress (Job* job, float progress)
 
        Waker waker;
        waker.nudge ();
+
+       boost::this_thread::interruption_point();
 }
 
 
 /** Calculate hashes for any referenced MXF assets which do not already have one */
 void
-Writer::calculate_referenced_digests (boost::function<void (float)> set_progress)
+Writer::calculate_referenced_digests (std::function<void (float)> set_progress)
+try
 {
        for (auto const& i: _reel_assets) {
                auto file = dynamic_pointer_cast<dcp::ReelFileAsset>(i.asset);
@@ -944,6 +960,10 @@ Writer::calculate_referenced_digests (boost::function<void (float)> set_progress
                        file->set_hash (file->asset_ref().asset()->hash());
                }
        }
+} catch (boost::thread_interrupted) {
+       /* set_progress contains an interruption_point, so any of these methods
+        * may throw thread_interrupted, at which point we just give up.
+        */
 }