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