Disable show audio button when there is no audio (#73).
[dcpomatic.git] / src / lib / film.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <stdexcept>
21 #include <iostream>
22 #include <algorithm>
23 #include <fstream>
24 #include <cstdlib>
25 #include <sstream>
26 #include <iomanip>
27 #include <unistd.h>
28 #include <boost/filesystem.hpp>
29 #include <boost/algorithm/string.hpp>
30 #include <boost/lexical_cast.hpp>
31 #include <boost/date_time.hpp>
32 #include "film.h"
33 #include "format.h"
34 #include "job.h"
35 #include "filter.h"
36 #include "transcoder.h"
37 #include "util.h"
38 #include "job_manager.h"
39 #include "ab_transcode_job.h"
40 #include "transcode_job.h"
41 #include "scp_dcp_job.h"
42 #include "log.h"
43 #include "options.h"
44 #include "exceptions.h"
45 #include "examine_content_job.h"
46 #include "scaler.h"
47 #include "decoder_factory.h"
48 #include "config.h"
49 #include "version.h"
50 #include "ui_signaller.h"
51 #include "video_decoder.h"
52 #include "audio_decoder.h"
53 #include "external_audio_decoder.h"
54 #include "analyse_audio_job.h"
55
56 #include "i18n.h"
57
58 using std::string;
59 using std::stringstream;
60 using std::multimap;
61 using std::pair;
62 using std::map;
63 using std::vector;
64 using std::ifstream;
65 using std::ofstream;
66 using std::setfill;
67 using std::min;
68 using std::make_pair;
69 using std::endl;
70 using boost::shared_ptr;
71 using boost::lexical_cast;
72 using boost::to_upper_copy;
73 using boost::ends_with;
74 using boost::starts_with;
75 using boost::optional;
76 using libdcp::Size;
77
78 int const Film::state_version = 4;
79
80 /** Construct a Film object in a given directory, reading any metadata
81  *  file that exists in that directory.  An exception will be thrown if
82  *  must_exist is true and the specified directory does not exist.
83  *
84  *  @param d Film directory.
85  *  @param must_exist true to throw an exception if does not exist.
86  */
87
88 Film::Film (string d, bool must_exist)
89         : _use_dci_name (true)
90         , _trust_content_header (true)
91         , _dcp_content_type (0)
92         , _format (0)
93         , _scaler (Scaler::from_id ("bicubic"))
94         , _trim_start (0)
95         , _trim_end (0)
96         , _dcp_ab (false)
97         , _use_content_audio (true)
98         , _audio_gain (0)
99         , _audio_delay (0)
100         , _still_duration (10)
101         , _with_subtitles (false)
102         , _subtitle_offset (0)
103         , _subtitle_scale (1)
104         , _colour_lut (0)
105         , _j2k_bandwidth (200000000)
106         , _dci_metadata (Config::instance()->default_dci_metadata ())
107         , _dcp_frame_rate (0)
108         , _source_frame_rate (0)
109         , _dirty (false)
110 {
111         set_dci_date_today ();
112         
113         /* Make state.directory a complete path without ..s (where possible)
114            (Code swiped from Adam Bowen on stackoverflow)
115         */
116         
117         boost::filesystem::path p (boost::filesystem::system_complete (d));
118         boost::filesystem::path result;
119         for (boost::filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
120                 if (*i == "..") {
121                         if (boost::filesystem::is_symlink (result) || result.filename() == "..") {
122                                 result /= *i;
123                         } else {
124                                 result = result.parent_path ();
125                         }
126                 } else if (*i != ".") {
127                         result /= *i;
128                 }
129         }
130
131         set_directory (result.string ());
132         
133         if (!boost::filesystem::exists (directory())) {
134                 if (must_exist) {
135                         throw OpenFileError (directory());
136                 } else {
137                         boost::filesystem::create_directory (directory());
138                 }
139         }
140
141         _external_audio_stream = ExternalAudioStream::create ();
142         
143         if (must_exist) {
144                 read_metadata ();
145         }
146
147         _log = new FileLog (file ("log"));
148 }
149
150 Film::Film (Film const & o)
151         : boost::enable_shared_from_this<Film> (o)
152         , _log (0)
153         , _directory         (o._directory)
154         , _name              (o._name)
155         , _use_dci_name      (o._use_dci_name)
156         , _content           (o._content)
157         , _trust_content_header (o._trust_content_header)
158         , _dcp_content_type  (o._dcp_content_type)
159         , _format            (o._format)
160         , _crop              (o._crop)
161         , _filters           (o._filters)
162         , _scaler            (o._scaler)
163         , _trim_start        (o._trim_start)
164         , _trim_end          (o._trim_end)
165         , _dcp_ab            (o._dcp_ab)
166         , _content_audio_stream (o._content_audio_stream)
167         , _external_audio    (o._external_audio)
168         , _use_content_audio (o._use_content_audio)
169         , _audio_gain        (o._audio_gain)
170         , _audio_delay       (o._audio_delay)
171         , _still_duration    (o._still_duration)
172         , _subtitle_stream   (o._subtitle_stream)
173         , _with_subtitles    (o._with_subtitles)
174         , _subtitle_offset   (o._subtitle_offset)
175         , _subtitle_scale    (o._subtitle_scale)
176         , _colour_lut        (o._colour_lut)
177         , _j2k_bandwidth     (o._j2k_bandwidth)
178         , _dci_metadata      (o._dci_metadata)
179         , _dci_date          (o._dci_date)
180         , _dcp_frame_rate    (o._dcp_frame_rate)
181         , _size              (o._size)
182         , _length            (o._length)
183         , _dcp_intrinsic_duration (o._dcp_intrinsic_duration)
184         , _content_digest    (o._content_digest)
185         , _content_audio_streams (o._content_audio_streams)
186         , _external_audio_stream (o._external_audio_stream)
187         , _subtitle_streams  (o._subtitle_streams)
188         , _source_frame_rate (o._source_frame_rate)
189         , _dirty             (o._dirty)
190 {
191
192 }
193
194 Film::~Film ()
195 {
196         delete _log;
197 }
198
199 string
200 Film::video_state_identifier () const
201 {
202         assert (format ());
203
204         pair<string, string> f = Filter::ffmpeg_strings (filters());
205
206         stringstream s;
207         s << format()->id()
208           << "_" << content_digest()
209           << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom
210           << "_" << _dcp_frame_rate
211           << "_" << f.first << "_" << f.second
212           << "_" << scaler()->id()
213           << "_" << j2k_bandwidth()
214           << "_" << boost::lexical_cast<int> (colour_lut());
215
216         if (dcp_ab()) {
217                 pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
218                 s << "ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
219         }
220
221         return s.str ();
222 }
223           
224 /** @return The path to the directory to write video frame info files to */
225 string
226 Film::info_dir () const
227 {
228         boost::filesystem::path p;
229         p /= "info";
230         p /= video_state_identifier ();
231         return dir (p.string());
232 }
233
234 string
235 Film::video_mxf_dir () const
236 {
237         boost::filesystem::path p;
238         return dir ("video");
239 }
240
241 string
242 Film::video_mxf_filename () const
243 {
244         return video_state_identifier() + ".mxf";
245 }
246
247 string
248 Film::audio_analysis_path () const
249 {
250         boost::filesystem::path p;
251         p /= "analysis";
252         p /= content_digest();
253         return file (p.string ());
254 }
255
256 /** Add suitable Jobs to the JobManager to create a DCP for this Film */
257 void
258 Film::make_dcp ()
259 {
260         set_dci_date_today ();
261         
262         if (dcp_name().find ("/") != string::npos) {
263                 throw BadSettingError (_("name"), _("cannot contain slashes"));
264         }
265         
266         log()->log (String::compose ("DVD-o-matic %1 git %2 using %3", dvdomatic_version, dvdomatic_git_commit, dependency_version_summary()));
267
268         {
269                 char buffer[128];
270                 gethostname (buffer, sizeof (buffer));
271                 log()->log (String::compose ("Starting to make DCP on %1", buffer));
272         }
273         
274         log()->log (String::compose ("Content is %1; type %2", content_path(), (content_type() == STILL ? _("still") : _("video"))));
275         if (length()) {
276                 log()->log (String::compose ("Content length %1", length().get()));
277         }
278         log()->log (String::compose ("Content digest %1", content_digest()));
279         log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate()));
280         log()->log (String::compose ("%1 threads", Config::instance()->num_local_encoding_threads()));
281         log()->log (String::compose ("J2K bandwidth %1", j2k_bandwidth()));
282 #ifdef DVDOMATIC_DEBUG
283         log()->log ("DVD-o-matic built in debug mode.");
284 #else
285         log()->log ("DVD-o-matic built in optimised mode.");
286 #endif
287 #ifdef LIBDCP_DEBUG
288         log()->log ("libdcp built in debug mode.");
289 #else
290         log()->log ("libdcp built in optimised mode.");
291 #endif
292         pair<string, int> const c = cpu_info ();
293         log()->log (String::compose ("CPU: %1, %2 processors", c.first, c.second));
294         
295         if (format() == 0) {
296                 throw MissingSettingError (_("format"));
297         }
298
299         if (content().empty ()) {
300                 throw MissingSettingError (_("content"));
301         }
302
303         if (dcp_content_type() == 0) {
304                 throw MissingSettingError (_("content type"));
305         }
306
307         if (name().empty()) {
308                 throw MissingSettingError (_("name"));
309         }
310
311         DecodeOptions od;
312         od.decode_subtitles = with_subtitles ();
313
314         shared_ptr<Job> r;
315
316         if (dcp_ab()) {
317                 r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
318         } else {
319                 r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
320         }
321 }
322
323 /** Start a job to analyse the audio of our content file */
324 void
325 Film::analyse_audio ()
326 {
327         if (_analyse_audio_job) {
328                 return;
329         }
330
331         _analyse_audio_job.reset (new AnalyseAudioJob (shared_from_this()));
332         _analyse_audio_job->Finished.connect (bind (&Film::analyse_audio_finished, this));
333         JobManager::instance()->add (_analyse_audio_job);
334 }
335
336 /** Start a job to examine our content file */
337 void
338 Film::examine_content ()
339 {
340         if (_examine_content_job) {
341                 return;
342         }
343
344         _examine_content_job.reset (new ExamineContentJob (shared_from_this()));
345         _examine_content_job->Finished.connect (bind (&Film::examine_content_finished, this));
346         JobManager::instance()->add (_examine_content_job);
347 }
348
349 void
350 Film::analyse_audio_finished ()
351 {
352         ensure_ui_thread ();
353         _analyse_audio_job.reset ();
354
355         AudioAnalysisFinished ();
356 }
357
358 void
359 Film::examine_content_finished ()
360 {
361         _examine_content_job.reset ();
362 }
363
364 /** Start a job to send our DCP to the configured TMS */
365 void
366 Film::send_dcp_to_tms ()
367 {
368         shared_ptr<Job> j (new SCPDCPJob (shared_from_this()));
369         JobManager::instance()->add (j);
370 }
371
372 /** Count the number of frames that have been encoded for this film.
373  *  @return frame count.
374  */
375 int
376 Film::encoded_frames () const
377 {
378         if (format() == 0) {
379                 return 0;
380         }
381
382         int N = 0;
383         for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (info_dir ()); i != boost::filesystem::directory_iterator(); ++i) {
384                 ++N;
385                 boost::this_thread::interruption_point ();
386         }
387
388         return N;
389 }
390
391 /** Write state to our `metadata' file */
392 void
393 Film::write_metadata () const
394 {
395         boost::mutex::scoped_lock lm (_state_mutex);
396
397         boost::filesystem::create_directories (directory());
398
399         string const m = file ("metadata");
400         ofstream f (m.c_str ());
401         if (!f.good ()) {
402                 throw CreateFileError (m);
403         }
404
405         f << "version " << state_version << endl;
406
407         /* User stuff */
408         f << "name " << _name << endl;
409         f << "use_dci_name " << _use_dci_name << endl;
410         f << "content " << _content << endl;
411         f << "trust_content_header " << (_trust_content_header ? "1" : "0") << endl;
412         if (_dcp_content_type) {
413                 f << "dcp_content_type " << _dcp_content_type->dci_name () << endl;
414         }
415         if (_format) {
416                 f << "format " << _format->as_metadata () << endl;
417         }
418         f << "left_crop " << _crop.left << endl;
419         f << "right_crop " << _crop.right << endl;
420         f << "top_crop " << _crop.top << endl;
421         f << "bottom_crop " << _crop.bottom << endl;
422         for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
423                 f << "filter " << (*i)->id () << endl;
424         }
425         f << "scaler " << _scaler->id () << endl;
426         f << "trim_start " << _trim_start << endl;
427         f << "trim_end " << _trim_end << endl;
428         f << "dcp_ab " << (_dcp_ab ? "1" : "0") << endl;
429         if (_content_audio_stream) {
430                 f << "selected_content_audio_stream " << _content_audio_stream->to_string() << endl;
431         }
432         for (vector<string>::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) {
433                 f << "external_audio " << *i << endl;
434         }
435         f << "use_content_audio " << (_use_content_audio ? "1" : "0") << endl;
436         f << "audio_gain " << _audio_gain << endl;
437         f << "audio_delay " << _audio_delay << endl;
438         f << "still_duration " << _still_duration << endl;
439         if (_subtitle_stream) {
440                 f << "selected_subtitle_stream " << _subtitle_stream->to_string() << endl;
441         }
442         f << "with_subtitles " << _with_subtitles << endl;
443         f << "subtitle_offset " << _subtitle_offset << endl;
444         f << "subtitle_scale " << _subtitle_scale << endl;
445         f << "colour_lut " << _colour_lut << endl;
446         f << "j2k_bandwidth " << _j2k_bandwidth << endl;
447         _dci_metadata.write (f);
448         f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << endl;
449         f << "dcp_frame_rate " << _dcp_frame_rate << endl;
450         f << "width " << _size.width << endl;
451         f << "height " << _size.height << endl;
452         f << "length " << _length.get_value_or(0) << endl;
453         f << "dcp_intrinsic_duration " << _dcp_intrinsic_duration.get_value_or(0) << endl;
454         f << "content_digest " << _content_digest << endl;
455
456         for (vector<shared_ptr<AudioStream> >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
457                 f << "content_audio_stream " << (*i)->to_string () << endl;
458         }
459
460         f << "external_audio_stream " << _external_audio_stream->to_string() << endl;
461
462         for (vector<shared_ptr<SubtitleStream> >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
463                 f << "subtitle_stream " << (*i)->to_string () << endl;
464         }
465
466         f << "source_frame_rate " << _source_frame_rate << endl;
467         
468         _dirty = false;
469 }
470
471 /** Read state from our metadata file */
472 void
473 Film::read_metadata ()
474 {
475         boost::mutex::scoped_lock lm (_state_mutex);
476
477         _external_audio.clear ();
478         _content_audio_streams.clear ();
479         _subtitle_streams.clear ();
480
481         boost::optional<int> version;
482
483         /* Backward compatibility things */
484         boost::optional<int> audio_sample_rate;
485         boost::optional<int> audio_stream_index;
486         boost::optional<int> subtitle_stream_index;
487
488         ifstream f (file ("metadata").c_str());
489         if (!f.good()) {
490                 throw OpenFileError (file ("metadata"));
491         }
492         
493         multimap<string, string> kv = read_key_value (f);
494
495         /* We need version before anything else */
496         multimap<string, string>::iterator v = kv.find ("version");
497         if (v != kv.end ()) {
498                 version = atoi (v->second.c_str());
499         }
500         
501         for (multimap<string, string>::const_iterator i = kv.begin(); i != kv.end(); ++i) {
502                 string const k = i->first;
503                 string const v = i->second;
504
505                 if (k == "audio_sample_rate") {
506                         audio_sample_rate = atoi (v.c_str());
507                 }
508
509                 /* User-specified stuff */
510                 if (k == "name") {
511                         _name = v;
512                 } else if (k == "use_dci_name") {
513                         _use_dci_name = (v == "1");
514                 } else if (k == "content") {
515                         _content = v;
516                 } else if (k == "trust_content_header") {
517                         _trust_content_header = (v == "1");
518                 } else if (k == "dcp_content_type") {
519                         if (version < 3) {
520                                 _dcp_content_type = DCPContentType::from_pretty_name (v);
521                         } else {
522                                 _dcp_content_type = DCPContentType::from_dci_name (v);
523                         }
524                 } else if (k == "format") {
525                         _format = Format::from_metadata (v);
526                 } else if (k == "left_crop") {
527                         _crop.left = atoi (v.c_str ());
528                 } else if (k == "right_crop") {
529                         _crop.right = atoi (v.c_str ());
530                 } else if (k == "top_crop") {
531                         _crop.top = atoi (v.c_str ());
532                 } else if (k == "bottom_crop") {
533                         _crop.bottom = atoi (v.c_str ());
534                 } else if (k == "filter") {
535                         _filters.push_back (Filter::from_id (v));
536                 } else if (k == "scaler") {
537                         _scaler = Scaler::from_id (v);
538                 } else if ( ((!version || version < 2) && k == "dcp_trim_start") || k == "trim_start") {
539                         _trim_start = atoi (v.c_str ());
540                 } else if ( ((!version || version < 2) && k == "dcp_trim_end") || k == "trim_end") {
541                         _trim_end = atoi (v.c_str ());
542                 } else if (k == "dcp_ab") {
543                         _dcp_ab = (v == "1");
544                 } else if (k == "selected_content_audio_stream" || (!version && k == "selected_audio_stream")) {
545                         if (!version) {
546                                 audio_stream_index = atoi (v.c_str ());
547                         } else {
548                                 _content_audio_stream = audio_stream_factory (v, version);
549                         }
550                 } else if (k == "external_audio") {
551                         _external_audio.push_back (v);
552                 } else if (k == "use_content_audio") {
553                         _use_content_audio = (v == "1");
554                 } else if (k == "audio_gain") {
555                         _audio_gain = atof (v.c_str ());
556                 } else if (k == "audio_delay") {
557                         _audio_delay = atoi (v.c_str ());
558                 } else if (k == "still_duration") {
559                         _still_duration = atoi (v.c_str ());
560                 } else if (k == "selected_subtitle_stream") {
561                         if (!version) {
562                                 subtitle_stream_index = atoi (v.c_str ());
563                         } else {
564                                 _subtitle_stream = subtitle_stream_factory (v, version);
565                         }
566                 } else if (k == "with_subtitles") {
567                         _with_subtitles = (v == "1");
568                 } else if (k == "subtitle_offset") {
569                         _subtitle_offset = atoi (v.c_str ());
570                 } else if (k == "subtitle_scale") {
571                         _subtitle_scale = atof (v.c_str ());
572                 } else if (k == "colour_lut") {
573                         _colour_lut = atoi (v.c_str ());
574                 } else if (k == "j2k_bandwidth") {
575                         _j2k_bandwidth = atoi (v.c_str ());
576                 } else if (k == "dci_date") {
577                         _dci_date = boost::gregorian::from_undelimited_string (v);
578                 } else if (k == "dcp_frame_rate") {
579                         _dcp_frame_rate = atoi (v.c_str ());
580                 }
581
582                 _dci_metadata.read (k, v);
583                 
584                 /* Cached stuff */
585                 if (k == "width") {
586                         _size.width = atoi (v.c_str ());
587                 } else if (k == "height") {
588                         _size.height = atoi (v.c_str ());
589                 } else if (k == "length") {
590                         int const vv = atoi (v.c_str ());
591                         if (vv) {
592                                 _length = vv;
593                         }
594                 } else if (k == "dcp_intrinsic_duration") {
595                         int const vv = atoi (v.c_str ());
596                         if (vv) {
597                                 _dcp_intrinsic_duration = vv;
598                         }
599                 } else if (k == "content_digest") {
600                         _content_digest = v;
601                 } else if (k == "content_audio_stream" || (!version && k == "audio_stream")) {
602                         _content_audio_streams.push_back (audio_stream_factory (v, version));
603                 } else if (k == "external_audio_stream") {
604                         _external_audio_stream = audio_stream_factory (v, version);
605                 } else if (k == "subtitle_stream") {
606                         _subtitle_streams.push_back (subtitle_stream_factory (v, version));
607                 } else if (k == "source_frame_rate") {
608                         _source_frame_rate = atof (v.c_str ());
609                 } else if (version < 4 && k == "frames_per_second") {
610                         _source_frame_rate = atof (v.c_str ());
611                         /* Fill in what would have been used for DCP frame rate by the older version */
612                         _dcp_frame_rate = best_dcp_frame_rate (_source_frame_rate);
613                 }
614         }
615
616         if (!version) {
617                 if (audio_sample_rate) {
618                         /* version < 1 didn't specify sample rate in the audio streams, so fill it in here */
619                         for (vector<shared_ptr<AudioStream> >::iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
620                                 (*i)->set_sample_rate (audio_sample_rate.get());
621                         }
622                 }
623
624                 /* also the selected stream was specified as an index */
625                 if (audio_stream_index && audio_stream_index.get() >= 0 && audio_stream_index.get() < (int) _content_audio_streams.size()) {
626                         _content_audio_stream = _content_audio_streams[audio_stream_index.get()];
627                 }
628
629                 /* similarly the subtitle */
630                 if (subtitle_stream_index && subtitle_stream_index.get() >= 0 && subtitle_stream_index.get() < (int) _subtitle_streams.size()) {
631                         _subtitle_stream = _subtitle_streams[subtitle_stream_index.get()];
632                 }
633         }
634                 
635         _dirty = false;
636 }
637
638 libdcp::Size
639 Film::cropped_size (libdcp::Size s) const
640 {
641         boost::mutex::scoped_lock lm (_state_mutex);
642         s.width -= _crop.left + _crop.right;
643         s.height -= _crop.top + _crop.bottom;
644         return s;
645 }
646
647 /** Given a directory name, return its full path within the Film's directory.
648  *  The directory (and its parents) will be created if they do not exist.
649  */
650 string
651 Film::dir (string d) const
652 {
653         boost::mutex::scoped_lock lm (_directory_mutex);
654         
655         boost::filesystem::path p;
656         p /= _directory;
657         p /= d;
658         
659         boost::filesystem::create_directories (p);
660         
661         return p.string ();
662 }
663
664 /** Given a file or directory name, return its full path within the Film's directory.
665  *  _directory_mutex must not be locked on entry.
666  *  Any required parent directories will be created.
667  */
668 string
669 Film::file (string f) const
670 {
671         boost::mutex::scoped_lock lm (_directory_mutex);
672
673         boost::filesystem::path p;
674         p /= _directory;
675         p /= f;
676
677         boost::filesystem::create_directories (p.parent_path ());
678         
679         return p.string ();
680 }
681
682 /** @return full path of the content (actual video) file
683  *  of the Film.
684  */
685 string
686 Film::content_path () const
687 {
688         boost::mutex::scoped_lock lm (_state_mutex);
689         if (boost::filesystem::path(_content).has_root_directory ()) {
690                 return _content;
691         }
692
693         return file (_content);
694 }
695
696 ContentType
697 Film::content_type () const
698 {
699         if (boost::filesystem::is_directory (_content)) {
700                 /* Directory of images, we assume */
701                 return VIDEO;
702         }
703
704         if (still_image_file (_content)) {
705                 return STILL;
706         }
707
708         return VIDEO;
709 }
710
711 /** @return The sampling rate that we will resample the audio to */
712 int
713 Film::target_audio_sample_rate () const
714 {
715         if (!audio_stream()) {
716                 return 0;
717         }
718         
719         /* Resample to a DCI-approved sample rate */
720         double t = dcp_audio_sample_rate (audio_stream()->sample_rate());
721
722         FrameRateConversion frc (source_frame_rate(), dcp_frame_rate());
723
724         /* Compensate if the DCP is being run at a different frame rate
725            to the source; that is, if the video is run such that it will
726            look different in the DCP compared to the source (slower or faster).
727            skip/repeat doesn't come into effect here.
728         */
729
730         if (frc.change_speed) {
731                 t *= source_frame_rate() * frc.factor() / dcp_frame_rate();
732         }
733
734         return rint (t);
735 }
736
737 int
738 Film::still_duration_in_frames () const
739 {
740         return still_duration() * source_frame_rate();
741 }
742
743 /** @return a DCI-compliant name for a DCP of this film */
744 string
745 Film::dci_name (bool if_created_now) const
746 {
747         stringstream d;
748
749         string fixed_name = to_upper_copy (name());
750         for (size_t i = 0; i < fixed_name.length(); ++i) {
751                 if (fixed_name[i] == ' ') {
752                         fixed_name[i] = '-';
753                 }
754         }
755
756         /* Spec is that the name part should be maximum 14 characters, as I understand it */
757         if (fixed_name.length() > 14) {
758                 fixed_name = fixed_name.substr (0, 14);
759         }
760
761         d << fixed_name << "_";
762
763         if (dcp_content_type()) {
764                 d << dcp_content_type()->dci_name() << "_";
765         }
766
767         if (format()) {
768                 d << format()->dci_name() << "_";
769         }
770
771         DCIMetadata const dm = dci_metadata ();
772
773         if (!dm.audio_language.empty ()) {
774                 d << dm.audio_language;
775                 if (!dm.subtitle_language.empty() && with_subtitles()) {
776                         d << "-" << dm.subtitle_language;
777                 } else {
778                         d << "-XX";
779                 }
780                         
781                 d << "_";
782         }
783
784         if (!dm.territory.empty ()) {
785                 d << dm.territory;
786                 if (!dm.rating.empty ()) {
787                         d << "-" << dm.rating;
788                 }
789                 d << "_";
790         }
791
792         switch (audio_channels()) {
793         case 1:
794                 d << "10_";
795                 break;
796         case 2:
797                 d << "20_";
798                 break;
799         case 6:
800                 d << "51_";
801                 break;
802         case 8:
803                 d << "71_";
804                 break;
805         }
806
807         d << "2K_";
808
809         if (!dm.studio.empty ()) {
810                 d << dm.studio << "_";
811         }
812
813         if (if_created_now) {
814                 d << boost::gregorian::to_iso_string (boost::gregorian::day_clock::local_day ()) << "_";
815         } else {
816                 d << boost::gregorian::to_iso_string (_dci_date) << "_";
817         }
818
819         if (!dm.facility.empty ()) {
820                 d << dm.facility << "_";
821         }
822
823         if (!dm.package_type.empty ()) {
824                 d << dm.package_type;
825         }
826
827         return d.str ();
828 }
829
830 /** @return name to give the DCP */
831 string
832 Film::dcp_name (bool if_created_now) const
833 {
834         if (use_dci_name()) {
835                 return dci_name (if_created_now);
836         }
837
838         return name();
839 }
840
841
842 void
843 Film::set_directory (string d)
844 {
845         boost::mutex::scoped_lock lm (_state_mutex);
846         _directory = d;
847         _dirty = true;
848 }
849
850 void
851 Film::set_name (string n)
852 {
853         {
854                 boost::mutex::scoped_lock lm (_state_mutex);
855                 _name = n;
856         }
857         signal_changed (NAME);
858 }
859
860 void
861 Film::set_use_dci_name (bool u)
862 {
863         {
864                 boost::mutex::scoped_lock lm (_state_mutex);
865                 _use_dci_name = u;
866         }
867         signal_changed (USE_DCI_NAME);
868 }
869
870 void
871 Film::set_content (string c)
872 {
873         string check = directory ();
874
875         boost::filesystem::path slash ("/");
876         string platform_slash = slash.make_preferred().string ();
877
878         if (!ends_with (check, platform_slash)) {
879                 check += platform_slash;
880         }
881         
882         if (boost::filesystem::path(c).has_root_directory () && starts_with (c, check)) {
883                 c = c.substr (_directory.length() + 1);
884         }
885
886         string old_content;
887         
888         {
889                 boost::mutex::scoped_lock lm (_state_mutex);
890                 if (c == _content) {
891                         return;
892                 }
893
894                 old_content = _content;
895                 _content = c;
896         }
897
898         /* Reset streams here in case the new content doesn't have one or the other */
899         _content_audio_stream = shared_ptr<AudioStream> ();
900         _subtitle_stream = shared_ptr<SubtitleStream> ();
901
902         /* Start off using content audio */
903         set_use_content_audio (true);
904
905         /* Create a temporary decoder so that we can get information
906            about the content.
907         */
908
909         try {
910                 Decoders d = decoder_factory (shared_from_this(), DecodeOptions());
911                 
912                 set_size (d.video->native_size ());
913                 set_source_frame_rate (d.video->frames_per_second ());
914                 set_dcp_frame_rate (best_dcp_frame_rate (source_frame_rate ()));
915                 set_subtitle_streams (d.video->subtitle_streams ());
916                 if (d.audio) {
917                         set_content_audio_streams (d.audio->audio_streams ());
918                 }
919
920                 {
921                         boost::mutex::scoped_lock lm (_state_mutex);
922                         _content = c;
923                 }
924                 
925                 signal_changed (CONTENT);
926                 
927                 /* Start off with the first audio and subtitle streams */
928                 if (d.audio && !d.audio->audio_streams().empty()) {
929                         set_content_audio_stream (d.audio->audio_streams().front());
930                 }
931                 
932                 if (!d.video->subtitle_streams().empty()) {
933                         set_subtitle_stream (d.video->subtitle_streams().front());
934                 }
935                 
936                 examine_content ();
937
938         } catch (...) {
939
940                 boost::mutex::scoped_lock lm (_state_mutex);
941                 _content = old_content;
942                 throw;
943
944         }
945
946         /* Default format */
947         switch (content_type()) {
948         case STILL:
949                 set_format (Format::from_id ("var-185"));
950                 break;
951         case VIDEO:
952                 set_format (Format::from_id ("185"));
953                 break;
954         }
955
956         /* Still image DCPs must use external audio */
957         if (content_type() == STILL) {
958                 set_use_content_audio (false);
959         }
960 }
961
962 void
963 Film::set_trust_content_header (bool t)
964 {
965         {
966                 boost::mutex::scoped_lock lm (_state_mutex);
967                 _trust_content_header = t;
968         }
969         
970         signal_changed (TRUST_CONTENT_HEADER);
971
972         if (!_trust_content_header && !content().empty()) {
973                 /* We just said that we don't trust the content's header */
974                 examine_content ();
975         }
976 }
977                
978 void
979 Film::set_dcp_content_type (DCPContentType const * t)
980 {
981         {
982                 boost::mutex::scoped_lock lm (_state_mutex);
983                 _dcp_content_type = t;
984         }
985         signal_changed (DCP_CONTENT_TYPE);
986 }
987
988 void
989 Film::set_format (Format const * f)
990 {
991         {
992                 boost::mutex::scoped_lock lm (_state_mutex);
993                 _format = f;
994         }
995         signal_changed (FORMAT);
996 }
997
998 void
999 Film::set_crop (Crop c)
1000 {
1001         {
1002                 boost::mutex::scoped_lock lm (_state_mutex);
1003                 _crop = c;
1004         }
1005         signal_changed (CROP);
1006 }
1007
1008 void
1009 Film::set_left_crop (int c)
1010 {
1011         {
1012                 boost::mutex::scoped_lock lm (_state_mutex);
1013                 
1014                 if (_crop.left == c) {
1015                         return;
1016                 }
1017                 
1018                 _crop.left = c;
1019         }
1020         signal_changed (CROP);
1021 }
1022
1023 void
1024 Film::set_right_crop (int c)
1025 {
1026         {
1027                 boost::mutex::scoped_lock lm (_state_mutex);
1028                 if (_crop.right == c) {
1029                         return;
1030                 }
1031                 
1032                 _crop.right = c;
1033         }
1034         signal_changed (CROP);
1035 }
1036
1037 void
1038 Film::set_top_crop (int c)
1039 {
1040         {
1041                 boost::mutex::scoped_lock lm (_state_mutex);
1042                 if (_crop.top == c) {
1043                         return;
1044                 }
1045                 
1046                 _crop.top = c;
1047         }
1048         signal_changed (CROP);
1049 }
1050
1051 void
1052 Film::set_bottom_crop (int c)
1053 {
1054         {
1055                 boost::mutex::scoped_lock lm (_state_mutex);
1056                 if (_crop.bottom == c) {
1057                         return;
1058                 }
1059                 
1060                 _crop.bottom = c;
1061         }
1062         signal_changed (CROP);
1063 }
1064
1065 void
1066 Film::set_filters (vector<Filter const *> f)
1067 {
1068         {
1069                 boost::mutex::scoped_lock lm (_state_mutex);
1070                 _filters = f;
1071         }
1072         signal_changed (FILTERS);
1073 }
1074
1075 void
1076 Film::set_scaler (Scaler const * s)
1077 {
1078         {
1079                 boost::mutex::scoped_lock lm (_state_mutex);
1080                 _scaler = s;
1081         }
1082         signal_changed (SCALER);
1083 }
1084
1085 void
1086 Film::set_trim_start (int t)
1087 {
1088         {
1089                 boost::mutex::scoped_lock lm (_state_mutex);
1090                 _trim_start = t;
1091         }
1092         signal_changed (TRIM_START);
1093 }
1094
1095 void
1096 Film::set_trim_end (int t)
1097 {
1098         {
1099                 boost::mutex::scoped_lock lm (_state_mutex);
1100                 _trim_end = t;
1101         }
1102         signal_changed (TRIM_END);
1103 }
1104
1105 void
1106 Film::set_dcp_ab (bool a)
1107 {
1108         {
1109                 boost::mutex::scoped_lock lm (_state_mutex);
1110                 _dcp_ab = a;
1111         }
1112         signal_changed (DCP_AB);
1113 }
1114
1115 void
1116 Film::set_content_audio_stream (shared_ptr<AudioStream> s)
1117 {
1118         {
1119                 boost::mutex::scoped_lock lm (_state_mutex);
1120                 _content_audio_stream = s;
1121         }
1122         signal_changed (CONTENT_AUDIO_STREAM);
1123 }
1124
1125 void
1126 Film::set_external_audio (vector<string> a)
1127 {
1128         {
1129                 boost::mutex::scoped_lock lm (_state_mutex);
1130                 _external_audio = a;
1131         }
1132
1133         shared_ptr<ExternalAudioDecoder> decoder (new ExternalAudioDecoder (shared_from_this(), DecodeOptions()));
1134         if (decoder->audio_stream()) {
1135                 _external_audio_stream = decoder->audio_stream ();
1136         }
1137         
1138         signal_changed (EXTERNAL_AUDIO);
1139 }
1140
1141 void
1142 Film::set_use_content_audio (bool e)
1143 {
1144         {
1145                 boost::mutex::scoped_lock lm (_state_mutex);
1146                 _use_content_audio = e;
1147         }
1148
1149         signal_changed (USE_CONTENT_AUDIO);
1150 }
1151
1152 void
1153 Film::set_audio_gain (float g)
1154 {
1155         {
1156                 boost::mutex::scoped_lock lm (_state_mutex);
1157                 _audio_gain = g;
1158         }
1159         signal_changed (AUDIO_GAIN);
1160 }
1161
1162 void
1163 Film::set_audio_delay (int d)
1164 {
1165         {
1166                 boost::mutex::scoped_lock lm (_state_mutex);
1167                 _audio_delay = d;
1168         }
1169         signal_changed (AUDIO_DELAY);
1170 }
1171
1172 void
1173 Film::set_still_duration (int d)
1174 {
1175         {
1176                 boost::mutex::scoped_lock lm (_state_mutex);
1177                 _still_duration = d;
1178         }
1179         signal_changed (STILL_DURATION);
1180 }
1181
1182 void
1183 Film::set_subtitle_stream (shared_ptr<SubtitleStream> s)
1184 {
1185         {
1186                 boost::mutex::scoped_lock lm (_state_mutex);
1187                 _subtitle_stream = s;
1188         }
1189         signal_changed (SUBTITLE_STREAM);
1190 }
1191
1192 void
1193 Film::set_with_subtitles (bool w)
1194 {
1195         {
1196                 boost::mutex::scoped_lock lm (_state_mutex);
1197                 _with_subtitles = w;
1198         }
1199         signal_changed (WITH_SUBTITLES);
1200 }
1201
1202 void
1203 Film::set_subtitle_offset (int o)
1204 {
1205         {
1206                 boost::mutex::scoped_lock lm (_state_mutex);
1207                 _subtitle_offset = o;
1208         }
1209         signal_changed (SUBTITLE_OFFSET);
1210 }
1211
1212 void
1213 Film::set_subtitle_scale (float s)
1214 {
1215         {
1216                 boost::mutex::scoped_lock lm (_state_mutex);
1217                 _subtitle_scale = s;
1218         }
1219         signal_changed (SUBTITLE_SCALE);
1220 }
1221
1222 void
1223 Film::set_colour_lut (int i)
1224 {
1225         {
1226                 boost::mutex::scoped_lock lm (_state_mutex);
1227                 _colour_lut = i;
1228         }
1229         signal_changed (COLOUR_LUT);
1230 }
1231
1232 void
1233 Film::set_j2k_bandwidth (int b)
1234 {
1235         {
1236                 boost::mutex::scoped_lock lm (_state_mutex);
1237                 _j2k_bandwidth = b;
1238         }
1239         signal_changed (J2K_BANDWIDTH);
1240 }
1241
1242 void
1243 Film::set_dci_metadata (DCIMetadata m)
1244 {
1245         {
1246                 boost::mutex::scoped_lock lm (_state_mutex);
1247                 _dci_metadata = m;
1248         }
1249         signal_changed (DCI_METADATA);
1250 }
1251
1252
1253 void
1254 Film::set_dcp_frame_rate (int f)
1255 {
1256         {
1257                 boost::mutex::scoped_lock lm (_state_mutex);
1258                 _dcp_frame_rate = f;
1259         }
1260         signal_changed (DCP_FRAME_RATE);
1261 }
1262
1263 void
1264 Film::set_size (libdcp::Size s)
1265 {
1266         {
1267                 boost::mutex::scoped_lock lm (_state_mutex);
1268                 _size = s;
1269         }
1270         signal_changed (SIZE);
1271 }
1272
1273 void
1274 Film::set_length (SourceFrame l)
1275 {
1276         {
1277                 boost::mutex::scoped_lock lm (_state_mutex);
1278                 _length = l;
1279         }
1280         signal_changed (LENGTH);
1281 }
1282
1283 void
1284 Film::unset_length ()
1285 {
1286         {
1287                 boost::mutex::scoped_lock lm (_state_mutex);
1288                 _length = boost::none;
1289         }
1290         signal_changed (LENGTH);
1291 }
1292
1293 void
1294 Film::set_dcp_intrinsic_duration (int d)
1295 {
1296         {
1297                 boost::mutex::scoped_lock lm (_state_mutex);
1298                 _dcp_intrinsic_duration = d;
1299         }
1300         signal_changed (DCP_INTRINSIC_DURATION);
1301 }
1302
1303 void
1304 Film::set_content_digest (string d)
1305 {
1306         {
1307                 boost::mutex::scoped_lock lm (_state_mutex);
1308                 _content_digest = d;
1309         }
1310         _dirty = true;
1311 }
1312
1313 void
1314 Film::set_content_audio_streams (vector<shared_ptr<AudioStream> > s)
1315 {
1316         {
1317                 boost::mutex::scoped_lock lm (_state_mutex);
1318                 _content_audio_streams = s;
1319         }
1320         signal_changed (CONTENT_AUDIO_STREAMS);
1321 }
1322
1323 void
1324 Film::set_subtitle_streams (vector<shared_ptr<SubtitleStream> > s)
1325 {
1326         {
1327                 boost::mutex::scoped_lock lm (_state_mutex);
1328                 _subtitle_streams = s;
1329         }
1330         signal_changed (SUBTITLE_STREAMS);
1331 }
1332
1333 void
1334 Film::set_source_frame_rate (float f)
1335 {
1336         {
1337                 boost::mutex::scoped_lock lm (_state_mutex);
1338                 _source_frame_rate = f;
1339         }
1340         signal_changed (SOURCE_FRAME_RATE);
1341 }
1342         
1343 void
1344 Film::signal_changed (Property p)
1345 {
1346         {
1347                 boost::mutex::scoped_lock lm (_state_mutex);
1348                 _dirty = true;
1349         }
1350
1351         if (ui_signaller) {
1352                 ui_signaller->emit (boost::bind (boost::ref (Changed), p));
1353         }
1354 }
1355
1356 int
1357 Film::audio_channels () const
1358 {
1359         shared_ptr<AudioStream> s = audio_stream ();
1360         if (!s) {
1361                 return 0;
1362         }
1363
1364         return s->channels ();
1365 }
1366
1367 void
1368 Film::set_dci_date_today ()
1369 {
1370         _dci_date = boost::gregorian::day_clock::local_day ();
1371 }
1372
1373 boost::shared_ptr<AudioStream>
1374 Film::audio_stream () const
1375 {
1376         if (use_content_audio()) {
1377                 return _content_audio_stream;
1378         }
1379
1380         return _external_audio_stream;
1381 }
1382
1383 string
1384 Film::info_path (int f) const
1385 {
1386         boost::filesystem::path p;
1387         p /= info_dir ();
1388
1389         stringstream s;
1390         s.width (8);
1391         s << setfill('0') << f << ".md5";
1392
1393         p /= s.str();
1394
1395         /* info_dir() will already have added any initial bit of the path,
1396            so don't call file() on this.
1397         */
1398         return p.string ();
1399 }
1400
1401 string
1402 Film::j2c_path (int f, bool t) const
1403 {
1404         boost::filesystem::path p;
1405         p /= "j2c";
1406         p /= video_state_identifier ();
1407
1408         stringstream s;
1409         s.width (8);
1410         s << setfill('0') << f << ".j2c";
1411
1412         if (t) {
1413                 s << ".tmp";
1414         }
1415
1416         p /= s.str();
1417         return file (p.string ());
1418 }
1419
1420 /** Make an educated guess as to whether we have a complete DCP
1421  *  or not.
1422  *  @return true if we do.
1423  */
1424
1425 bool
1426 Film::have_dcp () const
1427 {
1428         try {
1429                 libdcp::DCP dcp (dir (dcp_name()));
1430                 dcp.read ();
1431         } catch (...) {
1432                 return false;
1433         }
1434
1435         return true;
1436 }
1437
1438 bool
1439 Film::has_audio () const
1440 {
1441         if (use_content_audio()) {
1442                 return audio_stream();
1443         }
1444
1445         vector<string> const e = external_audio ();
1446         for (vector<string>::const_iterator i = e.begin(); i != e.end(); ++i) {
1447                 if (!i->empty ()) {
1448                         return true;
1449                 }
1450         }
1451
1452         return false;
1453 }
1454