+ string check = directory ();
+
+#if BOOST_FILESYSTEM_VERSION == 3
+ boost::filesystem::path slash ("/");
+ string platform_slash = slash.make_preferred().string ();
+#else
+#ifdef DVDOMATIC_WINDOWS
+ string platform_slash = "\\";
+#else
+ string platform_slash = "/";
+#endif
+#endif
+
+ if (!ends_with (check, platform_slash)) {
+ check += platform_slash;
+ }
+
+ if (boost::filesystem::path(c).has_root_directory () && starts_with (c, check)) {
+ c = c.substr (_directory.length() + 1);
+ }
+
+ string old_content;
+
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ if (c == _content) {
+ return;
+ }
+
+ old_content = _content;
+ _content = c;
+ }
+
+ /* Reset streams here in case the new content doesn't have one or the other */
+ _content_audio_stream = shared_ptr<AudioStream> ();
+ _subtitle_stream = shared_ptr<SubtitleStream> ();
+
+ /* Start off using content audio */
+ set_use_content_audio (true);
+
+ /* Create a temporary decoder so that we can get information
+ about the content.
+ */
+
+ try {
+ shared_ptr<DecodeOptions> o (new DecodeOptions);
+ Decoders d = decoder_factory (shared_from_this(), o, 0);
+
+ set_size (d.video->native_size ());
+ set_frames_per_second (d.video->frames_per_second ());
+ set_subtitle_streams (d.video->subtitle_streams ());
+ if (d.audio) {
+ set_content_audio_streams (d.audio->audio_streams ());
+ }
+
+ /* Start off with the first audio and subtitle streams */
+ if (d.audio && !d.audio->audio_streams().empty()) {
+ set_content_audio_stream (d.audio->audio_streams().front());
+ }
+
+ if (!d.video->subtitle_streams().empty()) {
+ set_subtitle_stream (d.video->subtitle_streams().front());
+ }
+
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _content = c;
+ }
+
+ signal_changed (CONTENT);
+
+ examine_content ();
+
+ } catch (...) {
+
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _content = old_content;
+ throw;
+
+ }
+
+ /* Default format */
+ switch (content_type()) {
+ case STILL:
+ set_format (Format::from_id ("var-185"));
+ break;
+ case VIDEO:
+ set_format (Format::from_id ("185"));
+ break;
+ }
+
+ /* Still image DCPs must use external audio */
+ if (content_type() == STILL) {
+ set_use_content_audio (false);
+ }
+}
+
+void
+Film::set_trust_content_header (bool t)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _trust_content_header = t;
+ }
+
+ signal_changed (TRUST_CONTENT_HEADER);
+
+ if (!_trust_content_header && !content().empty()) {
+ /* We just said that we don't trust the content's header */
+ examine_content ();
+ }
+}
+
+void
+Film::set_dcp_content_type (DCPContentType const * t)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _dcp_content_type = t;
+ }
+ signal_changed (DCP_CONTENT_TYPE);
+}
+
+void
+Film::set_format (Format const * f)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _format = f;
+ }
+ signal_changed (FORMAT);
+}
+
+void
+Film::set_crop (Crop c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _crop = c;
+ }
+ signal_changed (CROP);
+}
+
+void
+Film::set_left_crop (int c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+
+ if (_crop.left == c) {
+ return;
+ }
+
+ _crop.left = c;
+ }
+ signal_changed (CROP);
+}
+
+void
+Film::set_right_crop (int c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ if (_crop.right == c) {
+ return;
+ }
+
+ _crop.right = c;
+ }
+ signal_changed (CROP);
+}
+
+void
+Film::set_top_crop (int c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ if (_crop.top == c) {
+ return;
+ }
+
+ _crop.top = c;
+ }
+ signal_changed (CROP);
+}
+
+void
+Film::set_bottom_crop (int c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ if (_crop.bottom == c) {
+ return;
+ }
+
+ _crop.bottom = c;
+ }
+ signal_changed (CROP);
+}
+
+void
+Film::set_filters (vector<Filter const *> f)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _filters = f;
+ }
+ signal_changed (FILTERS);
+}
+
+void
+Film::set_scaler (Scaler const * s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _scaler = s;
+ }
+ signal_changed (SCALER);
+}
+
+void
+Film::set_dcp_trim_start (int t)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _dcp_trim_start = t;
+ }
+ signal_changed (DCP_TRIM_START);
+}
+
+void
+Film::set_dcp_trim_end (int t)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _dcp_trim_end = t;
+ }
+ signal_changed (DCP_TRIM_END);
+}
+
+void
+Film::set_reel_size (uint64_t s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _reel_size = s;
+ }
+ signal_changed (REEL_SIZE);
+}
+
+void
+Film::unset_reel_size ()
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _reel_size = boost::optional<uint64_t> ();
+ }
+ signal_changed (REEL_SIZE);
+}
+
+void
+Film::set_dcp_ab (bool a)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _dcp_ab = a;
+ }
+ signal_changed (DCP_AB);
+}
+
+void
+Film::set_content_audio_stream (shared_ptr<AudioStream> s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _content_audio_stream = s;
+ }
+ signal_changed (CONTENT_AUDIO_STREAM);
+}
+
+void
+Film::set_external_audio (vector<string> a)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _external_audio = a;
+ }
+
+ shared_ptr<DecodeOptions> o (new DecodeOptions);
+ shared_ptr<ExternalAudioDecoder> decoder (new ExternalAudioDecoder (shared_from_this(), o, 0));
+ if (decoder->audio_stream()) {
+ _external_audio_stream = decoder->audio_stream ();
+ }
+
+ signal_changed (EXTERNAL_AUDIO);
+}
+
+void
+Film::set_use_content_audio (bool e)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _use_content_audio = e;
+ }
+
+ signal_changed (USE_CONTENT_AUDIO);
+}
+
+void
+Film::set_audio_gain (float g)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_gain = g;
+ }
+ signal_changed (AUDIO_GAIN);
+}
+
+void
+Film::set_audio_delay (int d)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_delay = d;
+ }
+ signal_changed (AUDIO_DELAY);
+}
+
+void
+Film::set_still_duration (int d)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _still_duration = d;
+ }
+ signal_changed (STILL_DURATION);
+}
+
+void
+Film::set_subtitle_stream (shared_ptr<SubtitleStream> s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _subtitle_stream = s;
+ }
+ signal_changed (SUBTITLE_STREAM);
+}
+
+void
+Film::set_with_subtitles (bool w)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _with_subtitles = w;
+ }
+ signal_changed (WITH_SUBTITLES);
+}
+
+void
+Film::set_subtitle_offset (int o)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _subtitle_offset = o;
+ }
+ signal_changed (SUBTITLE_OFFSET);
+}
+
+void
+Film::set_subtitle_scale (float s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _subtitle_scale = s;
+ }
+ signal_changed (SUBTITLE_SCALE);
+}
+
+void
+Film::set_colour_lut (int i)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _colour_lut = i;
+ }
+ signal_changed (COLOUR_LUT);
+}
+
+void
+Film::set_j2k_bandwidth (int b)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _j2k_bandwidth = b;
+ }
+ signal_changed (J2K_BANDWIDTH);
+}
+
+void
+Film::set_audio_language (string l)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_language = l;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_subtitle_language (string l)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _subtitle_language = l;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_territory (string t)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _territory = t;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_rating (string r)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _rating = r;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_studio (string s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _studio = s;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_facility (string f)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _facility = f;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_package_type (string p)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _package_type = p;
+ }
+ signal_changed (DCI_METADATA);
+}
+
+void
+Film::set_size (Size s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _size = s;
+ }
+ signal_changed (SIZE);
+}
+
+void
+Film::set_length (SourceFrame l)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _length = l;
+ }
+ signal_changed (LENGTH);
+}
+
+void
+Film::unset_length ()
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _length = boost::none;
+ }
+ signal_changed (LENGTH);
+}
+
+void
+Film::set_content_digest (string d)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _content_digest = d;
+ }
+ _dirty = true;
+}
+
+void
+Film::set_content_audio_streams (vector<shared_ptr<AudioStream> > s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _content_audio_streams = s;
+ }
+ signal_changed (CONTENT_AUDIO_STREAMS);
+}
+
+void
+Film::set_subtitle_streams (vector<shared_ptr<SubtitleStream> > s)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _subtitle_streams = s;
+ }
+ signal_changed (SUBTITLE_STREAMS);
+}
+
+void
+Film::set_frames_per_second (float f)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _frames_per_second = f;
+ }
+ signal_changed (FRAMES_PER_SECOND);
+}
+
+void
+Film::signal_changed (Property p)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _dirty = true;
+ }
+
+ if (ui_signaller) {
+ ui_signaller->emit (boost::bind (boost::ref (Changed), p));
+ }
+}
+
+int
+Film::audio_channels () const
+{
+ shared_ptr<AudioStream> s = audio_stream ();
+ if (!s) {
+ return 0;
+ }
+
+ return s->channels ();
+}
+
+void
+Film::set_dci_date_today ()
+{
+ _dci_date = boost::gregorian::day_clock::local_day ();
+}
+
+boost::shared_ptr<AudioStream>
+Film::audio_stream () const
+{
+ if (use_content_audio()) {
+ return _content_audio_stream;
+ }
+
+ return _external_audio_stream;