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