Add wrappers around boost::filesystem methods that handle the
[libdcp.git] / src / combine.cc
index 65cd3d0b6453afc628b0176c36f1decfdad2e3c4..b7a625f089df8e236722da76e7cad5f8f37d3a3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of libdcp.
 
 */
 
 
+/** @file  src/combine.cc
+ *  @brief Method to combine DCPs
+ */
+
+
 #include "asset.h"
 #include "combine.h"
 #include "cpl.h"
 #include "dcp.h"
 #include "dcp_assert.h"
 #include "exceptions.h"
+#include "filesystem.h"
 #include "font_asset.h"
 #include "interop_subtitle_asset.h"
 #include "raw_convert.h"
 #include <boost/filesystem.hpp>
-#include <boost/foreach.hpp>
 #include <set>
 #include <string>
 #include <vector>
 
 
-using std::list;
+using std::dynamic_pointer_cast;
 using std::map;
 using std::set;
+using std::shared_ptr;
 using std::string;
 using std::vector;
-using boost::dynamic_pointer_cast;
 using boost::optional;
-using boost::shared_ptr;
 
 
 boost::filesystem::path
 make_unique (boost::filesystem::path path)
 {
-       if (!boost::filesystem::exists(path)) {
+       if (!dcp::filesystem::exists(path)) {
                return path;
        }
 
        for (int i = 0; i < 10000; ++i) {
                boost::filesystem::path p = path.parent_path() / (path.stem().string() + dcp::raw_convert<string>(i) + path.extension().string());
-               if (!boost::filesystem::exists(p)) {
+               if (!dcp::filesystem::exists(p)) {
                        return p;
                }
        }
@@ -82,10 +86,10 @@ void
 create_hard_link_or_copy (boost::filesystem::path from, boost::filesystem::path to)
 {
        try {
-               create_hard_link (from, to);
+               dcp::filesystem::create_hard_link(from, to);
        } catch (boost::filesystem::filesystem_error& e) {
                if (e.code() == boost::system::errc::cross_device_link) {
-                       copy_file (from, to);
+                       dcp::filesystem::copy_file(from, to);
                } else {
                        throw;
                }
@@ -104,14 +108,12 @@ dcp::combine (
        shared_ptr<const CertificateChain> signer
        )
 {
-       using namespace boost::filesystem;
-
        DCP_ASSERT (!inputs.empty());
 
        DCP output_dcp (output);
        optional<dcp::Standard> standard;
 
-       BOOST_FOREACH (path i, inputs) {
+       for (auto i: inputs) {
                DCP dcp (i);
                dcp.read ();
                if (!standard) {
@@ -121,47 +123,38 @@ dcp::combine (
                }
        }
 
-       list<path> paths;
-       list<shared_ptr<dcp::Asset> > assets;
+       vector<boost::filesystem::path> paths;
+       vector<shared_ptr<dcp::Asset>> assets;
 
-       BOOST_FOREACH (path i, inputs) {
+       for (auto i: inputs) {
                DCP dcp (i);
                dcp.read ();
 
-               BOOST_FOREACH (shared_ptr<dcp::CPL> j, dcp.cpls()) {
+               for (auto j: dcp.cpls()) {
                        output_dcp.add (j);
                }
 
-               BOOST_FOREACH (shared_ptr<dcp::Asset> j, dcp.assets(true)) {
+               for (auto j: dcp.assets(true)) {
                        if (dynamic_pointer_cast<dcp::CPL>(j)) {
                                continue;
                        }
 
-                       optional<path> file = j->file();
-                       DCP_ASSERT (file);
-                       path new_path = make_unique(output / file->filename());
-
-                       shared_ptr<dcp::InteropSubtitleAsset> sub = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(j);
+                       auto sub = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(j);
                        if (sub) {
                                /* Interop fonts are really fiddly.  The font files are assets (in the ASSETMAP)
                                 * and also linked from the font XML by filename.  We have to fix both these things,
                                 * and re-write the font XML file since the font URI might have changed if it's a duplicate
                                 * with another DCP.
                                 */
-                               map<string, path> fonts = sub->font_filenames ();
-                               for (map<string, path>::const_iterator k = fonts.begin(); k != fonts.end(); ++k) {
-                                       sub->set_font_file (k->first, make_unique(output / k->second.filename()));
+                               auto fonts = sub->font_filenames ();
+                               for (auto const& k: fonts) {
+                                       sub->set_font_file (k.first, make_unique(output / k.second.filename()));
                                }
-                               sub->write (new_path);
-                       } else if (!dynamic_pointer_cast<dcp::FontAsset>(j)) {
-                               /* Take care of everything else that's not a Interop subtitle asset, Interop font file
-                                * or CPL.
-                                */
-                               optional<path> file = j->file();
+                               auto file = sub->file();
                                DCP_ASSERT (file);
-                               path new_path = make_unique(output / file->filename());
-                               create_hard_link_or_copy (*file, new_path);
-                               j->set_file (new_path);
+                               auto new_path = make_unique(output / file->filename());
+                               sub->write (new_path);
+                               add_to_container(assets, sub->font_assets());
                        }
 
                        assets.push_back (j);
@@ -169,5 +162,21 @@ dcp::combine (
        }
 
        output_dcp.resolve_refs (assets);
-       output_dcp.write_xml (*standard, issuer, creator, issue_date, annotation_text, signer);
+
+       for (auto i: output_dcp.assets()) {
+               if (!dynamic_pointer_cast<dcp::FontAsset>(i) && !dynamic_pointer_cast<dcp::CPL>(i)) {
+                       auto file = i->file();
+                       DCP_ASSERT (file);
+                       auto new_path = make_unique(output / file->filename());
+                       create_hard_link_or_copy (*file, new_path);
+                       i->set_file (new_path);
+               }
+       }
+
+       output_dcp.set_issuer(issuer);
+       output_dcp.set_creator(creator);
+       output_dcp.set_issue_date(issue_date);
+       output_dcp.set_annotation_text(annotation_text);
+
+       output_dcp.write_xml(signer);
 }