Handle fonts/subdirs correctly for CCAPs with _map (#2584).
[dcpomatic.git] / src / lib / map_cli.cc
index c95d7f1a1aaa4c2f3bb2b5f2eda6ddf2b80c7bb0..31adf3a519ba00fcebf01b7f8b49fbbbd512b74e 100644 (file)
@@ -196,13 +196,20 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                CopyError(std::string message) : std::runtime_error(message) {}
        };
 
-       auto maybe_copy = [&assets, output_dir](
+       vector<string> already_copied;
+
+       auto maybe_copy = [&assets, &already_copied, output_dir](
                string asset_id,
                bool rename,
                bool hard_link,
                bool soft_link,
                boost::optional<boost::filesystem::path> extra = boost::none
                ) {
+
+               if (std::find(already_copied.begin(), already_copied.end(), asset_id) != already_copied.end()) {
+                       return;
+               }
+
                auto iter = std::find_if(assets.begin(), assets.end(), [asset_id](shared_ptr<const dcp::Asset> a) { return a->id() == asset_id; });
                if (iter != assets.end()) {
                        DCP_ASSERT((*iter)->file());
@@ -239,7 +246,8 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                                        throw CopyError(String::compose("Could not copy asset %1: %2", input_path.string(), ec.message()));
                                }
                        }
-                       (*iter)->set_file(output_path);
+                       (*iter)->set_file_preserving_hash(output_path);
+                       already_copied.push_back(asset_id);
                } else {
                        boost::system::error_code ec;
                        boost::filesystem::remove_all(*output_dir, ec);
@@ -259,25 +267,31 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                }
        };
 
+       auto maybe_copy_font = [&maybe_copy](shared_ptr<const dcp::SubtitleAsset> asset, bool rename, bool hard_link, bool soft_link) {
+               auto interop = dynamic_pointer_cast<const dcp::InteropSubtitleAsset>(asset);
+               boost::optional<boost::filesystem::path> extra;
+               if (interop) {
+                       extra = interop->id();
+                       for (auto font_asset: interop->font_assets()) {
+                               maybe_copy(font_asset->id(), rename, hard_link, soft_link, extra);
+                       }
+               }
+               return extra;
+       };
+
        /* Copy assets that the CPLs need */
        try {
                for (auto cpl: cpls) {
                        for (auto reel: cpl->reels()) {
                                maybe_copy_from_reel(reel->main_picture(), rename, hard_link, soft_link);
                                maybe_copy_from_reel(reel->main_sound(), rename, hard_link, soft_link);
-                               boost::optional<boost::filesystem::path> extra;
                                if (reel->main_subtitle()) {
-                                       auto interop = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(reel->main_subtitle()->asset());
-                                       if (interop) {
-                                               extra = interop->id();
-                                               for (auto font_asset: interop->font_assets()) {
-                                                       maybe_copy(font_asset->id(), rename, hard_link, soft_link, extra);
-                                               }
-                                       }
+                                       auto extra = maybe_copy_font(reel->main_subtitle()->asset(), rename, hard_link, soft_link);
+                                       maybe_copy_from_reel(reel->main_subtitle(), rename, hard_link, soft_link, extra);
                                }
-                               maybe_copy_from_reel(reel->main_subtitle(), rename, hard_link, soft_link, extra);
                                for (auto ccap: reel->closed_captions()) {
-                                       maybe_copy_from_reel(ccap, rename, hard_link, soft_link);
+                                       auto extra = maybe_copy_font(ccap->asset(), rename, hard_link, soft_link);
+                                       maybe_copy_from_reel(ccap, rename, hard_link, soft_link, extra);
                                }
                                maybe_copy_from_reel(reel->atmos(), rename, hard_link, soft_link);
                        }
@@ -290,7 +304,11 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
 
        dcp.resolve_refs(assets);
        dcp.set_annotation_text(cpls[0]->annotation_text().get_value_or(""));
-       dcp.write_xml(Config::instance()->signer_chain());
+       try {
+               dcp.write_xml(Config::instance()->signer_chain());
+       } catch (dcp::UnresolvedRefError& e) {
+               return String::compose("%1\nPerhaps you need to give a -d parameter to say where this asset is located.", e.what());
+       }
 
        return {};
 }