Distinguish master DoM encode threads count from the server count.
[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()->master_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  *  @param d directory name within the Filn's directory.
513  *  @param create true to create the directory (and its parents) if they do not exist.
514  */
515 boost::filesystem::path
516 Film::dir (boost::filesystem::path d, bool create) const
517 {
518         DCPOMATIC_ASSERT (_directory);
519
520         boost::filesystem::path p;
521         p /= _directory.get();
522         p /= d;
523
524         if (create) {
525                 boost::filesystem::create_directories (p);
526         }
527
528         return p;
529 }
530
531 /** Given a file or directory name, return its full path within the Film's directory.
532  *  Any required parent directories will be created.
533  */
534 boost::filesystem::path
535 Film::file (boost::filesystem::path f) const
536 {
537         DCPOMATIC_ASSERT (_directory);
538
539         boost::filesystem::path p;
540         p /= _directory.get();
541         p /= f;
542
543         boost::filesystem::create_directories (p.parent_path ());
544
545         return p;
546 }
547
548 list<int>
549 Film::mapped_audio_channels () const
550 {
551         list<int> mapped;
552
553         if (audio_processor ()) {
554                 /* Processors are mapped 1:1 to DCP outputs so we can work out mappings from there */
555                 for (int i = 0; i < audio_processor()->out_channels(); ++i) {
556                         mapped.push_back (i);
557                 }
558         } else {
559                 BOOST_FOREACH (shared_ptr<Content> i, content ()) {
560                         if (i->audio) {
561                                 list<int> c = i->audio->mapping().mapped_output_channels ();
562                                 copy (c.begin(), c.end(), back_inserter (mapped));
563                         }
564                 }
565
566                 mapped.sort ();
567                 mapped.unique ();
568         }
569
570         return mapped;
571 }
572
573 /** @return a ISDCF-compliant name for a DCP of this film */
574 string
575 Film::isdcf_name (bool if_created_now) const
576 {
577         string d;
578
579         string raw_name = name ();
580
581         /* Split the raw name up into words */
582         vector<string> words;
583         split (words, raw_name, is_any_of (" _-"));
584
585         string fixed_name;
586
587         /* Add each word to fixed_name */
588         for (vector<string>::const_iterator i = words.begin(); i != words.end(); ++i) {
589                 string w = *i;
590
591                 /* First letter is always capitalised */
592                 w[0] = toupper (w[0]);
593
594                 /* Count caps in w */
595                 size_t caps = 0;
596                 for (size_t i = 0; i < w.size(); ++i) {
597                         if (isupper (w[i])) {
598                                 ++caps;
599                         }
600                 }
601
602                 /* If w is all caps make the rest of it lower case, otherwise
603                    leave it alone.
604                 */
605                 if (caps == w.size ()) {
606                         for (size_t i = 1; i < w.size(); ++i) {
607                                 w[i] = tolower (w[i]);
608                         }
609                 }
610
611                 for (size_t i = 0; i < w.size(); ++i) {
612                         fixed_name += w[i];
613                 }
614         }
615
616         if (fixed_name.length() > 14) {
617                 fixed_name = fixed_name.substr (0, 14);
618         }
619
620         d += fixed_name;
621
622         if (dcp_content_type()) {
623                 d += "_" + dcp_content_type()->isdcf_name();
624                 d += "-" + raw_convert<string>(isdcf_metadata().content_version);
625         }
626
627         ISDCFMetadata const dm = isdcf_metadata ();
628
629         if (dm.temp_version) {
630                 d += "-Temp";
631         }
632
633         if (dm.pre_release) {
634                 d += "-Pre";
635         }
636
637         if (dm.red_band) {
638                 d += "-RedBand";
639         }
640
641         if (!dm.chain.empty ()) {
642                 d += "-" + dm.chain;
643         }
644
645         if (three_d ()) {
646                 d += "-3D";
647         }
648
649         if (dm.two_d_version_of_three_d) {
650                 d += "-2D";
651         }
652
653         if (!dm.mastered_luminance.empty ()) {
654                 d += "-" + dm.mastered_luminance;
655         }
656
657         if (video_frame_rate() != 24) {
658                 d += "-" + raw_convert<string>(video_frame_rate());
659         }
660
661         if (container()) {
662                 d += "_" + container()->isdcf_name();
663         }
664
665         /* XXX: this uses the first bit of content only */
666
667         /* The standard says we don't do this for trailers, for some strange reason */
668         if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::TRAILER) {
669                 Ratio const * content_ratio = 0;
670                 BOOST_FOREACH (shared_ptr<Content> i, content ()) {
671                         if (i->video) {
672                                 /* Here's the first piece of video content */
673                                 if (i->video->scale().ratio ()) {
674                                         content_ratio = i->video->scale().ratio ();
675                                 } else {
676                                         content_ratio = Ratio::from_ratio (i->video->size().ratio ());
677                                 }
678                                 break;
679                         }
680                 }
681
682                 if (content_ratio && content_ratio != container()) {
683                         d += "-" + content_ratio->isdcf_name();
684                 }
685         }
686
687         if (!dm.audio_language.empty ()) {
688                 d += "_" + dm.audio_language;
689                 if (!dm.subtitle_language.empty()) {
690
691                         bool burnt_in = true;
692                         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
693                                 if (!i->subtitle) {
694                                         continue;
695                                 }
696
697                                 if (i->subtitle->use() && !i->subtitle->burn()) {
698                                         burnt_in = false;
699                                 }
700                         }
701
702                         string language = dm.subtitle_language;
703                         if (burnt_in && language != "XX") {
704                                 transform (language.begin(), language.end(), language.begin(), ::tolower);
705                         } else {
706                                 transform (language.begin(), language.end(), language.begin(), ::toupper);
707                         }
708
709                         d += "-" + language;
710                 } else {
711                         d += "-XX";
712                 }
713         }
714
715         if (!dm.territory.empty ()) {
716                 d += "_" + dm.territory;
717                 if (dm.rating.empty ()) {
718                         d += "-NR";
719                 } else {
720                         d += "-" + dm.rating;
721                 }
722         }
723
724         /* Count mapped audio channels */
725
726         int non_lfe = 0;
727         int lfe = 0;
728
729         BOOST_FOREACH (int i, mapped_audio_channels ()) {
730                 if (i >= audio_channels()) {
731                         /* This channel is mapped but is not included in the DCP */
732                         continue;
733                 }
734
735                 if (static_cast<dcp::Channel> (i) == dcp::LFE) {
736                         ++lfe;
737                 } else {
738                         ++non_lfe;
739                 }
740         }
741
742         if (non_lfe) {
743                 d += String::compose("_%1%2", non_lfe, lfe);
744         }
745
746         /* XXX: HI/VI */
747
748         d += "_" + resolution_to_string (_resolution);
749
750         if (!dm.studio.empty ()) {
751                 d += "_" + dm.studio;
752         }
753
754         if (if_created_now) {
755                 d += "_" + boost::gregorian::to_iso_string (boost::gregorian::day_clock::local_day ());
756         } else {
757                 d += "_" + boost::gregorian::to_iso_string (_isdcf_date);
758         }
759
760         if (!dm.facility.empty ()) {
761                 d += "_" + dm.facility;
762         }
763
764         if (_interop) {
765                 d += "_IOP";
766         } else {
767                 d += "_SMPTE";
768         }
769
770         if (three_d ()) {
771                 d += "-3D";
772         }
773
774         bool vf = false;
775         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
776                 shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
777                 if (dc && (dc->reference_video() || dc->reference_audio() || dc->reference_subtitle())) {
778                         vf = true;
779                 }
780         }
781
782         if (vf) {
783                 d += "_VF";
784         } else {
785                 d += "_OV";
786         }
787
788         return d;
789 }
790
791 /** @return name to give the DCP */
792 string
793 Film::dcp_name (bool if_created_now) const
794 {
795         string unfiltered;
796         if (use_isdcf_name()) {
797                 return careful_string_filter (isdcf_name (if_created_now));
798         }
799
800         return careful_string_filter (name ());
801 }
802
803 void
804 Film::set_directory (boost::filesystem::path d)
805 {
806         _directory = d;
807         _dirty = true;
808 }
809
810 void
811 Film::set_name (string n)
812 {
813         _name = n;
814         signal_changed (NAME);
815 }
816
817 void
818 Film::set_use_isdcf_name (bool u)
819 {
820         _use_isdcf_name = u;
821         signal_changed (USE_ISDCF_NAME);
822 }
823
824 void
825 Film::set_dcp_content_type (DCPContentType const * t)
826 {
827         _dcp_content_type = t;
828         signal_changed (DCP_CONTENT_TYPE);
829 }
830
831 void
832 Film::set_container (Ratio const * c)
833 {
834         _container = c;
835         signal_changed (CONTAINER);
836 }
837
838 void
839 Film::set_resolution (Resolution r)
840 {
841         _resolution = r;
842         signal_changed (RESOLUTION);
843 }
844
845 void
846 Film::set_j2k_bandwidth (int b)
847 {
848         _j2k_bandwidth = b;
849         signal_changed (J2K_BANDWIDTH);
850 }
851
852 void
853 Film::set_isdcf_metadata (ISDCFMetadata m)
854 {
855         _isdcf_metadata = m;
856         signal_changed (ISDCF_METADATA);
857 }
858
859 void
860 Film::set_video_frame_rate (int f)
861 {
862         _video_frame_rate = f;
863         signal_changed (VIDEO_FRAME_RATE);
864 }
865
866 void
867 Film::set_audio_channels (int c)
868 {
869         _audio_channels = c;
870         signal_changed (AUDIO_CHANNELS);
871 }
872
873 void
874 Film::set_three_d (bool t)
875 {
876         _three_d = t;
877         signal_changed (THREE_D);
878
879         if (_three_d && _isdcf_metadata.two_d_version_of_three_d) {
880                 _isdcf_metadata.two_d_version_of_three_d = false;
881                 signal_changed (ISDCF_METADATA);
882         }
883 }
884
885 void
886 Film::set_interop (bool i)
887 {
888         _interop = i;
889         signal_changed (INTEROP);
890 }
891
892 void
893 Film::set_audio_processor (AudioProcessor const * processor)
894 {
895         _audio_processor = processor;
896         signal_changed (AUDIO_PROCESSOR);
897         signal_changed (AUDIO_CHANNELS);
898 }
899
900 void
901 Film::set_reel_type (ReelType t)
902 {
903         _reel_type = t;
904         signal_changed (REEL_TYPE);
905 }
906
907 /** @param r Desired reel length in bytes */
908 void
909 Film::set_reel_length (int64_t r)
910 {
911         _reel_length = r;
912         signal_changed (REEL_LENGTH);
913 }
914
915 void
916 Film::set_upload_after_make_dcp (bool u)
917 {
918         _upload_after_make_dcp = u;
919         signal_changed (UPLOAD_AFTER_MAKE_DCP);
920 }
921
922 void
923 Film::signal_changed (Property p)
924 {
925         _dirty = true;
926
927         switch (p) {
928         case Film::CONTENT:
929                 set_video_frame_rate (_playlist->best_video_frame_rate ());
930                 break;
931         case Film::VIDEO_FRAME_RATE:
932         case Film::SEQUENCE:
933                 _playlist->maybe_sequence ();
934                 break;
935         default:
936                 break;
937         }
938
939         emit (boost::bind (boost::ref (Changed), p));
940 }
941
942 void
943 Film::set_isdcf_date_today ()
944 {
945         _isdcf_date = boost::gregorian::day_clock::local_day ();
946 }
947
948 boost::filesystem::path
949 Film::j2c_path (int reel, Frame frame, Eyes eyes, bool tmp) const
950 {
951         boost::filesystem::path p;
952         p /= "j2c";
953         p /= video_identifier ();
954
955         char buffer[256];
956         snprintf(buffer, sizeof(buffer), "%08d_%08" PRId64, reel, frame);
957         string s (buffer);
958
959         if (eyes == EYES_LEFT) {
960                 s += ".L";
961         } else if (eyes == EYES_RIGHT) {
962                 s += ".R";
963         }
964
965         s += ".j2c";
966
967         if (tmp) {
968                 s += ".tmp";
969         }
970
971         p /= s;
972         return file (p);
973 }
974
975 /** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs */
976 vector<CPLSummary>
977 Film::cpls () const
978 {
979         if (!directory ()) {
980                 return vector<CPLSummary> ();
981         }
982
983         vector<CPLSummary> out;
984
985         boost::filesystem::path const dir = directory().get();
986         for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator(dir); i != boost::filesystem::directory_iterator(); ++i) {
987                 if (
988                         boost::filesystem::is_directory (*i) &&
989                         i->path().leaf() != "j2c" && i->path().leaf() != "video" && i->path().leaf() != "info" && i->path().leaf() != "analysis"
990                         ) {
991
992                         try {
993                                 dcp::DCP dcp (*i);
994                                 dcp.read ();
995                                 DCPOMATIC_ASSERT (dcp.cpls().front()->file());
996                                 out.push_back (
997                                         CPLSummary (
998                                                 i->path().leaf().string(),
999                                                 dcp.cpls().front()->id(),
1000                                                 dcp.cpls().front()->annotation_text(),
1001                                                 dcp.cpls().front()->file().get()
1002                                                 )
1003                                         );
1004                         } catch (...) {
1005
1006                         }
1007                 }
1008         }
1009
1010         return out;
1011 }
1012
1013 void
1014 Film::set_signed (bool s)
1015 {
1016         _signed = s;
1017         signal_changed (SIGNED);
1018 }
1019
1020 void
1021 Film::set_encrypted (bool e)
1022 {
1023         _encrypted = e;
1024         signal_changed (ENCRYPTED);
1025 }
1026
1027 void
1028 Film::set_key (dcp::Key key)
1029 {
1030         _key = key;
1031         signal_changed (KEY);
1032 }
1033
1034 ContentList
1035 Film::content () const
1036 {
1037         return _playlist->content ();
1038 }
1039
1040 void
1041 Film::examine_and_add_content (shared_ptr<Content> c)
1042 {
1043         if (dynamic_pointer_cast<FFmpegContent> (c) && _directory) {
1044                 run_ffprobe (c->path(0), file ("ffprobe.log"), _log);
1045         }
1046
1047         shared_ptr<Job> j (new ExamineContentJob (shared_from_this(), c));
1048
1049         _job_connections.push_back (
1050                 j->Finished.connect (bind (&Film::maybe_add_content, this, weak_ptr<Job> (j), weak_ptr<Content> (c)))
1051                 );
1052
1053         JobManager::instance()->add (j);
1054 }
1055
1056 void
1057 Film::maybe_add_content (weak_ptr<Job> j, weak_ptr<Content> c)
1058 {
1059         shared_ptr<Job> job = j.lock ();
1060         if (!job || !job->finished_ok ()) {
1061                 return;
1062         }
1063
1064         shared_ptr<Content> content = c.lock ();
1065         if (!content) {
1066                 return;
1067         }
1068
1069         add_content (content);
1070
1071         if (Config::instance()->automatic_audio_analysis() && content->audio) {
1072                 shared_ptr<Playlist> playlist (new Playlist);
1073                 playlist->add (content);
1074                 boost::signals2::connection c;
1075                 JobManager::instance()->analyse_audio (
1076                         shared_from_this (), playlist, c, bind (&Film::audio_analysis_finished, this)
1077                         );
1078                 _audio_analysis_connections.push_back (c);
1079         }
1080 }
1081
1082 void
1083 Film::add_content (shared_ptr<Content> c)
1084 {
1085         /* Add {video,subtitle} content after any existing {video,subtitle} content */
1086         if (c->video) {
1087                 c->set_position (_playlist->video_end ());
1088         } else if (c->subtitle) {
1089                 c->set_position (_playlist->subtitle_end ());
1090         }
1091
1092         if (_template_film) {
1093                 /* Take settings from the first piece of content of c's type in _template */
1094                 BOOST_FOREACH (shared_ptr<Content> i, _template_film->content()) {
1095                         if (typeid(i.get()) == typeid(c.get())) {
1096                                 c->use_template (i);
1097                         }
1098                 }
1099         }
1100
1101         _playlist->add (c);
1102 }
1103
1104 void
1105 Film::remove_content (shared_ptr<Content> c)
1106 {
1107         _playlist->remove (c);
1108 }
1109
1110 void
1111 Film::move_content_earlier (shared_ptr<Content> c)
1112 {
1113         _playlist->move_earlier (c);
1114 }
1115
1116 void
1117 Film::move_content_later (shared_ptr<Content> c)
1118 {
1119         _playlist->move_later (c);
1120 }
1121
1122 /** @return length of the film from time 0 to the last thing on the playlist */
1123 DCPTime
1124 Film::length () const
1125 {
1126         return _playlist->length ();
1127 }
1128
1129 int
1130 Film::best_video_frame_rate () const
1131 {
1132         return _playlist->best_video_frame_rate ();
1133 }
1134
1135 FrameRateChange
1136 Film::active_frame_rate_change (DCPTime t) const
1137 {
1138         return _playlist->active_frame_rate_change (t, video_frame_rate ());
1139 }
1140
1141 void
1142 Film::playlist_content_changed (weak_ptr<Content> c, int p, bool frequent)
1143 {
1144         _dirty = true;
1145
1146         if (p == ContentProperty::VIDEO_FRAME_RATE) {
1147                 set_video_frame_rate (_playlist->best_video_frame_rate ());
1148         } else if (p == AudioContentProperty::STREAMS) {
1149                 signal_changed (NAME);
1150         }
1151
1152         emit (boost::bind (boost::ref (ContentChanged), c, p, frequent));
1153 }
1154
1155 void
1156 Film::playlist_changed ()
1157 {
1158         signal_changed (CONTENT);
1159         signal_changed (NAME);
1160 }
1161
1162 void
1163 Film::playlist_order_changed ()
1164 {
1165         signal_changed (CONTENT_ORDER);
1166 }
1167
1168 int
1169 Film::audio_frame_rate () const
1170 {
1171         BOOST_FOREACH (shared_ptr<Content> i, content ()) {
1172                 if (i->audio && i->audio->has_rate_above_48k ()) {
1173                         return 96000;
1174                 }
1175         }
1176
1177         return 48000;
1178 }
1179
1180 void
1181 Film::set_sequence (bool s)
1182 {
1183         _sequence = s;
1184         _playlist->set_sequence (s);
1185         signal_changed (SEQUENCE);
1186 }
1187
1188 /** @return Size of the largest possible image in whatever resolution we are using */
1189 dcp::Size
1190 Film::full_frame () const
1191 {
1192         switch (_resolution) {
1193         case RESOLUTION_2K:
1194                 return dcp::Size (2048, 1080);
1195         case RESOLUTION_4K:
1196                 return dcp::Size (4096, 2160);
1197         }
1198
1199         DCPOMATIC_ASSERT (false);
1200         return dcp::Size ();
1201 }
1202
1203 /** @return Size of the frame */
1204 dcp::Size
1205 Film::frame_size () const
1206 {
1207         return fit_ratio_within (container()->ratio(), full_frame ());
1208 }
1209
1210 /** @param recipient KDM recipient certificate.
1211  *  @param trusted_devices Certificates of other trusted devices (can be empty).
1212  *  @param cpl_file CPL filename.
1213  *  @param from KDM from time expressed as a local time with an offset from UTC.
1214  *  @param until KDM to time expressed as a local time with an offset from UTC.
1215  *  @param formulation KDM formulation to use.
1216  */
1217 dcp::EncryptedKDM
1218 Film::make_kdm (
1219         dcp::Certificate recipient,
1220         vector<dcp::Certificate> trusted_devices,
1221         boost::filesystem::path cpl_file,
1222         dcp::LocalTime from,
1223         dcp::LocalTime until,
1224         dcp::Formulation formulation
1225         ) const
1226 {
1227         shared_ptr<const dcp::CPL> cpl (new dcp::CPL (cpl_file));
1228         shared_ptr<const dcp::CertificateChain> signer = Config::instance()->signer_chain ();
1229         if (!signer->valid ()) {
1230                 throw InvalidSignerError ();
1231         }
1232
1233         /* Find keys that have been added to imported, encrypted DCP content */
1234         list<dcp::DecryptedKDMKey> imported_keys;
1235         BOOST_FOREACH (shared_ptr<Content> i, content()) {
1236                 shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
1237                 if (d && d->kdm()) {
1238                         dcp::DecryptedKDM kdm (d->kdm().get(), Config::instance()->decryption_chain()->key().get());
1239                         list<dcp::DecryptedKDMKey> keys = kdm.keys ();
1240                         copy (keys.begin(), keys.end(), back_inserter (imported_keys));
1241                 }
1242         }
1243
1244         map<shared_ptr<const dcp::ReelMXF>, dcp::Key> keys;
1245
1246         BOOST_FOREACH(shared_ptr<const dcp::ReelAsset> i, cpl->reel_assets ()) {
1247                 shared_ptr<const dcp::ReelMXF> mxf = boost::dynamic_pointer_cast<const dcp::ReelMXF> (i);
1248                 if (!mxf || !mxf->key_id()) {
1249                         continue;
1250                 }
1251
1252                 /* Get any imported key for this ID */
1253                 bool done = false;
1254                 BOOST_FOREACH (dcp::DecryptedKDMKey j, imported_keys) {
1255                         if (j.id() == mxf->key_id().get()) {
1256                                 LOG_GENERAL ("Using imported key for %1", mxf->key_id().get());
1257                                 keys[mxf] = j.key();
1258                                 done = true;
1259                         }
1260                 }
1261
1262                 if (!done) {
1263                         /* No imported key; it must be an asset that we encrypted */
1264                         LOG_GENERAL ("Using our own key for %1", mxf->key_id().get());
1265                         keys[mxf] = key();
1266                 }
1267         }
1268
1269         return dcp::DecryptedKDM (
1270                 cpl->id(), keys, from, until, cpl->content_title_text(), cpl->content_title_text(), dcp::LocalTime().as_string()
1271                 ).encrypt (signer, recipient, trusted_devices, formulation);
1272 }
1273
1274 /** @param screens Screens to make KDMs for.
1275  *  @param cpl_file Path to CPL to make KDMs for.
1276  *  @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema.
1277  *  @param until KDM to time expressed as a local time in the time zone of the Screen's Cinema.
1278  *  @param formulation KDM formulation to use.
1279  */
1280 list<ScreenKDM>
1281 Film::make_kdms (
1282         list<shared_ptr<Screen> > screens,
1283         boost::filesystem::path cpl_file,
1284         boost::posix_time::ptime from,
1285         boost::posix_time::ptime until,
1286         dcp::Formulation formulation
1287         ) const
1288 {
1289         list<ScreenKDM> kdms;
1290
1291         BOOST_FOREACH (shared_ptr<Screen> i, screens) {
1292                 if (i->recipient) {
1293                         dcp::EncryptedKDM const kdm = make_kdm (
1294                                 i->recipient.get(),
1295                                 i->trusted_devices,
1296                                 cpl_file,
1297                                 dcp::LocalTime (from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
1298                                 dcp::LocalTime (until, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
1299                                 formulation
1300                                 );
1301
1302                         kdms.push_back (ScreenKDM (i, kdm));
1303                 }
1304         }
1305
1306         return kdms;
1307 }
1308
1309 /** @return The approximate disk space required to encode a DCP of this film with the
1310  *  current settings, in bytes.
1311  */
1312 uint64_t
1313 Film::required_disk_space () const
1314 {
1315         return _playlist->required_disk_space (j2k_bandwidth(), audio_channels(), audio_frame_rate());
1316 }
1317
1318 /** This method checks the disk that the Film is on and tries to decide whether or not
1319  *  there will be enough space to make a DCP for it.  If so, true is returned; if not,
1320  *  false is returned and required and available are filled in with the amount of disk space
1321  *  required and available respectively (in Gb).
1322  *
1323  *  Note: the decision made by this method isn't, of course, 100% reliable.
1324  */
1325 bool
1326 Film::should_be_enough_disk_space (double& required, double& available, bool& can_hard_link) const
1327 {
1328         /* Create a test file and see if we can hard-link it */
1329         boost::filesystem::path test = internal_video_asset_dir() / "test";
1330         boost::filesystem::path test2 = internal_video_asset_dir() / "test2";
1331         can_hard_link = true;
1332         FILE* f = fopen_boost (test, "w");
1333         if (f) {
1334                 fclose (f);
1335                 boost::system::error_code ec;
1336                 boost::filesystem::create_hard_link (test, test2, ec);
1337                 if (ec) {
1338                         can_hard_link = false;
1339                 }
1340                 boost::filesystem::remove (test);
1341                 boost::filesystem::remove (test2);
1342         }
1343
1344         boost::filesystem::space_info s = boost::filesystem::space (internal_video_asset_dir ());
1345         required = double (required_disk_space ()) / 1073741824.0f;
1346         if (!can_hard_link) {
1347                 required *= 2;
1348         }
1349         available = double (s.available) / 1073741824.0f;
1350         return (available - required) > 1;
1351 }
1352
1353 string
1354 Film::subtitle_language () const
1355 {
1356         set<string> languages;
1357
1358         ContentList cl = content ();
1359         BOOST_FOREACH (shared_ptr<Content>& c, cl) {
1360                 if (c->subtitle) {
1361                         languages.insert (c->subtitle->language ());
1362                 }
1363         }
1364
1365         string all;
1366         BOOST_FOREACH (string s, languages) {
1367                 if (!all.empty ()) {
1368                         all += "/" + s;
1369                 } else {
1370                         all += s;
1371                 }
1372         }
1373
1374         return all;
1375 }
1376
1377 /** Change the gains of the supplied AudioMapping to make it a default
1378  *  for this film.  The defaults are guessed based on what processor (if any)
1379  *  is in use, the number of input channels and any filename supplied.
1380  */
1381 void
1382 Film::make_audio_mapping_default (AudioMapping& mapping, optional<boost::filesystem::path> filename) const
1383 {
1384         static string const regex[] = {
1385                 ".*[\\._-]L[\\._-].*",
1386                 ".*[\\._-]R[\\._-].*",
1387                 ".*[\\._-]C[\\._-].*",
1388                 ".*[\\._-]Lfe[\\._-].*",
1389                 ".*[\\._-]Ls[\\._-].*",
1390                 ".*[\\._-]Rs[\\._-].*"
1391         };
1392
1393         static int const regexes = sizeof(regex) / sizeof(*regex);
1394
1395         if (audio_processor ()) {
1396                 audio_processor()->make_audio_mapping_default (mapping);
1397         } else {
1398                 mapping.make_zero ();
1399                 if (mapping.input_channels() == 1) {
1400                         bool guessed = false;
1401
1402                         /* See if we can guess where this stream should go */
1403                         if (filename) {
1404                                 for (int i = 0; i < regexes; ++i) {
1405                                         boost::regex e (regex[i], boost::regex::icase);
1406                                         if (boost::regex_match (filename->string(), e) && i < mapping.output_channels()) {
1407                                                 mapping.set (0, i, 1);
1408                                                 guessed = true;
1409                                         }
1410                                 }
1411                         }
1412
1413                         if (!guessed) {
1414                                 /* If we have no idea, just put it on centre */
1415                                 mapping.set (0, static_cast<int> (dcp::CENTRE), 1);
1416                         }
1417                 } else {
1418                         /* 1:1 mapping */
1419                         for (int i = 0; i < min (mapping.input_channels(), mapping.output_channels()); ++i) {
1420                                 mapping.set (i, i, 1);
1421                         }
1422                 }
1423         }
1424 }
1425
1426 /** @return The names of the channels that audio contents' outputs are passed into;
1427  *  this is either the DCP or a AudioProcessor.
1428  */
1429 vector<string>
1430 Film::audio_output_names () const
1431 {
1432         if (audio_processor ()) {
1433                 return audio_processor()->input_names ();
1434         }
1435
1436         DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16);
1437
1438         vector<string> n;
1439
1440         for (int i = 0; i < audio_channels(); ++i) {
1441                 n.push_back (short_audio_channel_name (i));
1442         }
1443
1444         return n;
1445 }
1446
1447 void
1448 Film::repeat_content (ContentList c, int n)
1449 {
1450         _playlist->repeat (c, n);
1451 }
1452
1453 void
1454 Film::remove_content (ContentList c)
1455 {
1456         _playlist->remove (c);
1457 }
1458
1459 void
1460 Film::audio_analysis_finished ()
1461 {
1462         /* XXX */
1463 }
1464
1465 list<DCPTimePeriod>
1466 Film::reels () const
1467 {
1468         list<DCPTimePeriod> p;
1469         DCPTime const len = length().ceil (video_frame_rate ());
1470
1471         switch (reel_type ()) {
1472         case REELTYPE_SINGLE:
1473                 p.push_back (DCPTimePeriod (DCPTime (), len));
1474                 break;
1475         case REELTYPE_BY_VIDEO_CONTENT:
1476         {
1477                 optional<DCPTime> last_split;
1478                 shared_ptr<Content> last_video;
1479                 BOOST_FOREACH (shared_ptr<Content> c, content ()) {
1480                         if (c->video) {
1481                                 BOOST_FOREACH (DCPTime t, c->reel_split_points()) {
1482                                         if (last_split) {
1483                                                 p.push_back (DCPTimePeriod (last_split.get(), t));
1484                                         }
1485                                         last_split = t;
1486                                 }
1487                                 last_video = c;
1488                         }
1489                 }
1490
1491                 DCPTime video_end = last_video ? last_video->end() : DCPTime(0);
1492                 if (last_split) {
1493                         /* Definitely go from the last split to the end of the video content */
1494                         p.push_back (DCPTimePeriod (last_split.get(), video_end));
1495                 }
1496
1497                 if (video_end < len) {
1498                         /* And maybe go after that as well if there is any non-video hanging over the end */
1499                         p.push_back (DCPTimePeriod (video_end, len));
1500                 }
1501                 break;
1502         }
1503         case REELTYPE_BY_LENGTH:
1504         {
1505                 DCPTime current;
1506                 /* Integer-divide reel length by the size of one frame to give the number of frames per reel */
1507                 Frame const reel_in_frames = _reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8);
1508                 while (current < len) {
1509                         DCPTime end = min (len, current + DCPTime::from_frames (reel_in_frames, video_frame_rate ()));
1510                         p.push_back (DCPTimePeriod (current, end));
1511                         current = end;
1512                 }
1513                 break;
1514         }
1515         }
1516
1517         return p;
1518 }
1519
1520 /** @param period A period within the DCP
1521  *  @return Name of the content which most contributes to the given period.
1522  */
1523 string
1524 Film::content_summary (DCPTimePeriod period) const
1525 {
1526         return _playlist->content_summary (period);
1527 }
1528
1529 list<string>
1530 Film::fix_conflicting_settings ()
1531 {
1532         list<string> notes;
1533
1534         list<boost::filesystem::path> was_referencing;
1535         BOOST_FOREACH (shared_ptr<Content> i, content()) {
1536                 shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
1537                 if (d) {
1538                         list<string> reasons;
1539                         bool was = false;
1540                         if (!d->can_reference_video(reasons) && d->reference_video()) {
1541                                 d->set_reference_video (false);
1542                                 was = true;
1543                         }
1544                         if (!d->can_reference_audio(reasons) && d->reference_audio()) {
1545                                 d->set_reference_audio (false);
1546                                 was = true;
1547                         }
1548                         if (!d->can_reference_subtitle(reasons) && d->reference_subtitle()) {
1549                                 d->set_reference_subtitle (false);
1550                                 was = true;
1551                         }
1552                         if (was) {
1553                                 was_referencing.push_back (d->path(0).parent_path().filename());
1554                         }
1555                 }
1556         }
1557
1558         BOOST_FOREACH (boost::filesystem::path d, was_referencing) {
1559                 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()));
1560         }
1561
1562         return notes;
1563 }
1564
1565 void
1566 Film::use_template (string name)
1567 {
1568         _template_film.reset (new Film (optional<boost::filesystem::path>()));
1569         _template_film->read_metadata (Config::instance()->template_path (name));
1570         _use_isdcf_name = _template_film->_use_isdcf_name;
1571         _dcp_content_type = _template_film->_dcp_content_type;
1572         _container = _template_film->_container;
1573         _resolution = _template_film->_resolution;
1574         _j2k_bandwidth = _template_film->_j2k_bandwidth;
1575         _video_frame_rate = _template_film->_video_frame_rate;
1576         _signed = _template_film->_signed;
1577         _encrypted = _template_film->_encrypted;
1578         _audio_channels = _template_film->_audio_channels;
1579         _sequence = _template_film->_sequence;
1580         _three_d = _template_film->_three_d;
1581         _interop = _template_film->_interop;
1582         _audio_processor = _template_film->_audio_processor;
1583         _reel_type = _template_film->_reel_type;
1584         _reel_length = _template_film->_reel_length;
1585         _upload_after_make_dcp = _template_film->_upload_after_make_dcp;
1586 }