Emit no audio from DCPs if none is mapped
[dcpomatic.git] / src / lib / map_cli.cc
index 368c3572554a6df81db67f5acbeef96d93b8b974..b158499a8d204628a87ddeb275d102d5f9556242 100644 (file)
@@ -56,7 +56,7 @@ using boost::optional;
 static void
 help(std::function<void (string)> out)
 {
-       out(String::compose("Syntax: %1 [OPTION} <cpl-file> [<cpl-file> ... ]", program_name));
+       out(String::compose("Syntax: %1 [OPTION} <cpl-file|ID> [<cpl-file|ID> ... ]", program_name));
        out("  -V, --version    show libdcp version");
        out("  -h, --help       show this help");
        out("  -o, --output     output directory");
@@ -138,12 +138,12 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                State::override_path = *config_dir;
        }
 
-       vector<boost::filesystem::path> cpl_filenames;
+       vector<string> cpl_filenames_or_ids;
        for (int i = optind; i < argc; ++i) {
-               cpl_filenames.push_back(argv[i]);
+               cpl_filenames_or_ids.push_back(argv[i]);
        }
 
-       if (cpl_filenames.empty()) {
+       if (cpl_filenames_or_ids.empty()) {
                return string{"No CPL specified."};
        }
 
@@ -181,13 +181,28 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
 
        /* Find all the CPLs */
        vector<shared_ptr<dcp::CPL>> cpls;
-       for (auto filename: cpl_filenames) {
-               try {
-                       auto cpl = make_shared<dcp::CPL>(filename);
-                       cpl->resolve_refs(assets);
-                       cpls.push_back(cpl);
-               } catch (std::exception& e) {
-                       return String::compose("Could not read CPL %1: %2", filename, e.what());
+       for (auto filename_or_id: cpl_filenames_or_ids) {
+               if (boost::filesystem::exists(filename_or_id)) {
+                       try {
+                               auto cpl = make_shared<dcp::CPL>(filename_or_id);
+                               cpl->resolve_refs(assets);
+                               cpls.push_back(cpl);
+                       } catch (std::exception& e) {
+                               return String::compose("Could not read CPL %1: %2", filename_or_id, e.what());
+                       }
+               } else {
+                       auto cpl_iter = std::find_if(assets.begin(), assets.end(), [filename_or_id](shared_ptr<dcp::Asset> asset) {
+                               return asset->id() == filename_or_id;
+                       });
+                       if (cpl_iter == assets.end()) {
+                               return String::compose("Could not find CPL with ID %1", filename_or_id);
+                       }
+                       if (auto cpl = dynamic_pointer_cast<dcp::CPL>(*cpl_iter)) {
+                               cpl->resolve_refs(assets);
+                               cpls.push_back(cpl);
+                       } else {
+                               return String::compose("Could not find CPL with ID %1", filename_or_id);
+                       }
                }
        }
 
@@ -199,7 +214,34 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
 
        vector<string> already_copied;
 
-       auto maybe_copy = [&assets, &already_copied, output_dir](
+       auto copy = [](
+               boost::filesystem::path input_path,
+               boost::filesystem::path output_path,
+               bool hard_link,
+               bool soft_link
+               ) {
+               dcp::filesystem::create_directories(output_path.parent_path());
+
+               boost::system::error_code ec;
+               if (hard_link) {
+                       dcp::filesystem::create_hard_link(input_path, output_path, ec);
+                       if (ec) {
+                               throw CopyError(String::compose("Could not hard-link asset %1: %2", input_path.string(), ec.message()));
+                       }
+               } else if (soft_link) {
+                       dcp::filesystem::create_symlink(input_path, output_path, ec);
+                       if (ec) {
+                               throw CopyError(String::compose("Could not soft-link asset %1: %2", input_path.string(), ec.message()));
+                       }
+               } else {
+                       dcp::filesystem::copy_file(input_path, output_path, ec);
+                       if (ec) {
+                               throw CopyError(String::compose("Could not copy asset %1: %2", input_path.string(), ec.message()));
+                       }
+               }
+       };
+
+       auto maybe_copy = [&assets, &already_copied, output_dir, copy](
                string asset_id,
                bool rename,
                bool hard_link,
@@ -228,25 +270,7 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                                output_path /= (*iter)->file()->filename();
                        }
 
-                       dcp::filesystem::create_directories(output_path.parent_path());
-
-                       boost::system::error_code ec;
-                       if (hard_link) {
-                               dcp::filesystem::create_hard_link(input_path, output_path, ec);
-                               if (ec) {
-                                       throw CopyError(String::compose("Could not hard-link asset %1: %2", input_path.string(), ec.message()));
-                               }
-                       } else if (soft_link) {
-                               dcp::filesystem::create_symlink(input_path, output_path, ec);
-                               if (ec) {
-                                       throw CopyError(String::compose("Could not soft-link asset %1: %2", input_path.string(), ec.message()));
-                               }
-                       } else {
-                               dcp::filesystem::copy_file(input_path, output_path, ec);
-                               if (ec) {
-                                       throw CopyError(String::compose("Could not copy asset %1: %2", input_path.string(), ec.message()));
-                               }
-                       }
+                       copy(input_path, output_path, hard_link, soft_link);
                        (*iter)->set_file_preserving_hash(output_path);
                        already_copied.push_back(asset_id);
                } else {
@@ -268,7 +292,7 @@ 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 maybe_copy_font_and_images = [&maybe_copy, output_dir, 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) {
@@ -276,6 +300,12 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                        for (auto font_asset: interop->font_assets()) {
                                maybe_copy(font_asset->id(), rename, hard_link, soft_link, extra);
                        }
+                       for (auto subtitle: interop->subtitles()) {
+                               if (auto image = dynamic_pointer_cast<const dcp::SubtitleImage>(subtitle)) {
+                                       auto const output_path = *output_dir / asset->id() / image->file()->filename();
+                                       copy(*image->file(), output_path, hard_link, soft_link);
+                               }
+                       }
                }
                return extra;
        };
@@ -287,11 +317,11 @@ map_cli(int argc, char* argv[], std::function<void (string)> out)
                                maybe_copy_from_reel(reel->main_picture(), rename, hard_link, soft_link);
                                maybe_copy_from_reel(reel->main_sound(), rename, hard_link, soft_link);
                                if (reel->main_subtitle()) {
-                                       auto extra = maybe_copy_font(reel->main_subtitle()->asset(), rename, hard_link, soft_link);
+                                       auto extra = maybe_copy_font_and_images(reel->main_subtitle()->asset(), rename, hard_link, soft_link);
                                        maybe_copy_from_reel(reel->main_subtitle(), rename, hard_link, soft_link, extra);
                                }
                                for (auto ccap: reel->closed_captions()) {
-                                       auto extra = maybe_copy_font(ccap->asset(), rename, hard_link, soft_link);
+                                       auto extra = maybe_copy_font_and_images(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);