Add some debugging for KDM generation from imported encrypted DCPs.
[dcpomatic.git] / src / lib / film.cc
1 /*
2     Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /** @file  src/film.cc
22  *  @brief A representation of some audio and video content, and details of
23  *  how they should be presented in a DCP.
24  */
25
26 #include "film.h"
27 #include "job.h"
28 #include "util.h"
29 #include "job_manager.h"
30 #include "transcode_job.h"
31 #include "upload_job.h"
32 #include "null_log.h"
33 #include "file_log.h"
34 #include "exceptions.h"
35 #include "examine_content_job.h"
36 #include "config.h"
37 #include "playlist.h"
38 #include "dcp_content_type.h"
39 #include "ratio.h"
40 #include "cross.h"
41 #include "environment_info.h"
42 #include "audio_processor.h"
43 #include "digester.h"
44 #include "compose.hpp"
45 #include "screen.h"
46 #include "audio_content.h"
47 #include "video_content.h"
48 #include "subtitle_content.h"
49 #include "ffmpeg_content.h"
50 #include "dcp_content.h"
51 #include "screen_kdm.h"
52 #include "cinema.h"
53 #include <libcxml/cxml.h>
54 #include <dcp/cpl.h>
55 #include <dcp/certificate_chain.h>
56 #include <dcp/util.h>
57 #include <dcp/local_time.h>
58 #include <dcp/decrypted_kdm.h>
59 #include <dcp/raw_convert.h>
60 #include <dcp/reel_mxf.h>
61 #include <dcp/reel_asset.h>
62 #include <libxml++/libxml++.h>
63 #include <boost/filesystem.hpp>
64 #include <boost/algorithm/string.hpp>
65 #include <boost/foreach.hpp>
66 #include <boost/regex.hpp>
67 #include <unistd.h>
68 #include <stdexcept>
69 #include <iostream>
70 #include <algorithm>
71 #include <cstdlib>
72 #include <iomanip>
73 #include <set>
74
75 #include "i18n.h"
76
77 using std::string;
78 using std::pair;
79 using std::vector;
80 using std::setfill;
81 using std::min;
82 using std::max;
83 using std::make_pair;
84 using std::cout;
85 using std::list;
86 using std::set;
87 using std::runtime_error;
88 using std::copy;
89 using std::back_inserter;
90 using std::map;
91 using boost::shared_ptr;
92 using boost::weak_ptr;
93 using boost::dynamic_pointer_cast;
94 using boost::optional;
95 using boost::is_any_of;
96 using dcp::raw_convert;
97
98 #define LOG_GENERAL(...) log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
99 #define LOG_GENERAL_NC(...) log()->log (__VA_ARGS__, LogEntry::TYPE_GENERAL);
100
101 /* 5 -> 6
102  * AudioMapping XML changed.
103  * 6 -> 7
104  * Subtitle offset changed to subtitle y offset, and subtitle x offset added.
105  * 7 -> 8
106  * Use <Scale> tag in <VideoContent> rather than <Ratio>.
107  * 8 -> 9
108  * DCI -> ISDCF
109  * 9 -> 10
110  * Subtitle X and Y scale.
111  *
112  * Bumped to 32 for 2.0 branch; some times are expressed in Times rather
113  * than frames now.
114  *
115  * 32 -> 33
116  * Changed <Period> to <Subtitle> in FFmpegSubtitleStream
117  * 33 -> 34
118  * Content only contains audio/subtitle-related tags if those things
119  * are present.
120  * 34 -> 35
121  * VideoFrameType in VideoContent is a string rather than an integer.
122  * 35 -> 36
123  * EffectColour rather than OutlineColour in Subtitle.
124  */
125 int const Film::current_state_version = 36;
126
127 /** Construct a Film object in a given directory.
128  *
129  *  @param dir Film directory.
130  */
131
132 Film::Film (optional<boost::filesystem::path> dir)
133         : _playlist (new Playlist)
134         , _use_isdcf_name (true)
135         , _dcp_content_type (Config::instance()->default_dcp_content_type ())
136         , _container (Config::instance()->default_container ())
137         , _resolution (RESOLUTION_2K)
138         , _signed (true)
139         , _encrypted (false)
140         , _context_id (dcp::make_uuid ())
141         , _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ())
142         , _isdcf_metadata (Config::instance()->default_isdcf_metadata ())
143         , _video_frame_rate (24)
144         , _audio_channels (Config::instance()->default_dcp_audio_channels ())
145         , _three_d (false)
146         , _sequence (true)
147         , _interop (Config::instance()->default_interop ())
148         , _audio_processor (0)
149         , _reel_type (REELTYPE_SINGLE)
150         , _reel_length (2000000000)
151         , _upload_after_make_dcp (false)
152         , _state_version (current_state_version)
153         , _dirty (false)
154 {
155         set_isdcf_date_today ();
156
157         _playlist_changed_connection = _playlist->Changed.connect (bind (&Film::playlist_changed, this));
158         _playlist_order_changed_connection = _playlist->OrderChanged.connect (bind (&Film::playlist_order_changed, this));
159         _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2, _3));
160
161         if (dir) {
162                 /* Make state.directory a complete path without ..s (where possible)
163                    (Code swiped from Adam Bowen on stackoverflow)
164                    XXX: couldn't/shouldn't this just be boost::filesystem::canonical?
165                 */
166
167                 boost::filesystem::path p (boost::filesystem::system_complete (dir.get()));
168                 boost::filesystem::path result;
169                 for (boost::filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
170                         if (*i == "..") {
171                                 if (boost::filesystem::is_symlink (result) || result.filename() == "..") {
172                                         result /= *i;
173                                 } else {
174                                         result = result.parent_path ();
175                                 }
176                         } else if (*i != ".") {
177                                 result /= *i;
178                         }
179                 }
180
181                 set_directory (result.make_preferred ());
182         }
183
184         if (_directory) {
185                 _log.reset (new FileLog (file ("log")));
186         } else {
187                 _log.reset (new NullLog);
188         }
189
190         _playlist->set_sequence (_sequence);
191 }
192
193 Film::~Film ()
194 {
195         BOOST_FOREACH (boost::signals2::connection& i, _job_connections) {
196                 i.disconnect ();
197         }
198
199         BOOST_FOREACH (boost::signals2::connection& i, _audio_analysis_connections) {
200                 i.disconnect ();
201         }
202 }
203
204 string
205 Film::video_identifier () const
206 {
207         DCPOMATIC_ASSERT (container ());
208
209         string s = container()->id()
210                 + "_" + resolution_to_string (_resolution)
211                 + "_" + _playlist->video_identifier()
212                 + "_" + raw_convert<string>(_video_frame_rate)
213                 + "_" + raw_convert<string>(j2k_bandwidth());
214
215         if (encrypted ()) {
216                 s += "_E";
217         } else {
218                 s += "_P";
219         }
220
221         if (_interop) {
222                 s += "_I";
223         } else {
224                 s += "_S";
225         }
226
227         if (_three_d) {
228                 s += "_3D";
229         }
230
231         return s;
232 }
233
234 /** @return The file to write video frame info to */
235 boost::filesystem::path
236 Film::info_file (DCPTimePeriod period) const
237 {
238         boost::filesystem::path p;
239         p /= "info";
240         p /= video_identifier () + "_" + raw_convert<string> (period.from.get()) + "_" + raw_convert<string> (period.to.get());
241         return file (p);
242 }
243
244 boost::filesystem::path
245 Film::internal_video_asset_dir () const
246 {
247         return dir ("video");
248 }
249
250 boost::filesystem::path
251 Film::internal_video_asset_filename (DCPTimePeriod p) const
252 {
253         return video_identifier() + "_" + raw_convert<string> (p.from.get()) + "_" + raw_convert<string> (p.to.get()) + ".mxf";
254 }
255
256 boost::filesystem::path
257 Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
258 {
259         boost::filesystem::path p = dir ("analysis");
260
261         Digester digester;
262         BOOST_FOREACH (shared_ptr<Content> i, playlist->content ()) {
263                 if (!i->audio) {
264                         continue;
265                 }
266
267                 digester.add (i->digest ());
268                 digester.add (i->audio->mapping().digest ());
269                 if (playlist->content().size() != 1) {
270                         /* Analyses should be considered equal regardless of gain
271                            if they were made from just one piece of content.  This
272                            is because we can fake any gain change in a single-content
273                            analysis at the plotting stage rather than having to
274                            recompute it.
275                         */
276                         digester.add (i->audio->gain ());
277                 }
278         }
279
280         if (audio_processor ()) {
281                 digester.add (audio_processor()->id ());
282         }
283
284         p /= digester.get ();
285         return p;
286 }
287
288 /** Add suitable Jobs to the JobManager to create a DCP for this Film */
289 void
290 Film::make_dcp ()
291 {
292         if (dcp_name().find ("/") != string::npos) {
293                 throw BadSettingError (_("name"), _("cannot contain slashes"));
294         }
295
296         if (container() == 0) {
297                 throw MissingSettingError (_("container"));
298         }
299
300         if (content().empty()) {
301                 throw runtime_error (_("you must add some content to the DCP before creating it"));
302         }
303
304         if (dcp_content_type() == 0) {
305                 throw MissingSettingError (_("content type"));
306         }
307
308         if (name().empty()) {
309                 throw MissingSettingError (_("name"));
310         }
311
312         BOOST_FOREACH (shared_ptr<const Content> i, content ()) {
313                 if (!i->paths_valid()) {
314                         throw runtime_error (_("some of your content is missing"));
315                 }
316                 shared_ptr<const DCPContent> dcp = dynamic_pointer_cast<const DCPContent> (i);
317                 if (dcp && dcp->needs_kdm()) {
318                         throw runtime_error (_("some of your content needs a KDM"));
319                 }
320                 if (dcp && dcp->needs_assets()) {
321                         throw runtime_error (_("some of your content needs an OV"));
322                 }
323         }
324
325         set_isdcf_date_today ();
326
327         BOOST_FOREACH (string i, environment_info ()) {
328                 LOG_GENERAL_NC (i);
329         }
330
331         BOOST_FOREACH (shared_ptr<const Content> i, content ()) {
332                 LOG_GENERAL ("Content: %1", i->technical_summary());
333         }
334         LOG_GENERAL ("DCP video rate %1 fps", video_frame_rate());
335         if (Config::instance()->only_servers_encode ()) {
336                 LOG_GENERAL_NC ("0 threads: ONLY SERVERS SET TO ENCODE");
337         } else {
338                 LOG_GENERAL ("%1 threads", Config::instance()->num_local_encoding_threads());
339         }
340         LOG_GENERAL ("J2K bandwidth %1", j2k_bandwidth());
341
342         JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this())));
343 }
344
345 /** Start a job to send our DCP to the configured TMS */
346 void
347 Film::send_dcp_to_tms ()
348 {
349         shared_ptr<Job> j (new UploadJob (shared_from_this()));
350         JobManager::instance()->add (j);
351 }
352
353 shared_ptr<xmlpp::Document>
354 Film::metadata (bool with_content_paths) const
355 {
356         shared_ptr<xmlpp::Document> doc (new xmlpp::Document);
357         xmlpp::Element* root = doc->create_root_node ("Metadata");
358
359         root->add_child("Version")->add_child_text (raw_convert<string> (current_state_version));
360         root->add_child("Name")->add_child_text (_name);
361         root->add_child("UseISDCFName")->add_child_text (_use_isdcf_name ? "1" : "0");
362
363         if (_dcp_content_type) {
364                 root->add_child("DCPContentType")->add_child_text (_dcp_content_type->isdcf_name ());
365         }
366
367         if (_container) {
368                 root->add_child("Container")->add_child_text (_container->id ());
369         }
370
371         root->add_child("Resolution")->add_child_text (resolution_to_string (_resolution));
372         root->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
373         _isdcf_metadata.as_xml (root->add_child ("ISDCFMetadata"));
374         root->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate));
375         root->add_child("ISDCFDate")->add_child_text (boost::gregorian::to_iso_string (_isdcf_date));
376         root->add_child("AudioChannels")->add_child_text (raw_convert<string> (_audio_channels));
377         root->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0");
378         root->add_child("Sequence")->add_child_text (_sequence ? "1" : "0");
379         root->add_child("Interop")->add_child_text (_interop ? "1" : "0");
380         root->add_child("Signed")->add_child_text (_signed ? "1" : "0");
381         root->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0");
382         root->add_child("Key")->add_child_text (_key.hex ());
383         root->add_child("ContextID")->add_child_text (_context_id);
384         if (_audio_processor) {
385                 root->add_child("AudioProcessor")->add_child_text (_audio_processor->id ());
386         }
387         root->add_child("ReelType")->add_child_text (raw_convert<string> (static_cast<int> (_reel_type)));
388         root->add_child("ReelLength")->add_child_text (raw_convert<string> (_reel_length));
389         root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0");
390         _playlist->as_xml (root->add_child ("Playlist"), with_content_paths);
391
392         return doc;
393 }
394
395 /** Write state to our `metadata' file */
396 void
397 Film::write_metadata () const
398 {
399         DCPOMATIC_ASSERT (directory());
400         boost::filesystem::create_directories (directory().get());
401         shared_ptr<xmlpp::Document> doc = metadata ();
402         doc->write_to_file_formatted (file("metadata.xml").string ());
403         _dirty = false;
404 }
405
406 /** Write a template from this film */
407 void
408 Film::write_template (boost::filesystem::path path) const
409 {
410         boost::filesystem::create_directories (path.parent_path());
411         shared_ptr<xmlpp::Document> doc = metadata (false);
412         doc->write_to_file_formatted (path.string ());
413 }
414
415 /** Read state from our metadata file.
416  *  @return Notes about things that the user should know about, or empty.
417  */
418 list<string>
419 Film::read_metadata (optional<boost::filesystem::path> path)
420 {
421         if (!path) {
422                 if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file ("metadata.xml"))) {
423                         throw runtime_error (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version.  You will need to create a new Film, re-add your content and set it up again.  Sorry!"));
424                 }
425
426                 path = file ("metadata.xml");
427         }
428
429         cxml::Document f ("Metadata");
430         f.read_file (path.get ());
431
432         _state_version = f.number_child<int> ("Version");
433         if (_state_version > current_state_version) {
434                 throw runtime_error (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version.  Sorry!"));
435         }
436
437         _name = f.string_child ("Name");
438         if (_state_version >= 9) {
439                 _use_isdcf_name = f.bool_child ("UseISDCFName");
440                 _isdcf_metadata = ISDCFMetadata (f.node_child ("ISDCFMetadata"));
441                 _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("ISDCFDate"));
442         } else {
443                 _use_isdcf_name = f.bool_child ("UseDCIName");
444                 _isdcf_metadata = ISDCFMetadata (f.node_child ("DCIMetadata"));
445                 _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
446         }
447
448         {
449                 optional<string> c = f.optional_string_child ("DCPContentType");
450                 if (c) {
451                         _dcp_content_type = DCPContentType::from_isdcf_name (c.get ());
452                 }
453         }
454
455         {
456                 optional<string> c = f.optional_string_child ("Container");
457                 if (c) {
458                         _container = Ratio::from_id (c.get ());
459                 }
460         }
461
462         _resolution = string_to_resolution (f.string_child ("Resolution"));
463         _j2k_bandwidth = f.number_child<int> ("J2KBandwidth");
464         _video_frame_rate = f.number_child<int> ("VideoFrameRate");
465         _signed = f.optional_bool_child("Signed").get_value_or (true);
466         _encrypted = f.bool_child ("Encrypted");
467         _audio_channels = f.number_child<int> ("AudioChannels");
468         /* We used to allow odd numbers (and zero) channels, but it's just not worth
469            the pain.
470         */
471         if (_audio_channels == 0) {
472                 _audio_channels = 2;
473         } else if ((_audio_channels % 2) == 1) {
474                 _audio_channels++;
475         }
476
477         if (f.optional_bool_child("SequenceVideo")) {
478                 _sequence = f.bool_child("SequenceVideo");
479         } else {
480                 _sequence = f.bool_child("Sequence");
481         }
482
483         _three_d = f.bool_child ("ThreeD");
484         _interop = f.bool_child ("Interop");
485         _key = dcp::Key (f.string_child ("Key"));
486         _context_id = f.optional_string_child("ContextID").get_value_or (dcp::make_uuid ());
487
488         if (f.optional_string_child ("AudioProcessor")) {
489                 _audio_processor = AudioProcessor::from_id (f.string_child ("AudioProcessor"));
490         } else {
491                 _audio_processor = 0;
492         }
493
494         _reel_type = static_cast<ReelType> (f.optional_number_child<int>("ReelType").get_value_or (static_cast<int>(REELTYPE_SINGLE)));
495         _reel_length = f.optional_number_child<int64_t>("ReelLength").get_value_or (2000000000);
496         _upload_after_make_dcp = f.optional_bool_child("UploadAfterMakeDCP").get_value_or (false);
497
498         list<string> notes;
499         /* This method is the only one that can return notes (so far) */
500         _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
501
502         /* Write backtraces to this film's directory, until another film is loaded */
503         if (_directory) {
504                 set_backtrace_file (file ("backtrace.txt"));
505         }
506
507         _dirty = false;
508         return notes;
509 }
510
511 /** Given a directory name, return its full path within the Film's directory.
512  *  The directory (and its parents) will be created if they do not exist.
513  */
514 boost::filesystem::path
515 Film::dir (boost::filesystem::path d) const
516 {
517         DCPOMATIC_ASSERT (_directory);
518
519         boost::filesystem::path p;
520         p /= _directory.get();
521         p /= d;
522
523         boost::filesystem::create_directories (p);
524
525         return p;
526 }
527
528 /** Given a file or directory name, return its full path within the Film's directory.
529  *  Any required parent directories will be created.
530  */
531 boost::filesystem::path
532 Film::file (boost::filesystem::path f) const
533 {
534         DCPOMATIC_ASSERT (_directory);
535
536         boost::filesystem::path p;
537         p /= _directory.get();
538         p /= f;
539
540         boost::filesystem::create_directories (p.parent_path ());
541
542         return p;
543 }
544
545 list<int>
546 Film::mapped_audio_channels () const
547 {
548         list<int> mapped;
549
550         if (audio_processor ()) {
551                 /* Processors are mapped 1:1 to DCP outputs so we can work out mappings from there */
552                 for (int i = 0; i < audio_processor()->out_channels(); ++i) {
553                         mapped.push_back (i);
554                 }
555         } else {
556                 BOOST_FOREACH (shared_ptr<Content> i, content ()) {
557                         if (i->audio) {
558                                 list<int> c = i->audio->mapping().mapped_output_channels ();
559                                 copy (c.begin(), c.end(), back_inserter (mapped));
560                         }
561                 }
562
563                 mapped.sort ();
564                 mapped.unique ();
565         }
566
567         return mapped;
568 }
569
570 /** @return a ISDCF-compliant name for a DCP of this film */
571 string
572 Film::isdcf_name (bool if_created_now) const
573 {
574         string d;
575
576         string raw_name = name ();
577
578         /* Split the raw name up into words */
579         vector<string> words;
580         split (words, raw_name, is_any_of (" _-"));
581
582         string fixed_name;
583
584         /* Add each word to fixed_name */
585         for (vector<string>::const_iterator i = words.begin(); i != words.end(); ++i) {
586                 string w = *i;
587
588                 /* First letter is always capitalised */
589                 w[0] = toupper (w[0]);
590
591                 /* Count caps in w */
592                 size_t caps = 0;
593                 for (size_t i = 0; i < w.size(); ++i) {
594                         if (isupper (w[i])) {
595                                 ++caps;
596                         }
597                 }
598
599                 /* If w is all caps make the rest of it lower case, otherwise
600                    leave it alone.
601                 */
602                 if (caps == w.size ()) {
603                         for (size_t i = 1; i < w.size(); ++i) {
604                                 w[i] = tolower (w[i]);
605                         }
606                 }
607
608                 for (size_t i = 0; i < w.size(); ++i) {
609                         fixed_name += w[i];
610                 }
611         }
612
613         if (fixed_name.length() > 14) {
614                 fixed_name = fixed_name.substr (0, 14);
615         }
616
617         d += fixed_name;
618
619         if (dcp_content_type()) {
620                 d += "_" + dcp_content_type()->isdcf_name();
621                 d += "-" + raw_convert<string>(isdcf_metadata().content_version);
622         }
623
624         ISDCFMetadata const dm = isdcf_metadata ();
625
626         if (dm.temp_version) {
627                 d += "-Temp";
628         }
629
630         if (dm.pre_release) {
631                 d += "-Pre";
632         }
633
634         if (dm.red_band) {
635                 d += "-RedBand";
636         }
637
638         if (!dm.chain.empty ()) {
639                 d += "-" + dm.chain;
640         }
641
642         if (three_d ()) {
643                 d += "-3D";
644         }
645
646         if (dm.two_d_version_of_three_d) {
647                 d += "-2D";
648         }
649
650         if (!dm.mastered_luminance.empty ()) {
651                 d += "-" + dm.mastered_luminance;
652         }
653
654         if (video_frame_rate() != 24) {
655                 d += "-" + raw_convert<string>(video_frame_rate());
656         }
657
658         if (container()) {
659                 d += "_" + container()->isdcf_name();
660         }
661
662         /* XXX: this uses the first bit of content only */
663
664         /* The standard says we don't do this for trailers, for some strange reason */
665         if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::TRAILER) {
666                 Ratio const * content_ratio = 0;
667                 BOOST_FOREACH (shared_ptr<Content> i, content ()) {
668                         if (i->video) {
669                                 /* Here's the first piece of video content */
670                                 if (i->video->scale().ratio ()) {
671                                         content_ratio = i->video->scale().ratio ();
672                                 } else {
673                                         content_ratio = Ratio::from_ratio (i->video->size().ratio ());
674                                 }
675                                 break;
676                         }
677                 }
678
679                 if (content_ratio && content_ratio != container()) {
680                         d += "-" + content_ratio->isdcf_name();
681                 }
682         }
683
684         if (!dm.audio_language.empty ()) {
685                 d += "_" + dm.audio_language;
686                 if (!dm.subtitle_language.empty()) {
687
688                         bool burnt_in = true;
689                         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
690                                 if (!i->subtitle) {
691                                         continue;
692                                 }
693
694                                 if (i->subtitle->use() && !i->subtitle->burn()) {
695                                         burnt_in = false;
696                                 }
697                         }
698
699                         string language = dm.subtitle_language;
700                         if (burnt_in && language != "XX") {
701                                 transform (language.begin(), language.end(), language.begin(), ::tolower);
702                         } else {
703                                 transform (language.begin(), language.end(), language.begin(), ::toupper);
704                         }
705
706                         d += "-" + language;
707                 } else {
708                         d += "-XX";
709                 }
710         }
711
712         if (!dm.territory.empty ()) {
713                 d += "_" + dm.territory;
714                 if (dm.rating.empty ()) {
715                         d += "-NR";
716                 } else {
717                         d += "-" + dm.rating;
718                 }
719         }
720
721         /* Count mapped audio channels */
722
723         int non_lfe = 0;
724         int lfe = 0;
725
726         BOOST_FOREACH (int i, mapped_audio_channels ()) {
727                 if (i >= audio_channels()) {
728                         /* This channel is mapped but is not included in the DCP */
729                         continue;
730                 }
731
732                 if (static_cast<dcp::Channel> (i) == dcp::LFE) {
733                         ++lfe;
734                 } else {
735                         ++non_lfe;
736                 }
737         }
738
739         if (non_lfe) {
740                 d += String::compose("_%1%2", non_lfe, lfe);
741         }
742
743         /* XXX: HI/VI */
744
745         d += "_" + resolution_to_string (_resolution);
746
747         if (!dm.studio.empty ()) {
748                 d += "_" + dm.studio;
749         }
750
751         if (if_created_now) {
752                 d += "_" + boost::gregorian::to_iso_string (boost::gregorian::day_clock::local_day ());
753         } else {
754                 d += "_" + boost::gregorian::to_iso_string (_isdcf_date);
755         }
756
757         if (!dm.facility.empty ()) {
758                 d += "_" + dm.facility;
759         }
760
761         if (_interop) {
762                 d += "_IOP";
763         } else {
764                 d += "_SMPTE";
765         }
766
767         if (three_d ()) {
768                 d += "-3D";
769         }
770
771         bool vf = false;
772         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
773                 shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
774                 if (dc && (dc->reference_video() || dc->reference_audio() || dc->reference_subtitle())) {
775                         vf = true;
776                 }
777         }
778
779         if (vf) {
780                 d += "_VF";
781         } else {
782                 d += "_OV";
783         }
784
785         return d;
786 }
787
788 /** @return name to give the DCP */
789 string
790 Film::dcp_name (bool if_created_now) const
791 {
792         string unfiltered;
793         if (use_isdcf_name()) {
794                 unfiltered = isdcf_name (if_created_now);
795         } else {
796                 unfiltered = name ();
797         }
798
799         /* Filter out `bad' characters which cause problems with some systems.
800            There's no apparent list of what really is allowed, so this is a guess.
801         */
802
803         string filtered;
804         string const allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
805         for (size_t i = 0; i < unfiltered.size(); ++i) {
806                 if (allowed.find (unfiltered[i]) != string::npos) {
807                         filtered += unfiltered[i];
808                 }
809         }
810
811         return filtered;
812 }
813
814 void
815 Film::set_directory (boost::filesystem::path d)
816 {
817         _directory = d;
818         _dirty = true;
819 }
820
821 void
822 Film::set_name (string n)
823 {
824         _name = n;
825         signal_changed (NAME);
826 }
827
828 void
829 Film::set_use_isdcf_name (bool u)
830 {
831         _use_isdcf_name = u;
832         signal_changed (USE_ISDCF_NAME);
833 }
834
835 void
836 Film::set_dcp_content_type (DCPContentType const * t)
837 {
838         _dcp_content_type = t;
839         signal_changed (DCP_CONTENT_TYPE);
840 }
841
842 void
843 Film::set_container (Ratio const * c)
844 {
845         _container = c;
846         signal_changed (CONTAINER);
847 }
848
849 void
850 Film::set_resolution (Resolution r)
851 {
852         _resolution = r;
853         signal_changed (RESOLUTION);
854 }
855
856 void
857 Film::set_j2k_bandwidth (int b)
858 {
859         _j2k_bandwidth = b;
860         signal_changed (J2K_BANDWIDTH);
861 }
862
863 void
864 Film::set_isdcf_metadata (ISDCFMetadata m)
865 {
866         _isdcf_metadata = m;
867         signal_changed (ISDCF_METADATA);
868 }
869
870 void
871 Film::set_video_frame_rate (int f)
872 {
873         _video_frame_rate = f;
874         signal_changed (VIDEO_FRAME_RATE);
875 }
876
877 void
878 Film::set_audio_channels (int c)
879 {
880         _audio_channels = c;
881         signal_changed (AUDIO_CHANNELS);
882 }
883
884 void
885 Film::set_three_d (bool t)
886 {
887         _three_d = t;
888         signal_changed (THREE_D);
889
890         if (_three_d && _isdcf_metadata.two_d_version_of_three_d) {
891                 _isdcf_metadata.two_d_version_of_three_d = false;
892                 signal_changed (ISDCF_METADATA);
893         }
894 }
895
896 void
897 Film::set_interop (bool i)
898 {
899         _interop = i;
900         signal_changed (INTEROP);
901 }
902
903 void
904 Film::set_audio_processor (AudioProcessor const * processor)
905 {
906         _audio_processor = processor;
907         signal_changed (AUDIO_PROCESSOR);
908         signal_changed (AUDIO_CHANNELS);
909 }
910
911 void
912 Film::set_reel_type (ReelType t)
913 {
914         _reel_type = t;
915         signal_changed (REEL_TYPE);
916 }
917
918 /** @param r Desired reel length in bytes */
919 void
920 Film::set_reel_length (int64_t r)
921 {
922         _reel_length = r;
923         signal_changed (REEL_LENGTH);
924 }
925
926 void
927 Film::set_upload_after_make_dcp (bool u)
928 {
929         _upload_after_make_dcp = u;
930         signal_changed (UPLOAD_AFTER_MAKE_DCP);
931 }
932
933 void
934 Film::signal_changed (Property p)
935 {
936         _dirty = true;
937
938         switch (p) {
939         case Film::CONTENT:
940                 set_video_frame_rate (_playlist->best_video_frame_rate ());
941                 break;
942         case Film::VIDEO_FRAME_RATE:
943         case Film::SEQUENCE:
944                 _playlist->maybe_sequence ();
945                 break;
946         default:
947                 break;
948         }
949
950         emit (boost::bind (boost::ref (Changed), p));
951 }
952
953 void
954 Film::set_isdcf_date_today ()
955 {
956         _isdcf_date = boost::gregorian::day_clock::local_day ();
957 }
958
959 boost::filesystem::path
960 Film::j2c_path (int reel, Frame frame, Eyes eyes, bool tmp) const
961 {
962         boost::filesystem::path p;
963         p /= "j2c";
964         p /= video_identifier ();
965
966         char buffer[256];
967         snprintf(buffer, sizeof(buffer), "%08d_%08" PRId64, reel, frame);
968         string s (buffer);
969
970         if (eyes == EYES_LEFT) {
971                 s += ".L";
972         } else if (eyes == EYES_RIGHT) {
973                 s += ".R";
974         }
975
976         s += ".j2c";
977
978         if (tmp) {
979                 s += ".tmp";
980         }
981
982         p /= s;
983         return file (p);
984 }
985
986 /** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs */
987 vector<CPLSummary>
988 Film::cpls () const
989 {
990         if (!directory ()) {
991                 return vector<CPLSummary> ();
992         }
993
994         vector<CPLSummary> out;
995
996         boost::filesystem::path const dir = directory().get();
997         for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator(dir); i != boost::filesystem::directory_iterator(); ++i) {
998                 if (
999                         boost::filesystem::is_directory (*i) &&
1000                         i->path().leaf() != "j2c" && i->path().leaf() != "video" && i->path().leaf() != "info" && i->path().leaf() != "analysis"
1001                         ) {
1002
1003                         try {
1004                                 dcp::DCP dcp (*i);
1005                                 dcp.read ();
1006                                 DCPOMATIC_ASSERT (dcp.cpls().front()->file());
1007                                 out.push_back (
1008                                         CPLSummary (
1009                                                 i->path().leaf().string(),
1010                                                 dcp.cpls().front()->id(),
1011                                                 dcp.cpls().front()->annotation_text(),
1012                                                 dcp.cpls().front()->file().get()
1013                                                 )
1014                                         );
1015                         } catch (...) {
1016
1017                         }
1018                 }
1019         }
1020
1021         return out;
1022 }
1023
1024 void
1025 Film::set_signed (bool s)
1026 {
1027         _signed = s;
1028         signal_changed (SIGNED);
1029 }
1030
1031 void
1032 Film::set_encrypted (bool e)
1033 {
1034         _encrypted = e;
1035         signal_changed (ENCRYPTED);
1036 }
1037
1038 void
1039 Film::set_key (dcp::Key key)
1040 {
1041         _key = key;
1042         signal_changed (KEY);
1043 }
1044
1045 ContentList
1046 Film::content () const
1047 {
1048         return _playlist->content ();
1049 }
1050
1051 void
1052 Film::examine_and_add_content (shared_ptr<Content> c)
1053 {
1054         if (dynamic_pointer_cast<FFmpegContent> (c) && _directory) {
1055                 run_ffprobe (c->path(0), file ("ffprobe.log"), _log);
1056         }
1057
1058         shared_ptr<Job> j (new ExamineContentJob (shared_from_this(), c));
1059
1060         _job_connections.push_back (
1061                 j->Finished.connect (bind (&Film::maybe_add_content, this, weak_ptr<Job> (j), weak_ptr<Content> (c)))
1062                 );
1063
1064         JobManager::instance()->add (j);
1065 }
1066
1067 void
1068 Film::maybe_add_content (weak_ptr<Job> j, weak_ptr<Content> c)
1069 {
1070         shared_ptr<Job> job = j.lock ();
1071         if (!job || !job->finished_ok ()) {
1072                 return;
1073         }
1074
1075         shared_ptr<Content> content = c.lock ();
1076         if (!content) {
1077                 return;
1078         }
1079
1080         add_content (content);
1081
1082         if (Config::instance()->automatic_audio_analysis() && content->audio) {
1083                 shared_ptr<Playlist> playlist (new Playlist);
1084                 playlist->add (content);
1085                 boost::signals2::connection c;
1086                 JobManager::instance()->analyse_audio (
1087                         shared_from_this (), playlist, c, bind (&Film::audio_analysis_finished, this)
1088                         );
1089                 _audio_analysis_connections.push_back (c);
1090         }
1091 }
1092
1093 void
1094 Film::add_content (shared_ptr<Content> c)
1095 {
1096         /* Add {video,subtitle} content after any existing {video,subtitle} content */
1097         if (c->video) {
1098                 c->set_position (_playlist->video_end ());
1099         } else if (c->subtitle) {
1100                 c->set_position (_playlist->subtitle_end ());
1101         }
1102
1103         if (_template_film) {
1104                 /* Take settings from the first piece of content of c's type in _template */
1105                 BOOST_FOREACH (shared_ptr<Content> i, _template_film->content()) {
1106                         if (typeid(i.get()) == typeid(c.get())) {
1107                                 c->use_template (i);
1108                         }
1109                 }
1110         }
1111
1112         _playlist->add (c);
1113 }
1114
1115 void
1116 Film::remove_content (shared_ptr<Content> c)
1117 {
1118         _playlist->remove (c);
1119 }
1120
1121 void
1122 Film::move_content_earlier (shared_ptr<Content> c)
1123 {
1124         _playlist->move_earlier (c);
1125 }
1126
1127 void
1128 Film::move_content_later (shared_ptr<Content> c)
1129 {
1130         _playlist->move_later (c);
1131 }
1132
1133 /** @return length of the film from time 0 to the last thing on the playlist */
1134 DCPTime
1135 Film::length () const
1136 {
1137         return _playlist->length ();
1138 }
1139
1140 int
1141 Film::best_video_frame_rate () const
1142 {
1143         return _playlist->best_video_frame_rate ();
1144 }
1145
1146 FrameRateChange
1147 Film::active_frame_rate_change (DCPTime t) const
1148 {
1149         return _playlist->active_frame_rate_change (t, video_frame_rate ());
1150 }
1151
1152 void
1153 Film::playlist_content_changed (weak_ptr<Content> c, int p, bool frequent)
1154 {
1155         _dirty = true;
1156
1157         if (p == ContentProperty::VIDEO_FRAME_RATE) {
1158                 set_video_frame_rate (_playlist->best_video_frame_rate ());
1159         } else if (p == AudioContentProperty::STREAMS) {
1160                 signal_changed (NAME);
1161         }
1162
1163         emit (boost::bind (boost::ref (ContentChanged), c, p, frequent));
1164 }
1165
1166 void
1167 Film::playlist_changed ()
1168 {
1169         signal_changed (CONTENT);
1170         signal_changed (NAME);
1171 }
1172
1173 void
1174 Film::playlist_order_changed ()
1175 {
1176         signal_changed (CONTENT_ORDER);
1177 }
1178
1179 int
1180 Film::audio_frame_rate () const
1181 {
1182         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
1183                 if (i->audio && i->audio->has_rate_above_48k ()) {
1184                         return 96000;
1185                 }
1186         }
1187
1188         return 48000;
1189 }
1190
1191 void
1192 Film::set_sequence (bool s)
1193 {
1194         _sequence = s;
1195         _playlist->set_sequence (s);
1196         signal_changed (SEQUENCE);
1197 }
1198
1199 /** @return Size of the largest possible image in whatever resolution we are using */
1200 dcp::Size
1201 Film::full_frame () const
1202 {
1203         switch (_resolution) {
1204         case RESOLUTION_2K:
1205                 return dcp::Size (2048, 1080);
1206         case RESOLUTION_4K:
1207                 return dcp::Size (4096, 2160);
1208         }
1209
1210         DCPOMATIC_ASSERT (false);
1211         return dcp::Size ();
1212 }
1213
1214 /** @return Size of the frame */
1215 dcp::Size
1216 Film::frame_size () const
1217 {
1218         return fit_ratio_within (container()->ratio(), full_frame ());
1219 }
1220
1221 /** @param from KDM from time expressed as a local time with an offset from UTC
1222  *  @param to KDM to time expressed as a local time with an offset from UTC
1223  */
1224 dcp::EncryptedKDM
1225 Film::make_kdm (
1226         dcp::Certificate recipient,
1227         vector<dcp::Certificate> trusted_devices,
1228         boost::filesystem::path cpl_file,
1229         dcp::LocalTime from,
1230         dcp::LocalTime until,
1231         dcp::Formulation formulation
1232         ) const
1233 {
1234         shared_ptr<const dcp::CPL> cpl (new dcp::CPL (cpl_file));
1235         shared_ptr<const dcp::CertificateChain> signer = Config::instance()->signer_chain ();
1236         if (!signer->valid ()) {
1237                 throw InvalidSignerError ();
1238         }
1239
1240         /* Find keys that have been added to imported, encrypted DCP content */
1241         list<dcp::DecryptedKDMKey> imported_keys;
1242         BOOST_FOREACH (shared_ptr<Content> i, content()) {
1243                 shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
1244                 if (d && d->kdm()) {
1245                         dcp::DecryptedKDM kdm (d->kdm().get(), Config::instance()->decryption_chain()->key().get());
1246                         list<dcp::DecryptedKDMKey> keys = kdm.keys ();
1247                         copy (keys.begin(), keys.end(), back_inserter (imported_keys));
1248                 }
1249         }
1250
1251         map<shared_ptr<const dcp::ReelMXF>, dcp::Key> keys;
1252
1253         BOOST_FOREACH(shared_ptr<const dcp::ReelAsset> i, cpl->reel_assets ()) {
1254                 shared_ptr<const dcp::ReelMXF> mxf = boost::dynamic_pointer_cast<const dcp::ReelMXF> (i);
1255                 if (!mxf || !mxf->key_id()) {
1256                         continue;
1257                 }
1258
1259                 /* Get any imported key for this ID */
1260                 bool done = false;
1261                 BOOST_FOREACH (dcp::DecryptedKDMKey j, imported_keys) {
1262                         if (j.id() == mxf->key_id().get()) {
1263                                 LOG_GENERAL ("Using imported key for %1", mxf->key_id().get());
1264                                 keys[mxf] = j.key();
1265                                 done = true;
1266                         }
1267                 }
1268
1269                 if (!done) {
1270                         /* No imported key; it must be an asset that we encrypted */
1271                         LOG_GENERAL ("Using our own key for %1", mxf->key_id().get());
1272                         keys[mxf] = key();
1273                 }
1274         }
1275
1276         return dcp::DecryptedKDM (
1277                 cpl->id(), keys, from, until, cpl->content_title_text(), cpl->content_title_text(), dcp::LocalTime().as_string()
1278                 ).encrypt (signer, recipient, trusted_devices, formulation);
1279 }
1280
1281 /** @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema.
1282  *  @param to KDM to time expressed as a local time in the time zone of the Screen's Cinema.
1283  */
1284 list<ScreenKDM>
1285 Film::make_kdms (
1286         list<shared_ptr<Screen> > screens,
1287         boost::filesystem::path dcp,
1288         boost::posix_time::ptime from,
1289         boost::posix_time::ptime until,
1290         dcp::Formulation formulation
1291         ) const
1292 {
1293         list<ScreenKDM> kdms;
1294
1295         BOOST_FOREACH (shared_ptr<Screen> i, screens) {
1296                 if (i->recipient) {
1297                         dcp::EncryptedKDM const kdm = make_kdm (
1298                                 i->recipient.get(),
1299                                 i->trusted_devices,
1300                                 dcp,
1301                                 dcp::LocalTime (from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
1302                                 dcp::LocalTime (until, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
1303                                 formulation
1304                                 );
1305
1306                         kdms.push_back (ScreenKDM (i, kdm));
1307                 }
1308         }
1309
1310         return kdms;
1311 }
1312
1313 /** @return The approximate disk space required to encode a DCP of this film with the
1314  *  current settings, in bytes.
1315  */
1316 uint64_t
1317 Film::required_disk_space () const
1318 {
1319         return _playlist->required_disk_space (j2k_bandwidth(), audio_channels(), audio_frame_rate());
1320 }
1321
1322 /** This method checks the disk that the Film is on and tries to decide whether or not
1323  *  there will be enough space to make a DCP for it.  If so, true is returned; if not,
1324  *  false is returned and required and available are filled in with the amount of disk space
1325  *  required and available respectively (in Gb).
1326  *
1327  *  Note: the decision made by this method isn't, of course, 100% reliable.
1328  */
1329 bool
1330 Film::should_be_enough_disk_space (double& required, double& available, bool& can_hard_link) const
1331 {
1332         /* Create a test file and see if we can hard-link it */
1333         boost::filesystem::path test = internal_video_asset_dir() / "test";
1334         boost::filesystem::path test2 = internal_video_asset_dir() / "test2";
1335         can_hard_link = true;
1336         FILE* f = fopen_boost (test, "w");
1337         if (f) {
1338                 fclose (f);
1339                 boost::system::error_code ec;
1340                 boost::filesystem::create_hard_link (test, test2, ec);
1341                 if (ec) {
1342                         can_hard_link = false;
1343                 }
1344                 boost::filesystem::remove (test);
1345                 boost::filesystem::remove (test2);
1346         }
1347
1348         boost::filesystem::space_info s = boost::filesystem::space (internal_video_asset_dir ());
1349         required = double (required_disk_space ()) / 1073741824.0f;
1350         if (!can_hard_link) {
1351                 required *= 2;
1352         }
1353         available = double (s.available) / 1073741824.0f;
1354         return (available - required) > 1;
1355 }
1356
1357 string
1358 Film::subtitle_language () const
1359 {
1360         set<string> languages;
1361
1362         ContentList cl = content ();
1363         BOOST_FOREACH (shared_ptr<Content>& c, cl) {
1364                 if (c->subtitle) {
1365                         languages.insert (c->subtitle->language ());
1366                 }
1367         }
1368
1369         string all;
1370         BOOST_FOREACH (string s, languages) {
1371                 if (!all.empty ()) {
1372                         all += "/" + s;
1373                 } else {
1374                         all += s;
1375                 }
1376         }
1377
1378         return all;
1379 }
1380
1381 /** Change the gains of the supplied AudioMapping to make it a default
1382  *  for this film.  The defaults are guessed based on what processor (if any)
1383  *  is in use, the number of input channels and any filename supplied.
1384  */
1385 void
1386 Film::make_audio_mapping_default (AudioMapping& mapping, optional<boost::filesystem::path> filename) const
1387 {
1388         static string const regex[] = {
1389                 ".*[\\._-]L[\\._-].*",
1390                 ".*[\\._-]R[\\._-].*",
1391                 ".*[\\._-]C[\\._-].*",
1392                 ".*[\\._-]Lfe[\\._-].*",
1393                 ".*[\\._-]Ls[\\._-].*",
1394                 ".*[\\._-]Rs[\\._-].*"
1395         };
1396
1397         static int const regexes = sizeof(regex) / sizeof(*regex);
1398
1399         if (audio_processor ()) {
1400                 audio_processor()->make_audio_mapping_default (mapping);
1401         } else {
1402                 mapping.make_zero ();
1403                 if (mapping.input_channels() == 1) {
1404                         bool guessed = false;
1405
1406                         /* See if we can guess where this stream should go */
1407                         if (filename) {
1408                                 for (int i = 0; i < regexes; ++i) {
1409                                         boost::regex e (regex[i], boost::regex::icase);
1410                                         if (boost::regex_match (filename->string(), e) && i < mapping.output_channels()) {
1411                                                 mapping.set (0, i, 1);
1412                                                 guessed = true;
1413                                         }
1414                                 }
1415                         }
1416
1417                         if (!guessed) {
1418                                 /* If we have no idea, just put it on centre */
1419                                 mapping.set (0, static_cast<int> (dcp::CENTRE), 1);
1420                         }
1421                 } else {
1422                         /* 1:1 mapping */
1423                         for (int i = 0; i < min (mapping.input_channels(), mapping.output_channels()); ++i) {
1424                                 mapping.set (i, i, 1);
1425                         }
1426                 }
1427         }
1428 }
1429
1430 /** @return The names of the channels that audio contents' outputs are passed into;
1431  *  this is either the DCP or a AudioProcessor.
1432  */
1433 vector<string>
1434 Film::audio_output_names () const
1435 {
1436         if (audio_processor ()) {
1437                 return audio_processor()->input_names ();
1438         }
1439
1440         DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16);
1441
1442         vector<string> n;
1443
1444         for (int i = 0; i < audio_channels(); ++i) {
1445                 n.push_back (short_audio_channel_name (i));
1446         }
1447
1448         return n;
1449 }
1450
1451 void
1452 Film::repeat_content (ContentList c, int n)
1453 {
1454         _playlist->repeat (c, n);
1455 }
1456
1457 void
1458 Film::remove_content (ContentList c)
1459 {
1460         _playlist->remove (c);
1461 }
1462
1463 void
1464 Film::audio_analysis_finished ()
1465 {
1466         /* XXX */
1467 }
1468
1469 list<DCPTimePeriod>
1470 Film::reels () const
1471 {
1472         list<DCPTimePeriod> p;
1473         DCPTime const len = length().ceil (video_frame_rate ());
1474
1475         switch (reel_type ()) {
1476         case REELTYPE_SINGLE:
1477                 p.push_back (DCPTimePeriod (DCPTime (), len));
1478                 break;
1479         case REELTYPE_BY_VIDEO_CONTENT:
1480         {
1481                 optional<DCPTime> last_split;
1482                 shared_ptr<Content> last_video;
1483                 BOOST_FOREACH (shared_ptr<Content> c, content ()) {
1484                         if (c->video) {
1485                                 BOOST_FOREACH (DCPTime t, c->reel_split_points()) {
1486                                         if (last_split) {
1487                                                 p.push_back (DCPTimePeriod (last_split.get(), t));
1488                                         }
1489                                         last_split = t;
1490                                 }
1491                                 last_video = c;
1492                         }
1493                 }
1494
1495                 DCPTime video_end = last_video ? last_video->end() : DCPTime(0);
1496                 if (last_split) {
1497                         /* Definitely go from the last split to the end of the video content */
1498                         p.push_back (DCPTimePeriod (last_split.get(), video_end));
1499                 }
1500
1501                 if (video_end < len) {
1502                         /* And maybe go after that as well if there is any non-video hanging over the end */
1503                         p.push_back (DCPTimePeriod (video_end, len));
1504                 }
1505                 break;
1506         }
1507         case REELTYPE_BY_LENGTH:
1508         {
1509                 DCPTime current;
1510                 /* Integer-divide reel length by the size of one frame to give the number of frames per reel */
1511                 Frame const reel_in_frames = _reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8);
1512                 while (current < len) {
1513                         DCPTime end = min (len, current + DCPTime::from_frames (reel_in_frames, video_frame_rate ()));
1514                         p.push_back (DCPTimePeriod (current, end));
1515                         current = end;
1516                 }
1517                 break;
1518         }
1519         }
1520
1521         return p;
1522 }
1523
1524 string
1525 Film::content_summary (DCPTimePeriod period) const
1526 {
1527         return _playlist->content_summary (period);
1528 }
1529
1530 list<string>
1531 Film::fix_conflicting_settings ()
1532 {
1533         list<string> notes;
1534
1535         list<boost::filesystem::path> was_referencing;
1536         BOOST_FOREACH (shared_ptr<Content> i, content()) {
1537                 shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
1538                 if (d) {
1539                         list<string> reasons;
1540                         bool was = false;
1541                         if (!d->can_reference_video(reasons) && d->reference_video()) {
1542                                 d->set_reference_video (false);
1543                                 was = true;
1544                         }
1545                         if (!d->can_reference_audio(reasons) && d->reference_audio()) {
1546                                 d->set_reference_audio (false);
1547                                 was = true;
1548                         }
1549                         if (!d->can_reference_subtitle(reasons) && d->reference_subtitle()) {
1550                                 d->set_reference_subtitle (false);
1551                                 was = true;
1552                         }
1553                         if (was) {
1554                                 was_referencing.push_back (d->path(0).parent_path().filename());
1555                         }
1556                 }
1557         }
1558
1559         BOOST_FOREACH (boost::filesystem::path d, was_referencing) {
1560                 notes.push_back (String::compose (_("The DCP %1 was being referred to by this film.  This not now possible because the reel sizes in the film no longer agree with those in the imported DCP.\n\nSetting the 'Reel type' to 'split by video content' will probably help.\n\nAfter doing that you would need to re-tick the appropriate 'refer to existing DCP' checkboxes."), d.string()));
1561         }
1562
1563         return notes;
1564 }
1565
1566 void
1567 Film::use_template (string name)
1568 {
1569         _template_film.reset (new Film (optional<boost::filesystem::path>()));
1570         _template_film->read_metadata (Config::instance()->template_path (name));
1571         _use_isdcf_name = _template_film->_use_isdcf_name;
1572         _dcp_content_type = _template_film->_dcp_content_type;
1573         _container = _template_film->_container;
1574         _resolution = _template_film->_resolution;
1575         _j2k_bandwidth = _template_film->_j2k_bandwidth;
1576         _video_frame_rate = _template_film->_video_frame_rate;
1577         _signed = _template_film->_signed;
1578         _encrypted = _template_film->_encrypted;
1579         _audio_channels = _template_film->_audio_channels;
1580         _sequence = _template_film->_sequence;
1581         _three_d = _template_film->_three_d;
1582         _interop = _template_film->_interop;
1583         _audio_processor = _template_film->_audio_processor;
1584         _reel_type = _template_film->_reel_type;
1585         _reel_length = _template_film->_reel_length;
1586         _upload_after_make_dcp = _template_film->_upload_after_make_dcp;
1587 }