+ DecodeOptions od;
+ od.decode_subtitles = with_subtitles ();
+
+ shared_ptr<Job> r;
+
+ if (transcode) {
+ if (dcp_ab()) {
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
+ } else {
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
+ }
+ }
+}
+
+/** Start a job to examine our content file */
+void
+Film::examine_content ()
+{
+ if (_examine_content_job) {
+ return;
+ }
+
+ _examine_content_job.reset (new ExamineContentJob (shared_from_this()));
+ _examine_content_job->Finished.connect (bind (&Film::examine_content_finished, this));
+ JobManager::instance()->add (_examine_content_job);
+}
+
+void
+Film::examine_content_finished ()
+{
+ _examine_content_job.reset ();
+}
+
+/** Start a job to send our DCP to the configured TMS */
+void
+Film::send_dcp_to_tms ()
+{
+ shared_ptr<Job> j (new SCPDCPJob (shared_from_this()));
+ JobManager::instance()->add (j);
+}
+
+/** Count the number of frames that have been encoded for this film.
+ * @return frame count.
+ */
+int
+Film::encoded_frames () const
+{
+ if (format() == 0) {
+ return 0;
+ }
+
+ int N = 0;
+ for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (info_dir ()); i != boost::filesystem::directory_iterator(); ++i) {
+ ++N;
+ boost::this_thread::interruption_point ();
+ }
+
+ return N;
+}
+
+/** Write state to our `metadata' file */
+void
+Film::write_metadata () const
+{
+ boost::mutex::scoped_lock lm (_state_mutex);
+
+ boost::filesystem::create_directories (directory());
+
+ string const m = file ("metadata");
+ ofstream f (m.c_str ());
+ if (!f.good ()) {
+ throw CreateFileError (m);
+ }
+
+ f << "version " << state_version << "\n";
+
+ /* User stuff */
+ f << "name " << _name << "\n";
+ f << "use_dci_name " << _use_dci_name << "\n";
+ f << "content " << _content << "\n";
+ f << "trust_content_header " << (_trust_content_header ? "1" : "0") << "\n";
+ if (_dcp_content_type) {
+ f << "dcp_content_type " << _dcp_content_type->dci_name () << "\n";
+ }
+ if (_format) {
+ f << "format " << _format->as_metadata () << "\n";
+ }
+ f << "left_crop " << _crop.left << "\n";
+ f << "right_crop " << _crop.right << "\n";
+ f << "top_crop " << _crop.top << "\n";
+ f << "bottom_crop " << _crop.bottom << "\n";
+ for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
+ f << "filter " << (*i)->id () << "\n";
+ }
+ f << "scaler " << _scaler->id () << "\n";
+ f << "trim_start " << _trim_start << "\n";
+ f << "trim_end " << _trim_end << "\n";
+ f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n";
+ if (_content_audio_stream) {
+ f << "selected_content_audio_stream " << _content_audio_stream->to_string() << "\n";
+ }
+ for (vector<string>::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) {
+ f << "external_audio " << *i << "\n";
+ }
+ f << "use_content_audio " << (_use_content_audio ? "1" : "0") << "\n";
+ f << "audio_gain " << _audio_gain << "\n";
+ f << "audio_delay " << _audio_delay << "\n";
+ f << "still_duration " << _still_duration << "\n";
+ if (_subtitle_stream) {
+ f << "selected_subtitle_stream " << _subtitle_stream->to_string() << "\n";
+ }
+ f << "with_subtitles " << _with_subtitles << "\n";
+ f << "subtitle_offset " << _subtitle_offset << "\n";
+ f << "subtitle_scale " << _subtitle_scale << "\n";
+ f << "colour_lut " << _colour_lut << "\n";
+ f << "j2k_bandwidth " << _j2k_bandwidth << "\n";
+ _dci_metadata.write (f);
+ f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << "\n";
+ f << "width " << _size.width << "\n";
+ f << "height " << _size.height << "\n";
+ f << "length " << _length.get_value_or(0) << "\n";
+ f << "dcp_intrinsic_duration " << _dcp_intrinsic_duration.get_value_or(0) << "\n";
+ f << "content_digest " << _content_digest << "\n";
+
+ for (vector<shared_ptr<AudioStream> >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
+ f << "content_audio_stream " << (*i)->to_string () << "\n";
+ }
+
+ f << "external_audio_stream " << _external_audio_stream->to_string() << "\n";
+
+ for (vector<shared_ptr<SubtitleStream> >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
+ f << "subtitle_stream " << (*i)->to_string () << "\n";
+ }
+
+ f << "frames_per_second " << _frames_per_second << "\n";
+
+ _dirty = false;
+}
+
+/** Read state from our metadata file */