Subtitle language handling tweaks; write multiple subtitle languages
[dcpomatic.git] / src / lib / writer.cc
index 7d1088276995a242300402684facbf0290e3876f..a9700f4f5edbbb7272e2ed2735c56f74cd2535b3 100644 (file)
@@ -62,7 +62,11 @@ using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
 using boost::optional;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
 using dcp::Data;
+using dcp::ArrayData;
 using namespace dcpomatic;
 
 Writer::Writer (shared_ptr<const Film> film, weak_ptr<Job> j)
@@ -127,7 +131,7 @@ Writer::~Writer ()
  *  @param eyes Eyes that this frame image is for.
  */
 void
-Writer::write (Data encoded, Frame frame, Eyes eyes)
+Writer::write (shared_ptr<const Data> encoded, Frame frame, Eyes eyes)
 {
        boost::mutex::scoped_lock lock (_state_mutex);
 
@@ -423,7 +427,7 @@ try
                        case QueueItem::FULL:
                                LOG_DEBUG_ENCODE (N_("Writer FULL-writes %1 (%2)"), qi.frame, (int) qi.eyes);
                                if (!qi.encoded) {
-                                       qi.encoded = Data (_film->j2c_path (qi.reel, qi.frame, qi.eyes, false));
+                                       qi.encoded.reset (new ArrayData(_film->j2c_path(qi.reel, qi.frame, qi.eyes, false)));
                                }
                                reel.write (qi.encoded, qi.frame, qi.eyes);
                                ++_full_written;
@@ -489,17 +493,18 @@ catch (...)
 void
 Writer::terminate_thread (bool can_throw)
 {
+       boost::this_thread::disable_interruption dis;
+
        boost::mutex::scoped_lock lock (_state_mutex);
-       if (!_thread.joinable()) {
-               return;
-       }
 
        _finish = true;
        _empty_condition.notify_all ();
        _full_condition.notify_all ();
        lock.unlock ();
 
-       _thread.join ();
+       try {
+               _thread.join ();
+       } catch (...) {}
 
        if (can_throw) {
                rethrow ();
@@ -561,27 +566,64 @@ Writer::finish ()
        pool.join_all ();
        service.stop ();
 
-       /* Add reels to CPL */
+       /* Add reels */
 
        BOOST_FOREACH (ReelWriter& i, _reels) {
                cpl->add (i.create_reel (_reel_assets, _fonts));
        }
 
-       dcp::XMLMetadata meta;
-       meta.annotation_text = cpl->annotation_text ();
-       meta.creator = Config::instance()->dcp_creator ();
-       if (meta.creator.empty ()) {
-               meta.creator = String::compose ("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
+       /* Add metadata */
+
+       string creator = Config::instance()->dcp_creator();
+       if (creator.empty()) {
+               creator = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
        }
-       meta.issuer = Config::instance()->dcp_issuer ();
-       if (meta.issuer.empty ()) {
-               meta.issuer = String::compose ("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
+
+       string issuer = Config::instance()->dcp_issuer();
+       if (issuer.empty()) {
+               issuer = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
        }
-       meta.set_issue_date_now ();
 
-       cpl->set_metadata (meta);
-       cpl->set_ratings (vector_to_list(_film->ratings()));
-       cpl->set_content_version_label_text (_film->content_version());
+       cpl->set_ratings (_film->ratings());
+
+       vector<dcp::ContentVersion> cv;
+       BOOST_FOREACH (string i, _film->content_versions()) {
+               cv.push_back (dcp::ContentVersion(i));
+       }
+       cpl->set_content_versions (cv);
+
+       cpl->set_full_content_title_text (_film->name());
+       cpl->set_full_content_title_text_language (_film->name_language());
+       cpl->set_release_territory (_film->release_territory());
+       cpl->set_version_number (_film->version_number());
+       cpl->set_status (_film->status());
+       cpl->set_chain (_film->chain());
+       cpl->set_distributor (_film->distributor());
+       cpl->set_facility (_film->facility());
+       cpl->set_luminance (_film->luminance());
+
+       list<int> ac = _film->mapped_audio_channels ();
+       dcp::MCASoundField field = (
+               find(ac.begin(), ac.end(), static_cast<int>(dcp::BSL)) != ac.end() ||
+               find(ac.begin(), ac.end(), static_cast<int>(dcp::BSR)) != ac.end()
+               ) ? dcp::SEVEN_POINT_ONE : dcp::FIVE_POINT_ONE;
+
+       dcp::MainSoundConfiguration msc (field, _film->audio_channels());
+       BOOST_FOREACH (int i, ac) {
+               if (i < _film->audio_channels()) {
+                       msc.set_mapping (i, static_cast<dcp::Channel>(i));
+               }
+       }
+
+       cpl->set_main_sound_configuration (msc.to_string());
+       cpl->set_main_sound_sample_rate (_film->audio_frame_rate());
+       cpl->set_main_picture_stored_area (_film->frame_size());
+       cpl->set_main_picture_active_area (_film->active_area());
+
+       vector<dcp::LanguageTag> sl = _film->subtitle_languages();
+       if (sl.size() > 1) {
+               cpl->set_additional_subtitle_languages(std::vector<dcp::LanguageTag>(sl.begin() + 1, sl.end()));
+       }
 
        shared_ptr<const dcp::CertificateChain> signer;
        signer = Config::instance()->signer_chain ();
@@ -591,7 +633,15 @@ Writer::finish ()
                throw InvalidSignerError (reason);
        }
 
-       dcp.write_xml (_film->interop () ? dcp::INTEROP : dcp::SMPTE, meta, signer, Config::instance()->dcp_metadata_filename_format());
+       dcp.write_xml (
+               _film->interop() ? dcp::INTEROP : dcp::SMPTE,
+               issuer,
+               creator,
+               dcp::LocalTime().as_string(),
+               String::compose("Created by libdcp %1", dcp::version),
+               signer,
+               Config::instance()->dcp_metadata_filename_format()
+               );
 
        LOG_GENERAL (
                N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT, %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk
@@ -615,15 +665,12 @@ Writer::write_cover_sheet ()
        boost::algorithm::replace_all (text, "$CONTAINER", _film->container()->container_nickname());
        boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", _film->isdcf_metadata().audio_language);
 
-       optional<string> subtitle_language;
-       BOOST_FOREACH (shared_ptr<Content> i, _film->content()) {
-               BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
-                       if (j->type() == TEXT_OPEN_SUBTITLE && j->use()) {
-                               subtitle_language = j->language ();
-                       }
-               }
+       vector<dcp::LanguageTag> subtitle_languages = _film->subtitle_languages();
+       if (subtitle_languages.empty()) {
+               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", "None");
+       } else {
+               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_languages.front().description());
        }
-       boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_language.get_value_or("None"));
 
        boost::uintmax_t size = 0;
        for (