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