From d6e74fb7dbc5b01c9ce42f8fe780bb16262d13b1 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 17 Oct 2012 22:40:08 +0100 Subject: [PATCH] Re-work FilmState / Film relationship a bit; Film now inherits from FilmState and FilmState does get/set. --- src/lib/ab_transcode_job.cc | 6 +- src/lib/check_hashes_job.cc | 6 +- src/lib/decoder.cc | 28 +- src/lib/examine_content_job.cc | 2 +- src/lib/ffmpeg_decoder.cc | 4 +- src/lib/film.cc | 456 ++------------------ src/lib/film.h | 274 +----------- src/lib/film_state.cc | 762 +++++++++++++++++++++++++-------- src/lib/film_state.h | 395 ++++++++++++++--- src/lib/imagemagick_encoder.cc | 8 +- src/lib/j2k_still_encoder.cc | 6 +- src/lib/j2k_wav_encoder.cc | 42 +- src/lib/make_dcp_job.cc | 19 +- src/lib/thumbs_job.cc | 2 +- src/lib/tiff_decoder.cc | 2 +- src/lib/transcode_job.cc | 2 +- src/tools/makedcp.cc | 2 +- src/wx/film_editor.cc | 158 +++---- src/wx/film_editor.h | 4 +- src/wx/film_viewer.cc | 36 +- src/wx/film_viewer.h | 2 +- test/test.cc | 26 +- 22 files changed, 1117 insertions(+), 1125 deletions(-) diff --git a/src/lib/ab_transcode_job.cc b/src/lib/ab_transcode_job.cc index fd8236bf0..89967bfca 100644 --- a/src/lib/ab_transcode_job.cc +++ b/src/lib/ab_transcode_job.cc @@ -39,14 +39,14 @@ ABTranscodeJob::ABTranscodeJob (shared_ptr s, shared_ptrscaler = Config::instance()->reference_scaler (); - _fs_b->filters = Config::instance()->reference_filters (); + _fs_b->set_scaler (Config::instance()->reference_scaler ()); + _fs_b->set_filters (Config::instance()->reference_filters ()); } string ABTranscodeJob::name () const { - return String::compose ("A/B transcode %1", _fs->name); + return String::compose ("A/B transcode %1", _fs->name()); } void diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc index f07a5ab2a..d64ccc866 100644 --- a/src/lib/check_hashes_job.cc +++ b/src/lib/check_hashes_job.cc @@ -41,7 +41,7 @@ CheckHashesJob::CheckHashesJob (shared_ptr s, shared_ptrname); + return String::compose ("Check hashes of %1", _fs->name()); } void @@ -66,13 +66,13 @@ CheckHashesJob::run () ++_bad; } - set_progress (float (i) / _fs->length); + set_progress (float (i) / _fs->length()); } if (_bad) { shared_ptr tc; - if (_fs->dcp_ab) { + if (_fs->dcp_ab()) { tc.reset (new ABTranscodeJob (_fs, _opt, _log, shared_from_this())); } else { tc.reset (new TranscodeJob (_fs, _opt, _log, shared_from_this())); diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index ef2ef6fb9..03131dac2 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -76,7 +76,7 @@ Decoder::Decoder (boost::shared_ptr s, boost::shared_ptrdecode_video_frequency != 0 && _fs->length == 0) { + if (_opt->decode_video_frequency != 0 && _fs->length() == 0) { throw DecodeError ("cannot do a partial decode if length == 0"); } } @@ -90,7 +90,7 @@ Decoder::~Decoder () void Decoder::process_begin () { - _delay_in_bytes = _fs->audio_delay * _fs->audio_sample_rate * _fs->audio_channels * _fs->bytes_per_sample() / 1000; + _delay_in_bytes = _fs->audio_delay() * _fs->audio_sample_rate() * _fs->audio_channels() * _fs->bytes_per_sample() / 1000; delete _delay_line; _delay_line = new DelayLine (_delay_in_bytes); @@ -104,7 +104,7 @@ Decoder::process_end () if (_delay_in_bytes < 0) { uint8_t remainder[-_delay_in_bytes]; _delay_line->get_remaining (remainder); - _audio_frames_processed += _delay_in_bytes / (_fs->audio_channels * _fs->bytes_per_sample()); + _audio_frames_processed += _delay_in_bytes / (_fs->audio_channels() * _fs->bytes_per_sample()); Audio (remainder, _delay_in_bytes); } @@ -113,7 +113,7 @@ Decoder::process_end () */ int64_t const audio_short_by_frames = - ((int64_t) _fs->dcp_length() * _fs->target_sample_rate() / _fs->frames_per_second) + ((int64_t) _fs->dcp_length() * _fs->target_sample_rate() / _fs->frames_per_second()) - _audio_frames_processed; if (audio_short_by_frames >= 0) { @@ -122,7 +122,7 @@ Decoder::process_end () s << "Adding " << audio_short_by_frames << " frames of silence to the end."; _log->log (s.str ()); - int64_t bytes = audio_short_by_frames * _fs->audio_channels * _fs->bytes_per_sample(); + int64_t bytes = audio_short_by_frames * _fs->audio_channels() * _fs->bytes_per_sample(); int64_t const silence_size = 64 * 1024; uint8_t silence[silence_size]; @@ -185,10 +185,10 @@ Decoder::process_audio (uint8_t* data, int size) int const samples = size / _fs->bytes_per_sample(); /* Maybe apply gain */ - if (_fs->audio_gain != 0) { - float const linear_gain = pow (10, _fs->audio_gain / 20); + if (_fs->audio_gain() != 0) { + float const linear_gain = pow (10, _fs->audio_gain() / 20); uint8_t* p = data; - switch (_fs->audio_sample_format) { + switch (_fs->audio_sample_format()) { case AV_SAMPLE_FMT_S16: for (int i = 0; i < samples; ++i) { /* XXX: assumes little-endian; also we should probably be dithering here */ @@ -217,7 +217,7 @@ Decoder::process_audio (uint8_t* data, int size) } /* Update the number of audio frames we've pushed to the encoder */ - _audio_frames_processed += size / (_fs->audio_channels * _fs->bytes_per_sample ()); + _audio_frames_processed += size / (_fs->audio_channels() * _fs->bytes_per_sample()); /* Push into the delay line and then tell the world what we've got */ int available = _delay_line->feed (data, size); @@ -240,7 +240,7 @@ Decoder::process_video (AVFrame* frame) int gap = 0; if (_opt->decode_video_frequency != 0) { - gap = _fs->length / _opt->decode_video_frequency; + gap = _fs->length() / _opt->decode_video_frequency; } if (_opt->decode_video_frequency != 0 && gap != 0 && (_video_frame % gap) != 0) { @@ -305,7 +305,7 @@ Decoder::process_video (AVFrame* frame) } shared_ptr sub; - if (_timed_subtitle && _timed_subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { + if (_timed_subtitle && _timed_subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second()))) { sub = _timed_subtitle->subtitle (); } @@ -328,13 +328,13 @@ Decoder::setup_video_filters () if (_opt->apply_crop) { size_after_crop = _fs->cropped_size (native_size ()); - fs << crop_string (Position (_fs->crop.left, _fs->crop.top), size_after_crop); + fs << crop_string (Position (_fs->crop().left, _fs->crop().top), size_after_crop); } else { size_after_crop = native_size (); fs << crop_string (Position (0, 0), size_after_crop); } - string filters = Filter::ffmpeg_strings (_fs->filters).first; + string filters = Filter::ffmpeg_strings (_fs->filters()).first; if (!filters.empty ()) { filters += ","; } @@ -418,6 +418,6 @@ Decoder::process_subtitle (shared_ptr s) if (_opt->apply_crop) { Position const p = _timed_subtitle->subtitle()->position (); - _timed_subtitle->subtitle()->set_position (Position (p.x - _fs->crop.left, p.y - _fs->crop.top)); + _timed_subtitle->subtitle()->set_position (Position (p.x - _fs->crop().left, p.y - _fs->crop().top)); } } diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index 36b4cbabc..fd574e2d0 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -43,7 +43,7 @@ ExamineContentJob::~ExamineContentJob () string ExamineContentJob::name () const { - return String::compose ("Examine content of %1", _fs->name); + return String::compose ("Examine content of %1", _fs->name()); } void diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 4cec7ef35..828934604 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -220,7 +220,7 @@ FFmpegDecoder::do_pass () 0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1 ); - assert (_audio_codec_context->channels == _fs->audio_channels); + assert (_audio_codec_context->channels == _fs->audio_channels()); process_audio (_frame->data[0], data_size); } } @@ -245,7 +245,7 @@ FFmpegDecoder::do_pass () 0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1 ); - assert (_audio_codec_context->channels == _fs->audio_channels); + assert (_audio_codec_context->channels == _fs->audio_channels()); process_audio (_frame->data[0], data_size); } diff --git a/src/lib/film.cc b/src/lib/film.cc index e92881dad..5b21ed3bc 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -64,9 +64,8 @@ using namespace boost; */ Film::Film (string d, bool must_exist) - : _dirty (false) { - /* Make _state.directory a complete path without ..s (where possible) + /* Make state.directory a complete path without ..s (where possible) (Code swiped from Adam Bowen on stackoverflow) */ @@ -84,27 +83,19 @@ Film::Film (string d, bool must_exist) } } - _state.directory = result.string (); + set_directory (result.string ()); - if (!filesystem::exists (_state.directory)) { + if (!filesystem::exists (directory())) { if (must_exist) { - throw OpenFileError (_state.directory); + throw OpenFileError (directory()); } else { - filesystem::create_directory (_state.directory); + filesystem::create_directory (directory()); } } read_metadata (); - _log = new FileLog (_state.file ("log")); -} - -/** Copy constructor */ -Film::Film (Film const & other) - : _state (other._state) - , _dirty (other._dirty) -{ - + _log = new FileLog (file ("log")); } Film::~Film () @@ -112,260 +103,17 @@ Film::~Film () delete _log; } -/** Read the `metadata' file inside this Film's directory, and fill the - * object's data with its content. - */ - -void -Film::read_metadata () -{ - ifstream f (metadata_file().c_str ()); - multimap kv = read_key_value (f); - for (multimap::const_iterator i = kv.begin(); i != kv.end(); ++i) { - _state.read_metadata (i->first, i->second); - } - _dirty = false; -} - -/** Write our state to a file `metadata' inside the Film's directory */ -void -Film::write_metadata () const -{ - filesystem::create_directories (_state.directory); - - ofstream f (metadata_file().c_str ()); - if (!f.good ()) { - throw CreateFileError (metadata_file ()); - } - - _state.write_metadata (f); - - _dirty = false; -} - -/** Set the name by which DVD-o-matic refers to this Film */ -void -Film::set_name (string n) -{ - _state.name = n; - signal_changed (NAME); -} - -/** Set the content file for this film. - * @param c New content file; if specified as an absolute path, the content should - * be within the film's _state.directory; if specified as a relative path, the content - * will be assumed to be within the film's _state.directory. - */ -void -Film::set_content (string c) -{ - string check = _state.directory; - -#if BOOST_FILESYSTEM_VERSION == 3 - 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 (filesystem::path(c).has_root_directory () && starts_with (c, check)) { - c = c.substr (_state.directory.length() + 1); - } - - if (c == _state.content) { - return; - } - - /* Create a temporary decoder so that we can get information - about the content. - */ - shared_ptr s = state_copy (); - s->content = c; - shared_ptr o (new Options ("", "", "")); - o->out_size = Size (1024, 1024); - - shared_ptr d = decoder_factory (s, o, 0, _log); - - _state.size = d->native_size (); - _state.length = d->length_in_frames (); - _state.frames_per_second = d->frames_per_second (); - _state.audio_channels = d->audio_channels (); - _state.audio_sample_rate = d->audio_sample_rate (); - _state.audio_sample_format = d->audio_sample_format (); - _state.has_subtitles = d->has_subtitles (); - _state.audio_streams = d->audio_streams (); - _state.subtitle_streams = d->subtitle_streams (); - _state.audio_stream = _state.audio_streams.empty() ? -1 : _state.audio_streams.front().id; - _state.subtitle_stream = _state.subtitle_streams.empty() ? -1 : _state.subtitle_streams.front().id; - - _state.content_digest = md5_digest (s->content_path ()); - _state.content = c; - - signal_changed (SIZE); - signal_changed (LENGTH); - signal_changed (FRAMES_PER_SECOND); - signal_changed (AUDIO_CHANNELS); - signal_changed (AUDIO_SAMPLE_RATE); - signal_changed (CONTENT); - signal_changed (AUDIO_STREAM); - signal_changed (SUBTITLE_STREAM); -} - -/** Set the format that this Film should be shown in */ -void -Film::set_format (Format const * f) -{ - _state.format = f; - signal_changed (FORMAT); -} - -/** Set the type to specify the DCP as having - * (feature, trailer etc.) - */ -void -Film::set_dcp_content_type (DCPContentType const * t) -{ - _state.dcp_content_type = t; - signal_changed (DCP_CONTENT_TYPE); -} - -/** Set the number of pixels by which to crop the left of the source video */ -void -Film::set_left_crop (int c) -{ - if (c == _state.crop.left) { - return; - } - - _state.crop.left = c; - signal_changed (CROP); -} - -/** Set the number of pixels by which to crop the right of the source video */ -void -Film::set_right_crop (int c) -{ - if (c == _state.crop.right) { - return; - } - - _state.crop.right = c; - signal_changed (CROP); -} - -/** Set the number of pixels by which to crop the top of the source video */ -void -Film::set_top_crop (int c) -{ - if (c == _state.crop.top) { - return; - } - - _state.crop.top = c; - signal_changed (CROP); -} - -/** Set the number of pixels by which to crop the bottom of the source video */ -void -Film::set_bottom_crop (int c) -{ - if (c == _state.crop.bottom) { - return; - } - - _state.crop.bottom = c; - signal_changed (CROP); -} - -/** Set the filters to apply to the image when generating thumbnails - * or a DCP. - */ -void -Film::set_filters (vector const & f) -{ - _state.filters = f; - signal_changed (FILTERS); -} - -/** Set the number of frames to put in any generated DCP (from - * the start of the film). 0 indicates that all frames should - * be used. - */ -void -Film::set_dcp_frames (int n) -{ - _state.dcp_frames = n; - signal_changed (DCP_FRAMES); -} - -void -Film::set_dcp_trim_action (TrimAction a) -{ - _state.dcp_trim_action = a; - signal_changed (DCP_TRIM_ACTION); -} - -/** Set whether or not to generate a A/B comparison DCP. - * Such a DCP has the left half of its frame as the Film - * content without any filtering or post-processing; the - * right half is rendered with filters and post-processing. - */ -void -Film::set_dcp_ab (bool a) -{ - _state.dcp_ab = a; - signal_changed (DCP_AB); -} - -void -Film::set_audio_gain (float g) -{ - _state.audio_gain = g; - signal_changed (AUDIO_GAIN); -} - -void -Film::set_audio_delay (int d) -{ - _state.audio_delay = d; - signal_changed (AUDIO_DELAY); -} - -/** @return path of metadata file */ -string -Film::metadata_file () const -{ - return _state.file ("metadata"); -} - -/** @return full path of the content (actual video) file - * of this Film. - */ -string -Film::content () const -{ - return _state.content_path (); -} - /** The pre-processing GUI part of a thumbs update. * Must be called from the GUI thread. */ void Film::update_thumbs_pre_gui () { - _state.thumbs.clear (); - filesystem::remove_all (_state.dir ("thumbs")); + set_thumbs (vector ()); + filesystem::remove_all (dir ("thumbs")); /* This call will recreate the directory */ - _state.dir ("thumbs"); + dir ("thumbs"); } /** The post-processing GUI part of a thumbs update. @@ -374,7 +122,8 @@ Film::update_thumbs_pre_gui () void Film::update_thumbs_post_gui () { - string const tdir = _state.dir ("thumbs"); + string const tdir = dir ("thumbs"); + vector thumbs; for (filesystem::directory_iterator i = filesystem::directory_iterator (tdir); i != filesystem::directory_iterator(); ++i) { @@ -387,39 +136,12 @@ Film::update_thumbs_post_gui () size_t const d = l.find (".png"); if (d != string::npos) { - _state.thumbs.push_back (atoi (l.substr (0, d).c_str())); + thumbs.push_back (atoi (l.substr (0, d).c_str())); } } - sort (_state.thumbs.begin(), _state.thumbs.end()); - - write_metadata (); - signal_changed (THUMBS); -} - -/** @return the number of thumbnail images that we have */ -int -Film::num_thumbs () const -{ - return _state.thumbs.size (); -} - -/** @param n A thumb index. - * @return The frame within the Film that it is for. - */ -int -Film::thumb_frame (int n) const -{ - return _state.thumb_frame (n); -} - -/** @param n A thumb index. - * @return The path to the thumb's image file. - */ -string -Film::thumb_file (int n) const -{ - return _state.thumb_file (n); + sort (thumbs.begin(), thumbs.end()); + set_thumbs (thumbs); } /** @return The path to the directory to write JPEG2000 files to */ @@ -433,18 +155,18 @@ Film::j2k_dir () const /* Start with j2c */ p /= "j2c"; - pair f = Filter::ffmpeg_strings (filters ()); + pair f = Filter::ffmpeg_strings (filters()); /* Write stuff to specify the filter / post-processing settings that are in use, so that we don't get confused about J2K files generated using different settings. */ stringstream s; - s << _state.format->id() - << "_" << _state.content_digest + s << format()->id() + << "_" << content_digest() << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom << "_" << f.first << "_" << f.second - << "_" << _state.scaler->id(); + << "_" << scaler()->id(); p /= s.str (); @@ -456,15 +178,7 @@ Film::j2k_dir () const p /= s.str (); } - return _state.dir (p.string ()); -} - -/** Handle a change to the Film's metadata */ -void -Film::signal_changed (Property p) -{ - _dirty = true; - Changed (p); + return dir (p.string()); } /** Add suitable Jobs to the JobManager to create a DCP for this Film. @@ -502,7 +216,7 @@ Film::make_dcp (bool transcode, int freq) } shared_ptr fs = state_copy (); - shared_ptr o (new Options (j2k_dir(), ".j2c", _state.dir ("wavs"))); + shared_ptr o (new Options (j2k_dir(), ".j2c", dir ("wavs"))); o->out_size = format()->dcp_size (); if (dcp_frames() == 0) { /* Decode the whole film, no blacking */ @@ -527,7 +241,7 @@ Film::make_dcp (bool transcode, int freq) shared_ptr r; if (transcode) { - if (_state.dcp_ab) { + if (dcp_ab()) { r = JobManager::instance()->add (shared_ptr (new ABTranscodeJob (fs, o, log(), shared_ptr ()))); } else { r = JobManager::instance()->add (shared_ptr (new TranscodeJob (fs, o, log(), shared_ptr ()))); @@ -538,16 +252,10 @@ Film::make_dcp (bool transcode, int freq) JobManager::instance()->add (shared_ptr (new MakeDCPJob (fs, o, log(), r))); } -shared_ptr -Film::state_copy () const -{ - return shared_ptr (new FilmState (_state)); -} - void Film::copy_from_dvd_post_gui () { - const string dvd_dir = _state.dir ("dvd"); + const string dvd_dir = dir ("dvd"); string largest_file; uintmax_t largest_size = 0; @@ -582,44 +290,23 @@ Film::examine_content () void Film::examine_content_post_gui () { - _state.length = _examine_content_job->last_video_frame (); - signal_changed (LENGTH); - + set_length (_examine_content_job->last_video_frame ()); _examine_content_job.reset (); } -void -Film::set_scaler (Scaler const * s) -{ - _state.scaler = s; - signal_changed (SCALER); -} /** @return full paths to any audio files that this Film has */ vector Film::audio_files () const { vector f; - for (filesystem::directory_iterator i = filesystem::directory_iterator (_state.dir("wavs")); i != filesystem::directory_iterator(); ++i) { + for (filesystem::directory_iterator i = filesystem::directory_iterator (dir("wavs")); i != filesystem::directory_iterator(); ++i) { f.push_back (i->path().string ()); } return f; } -ContentType -Film::content_type () const -{ - return _state.content_type (); -} - -void -Film::set_still_duration (int d) -{ - _state.still_duration = d; - signal_changed (STILL_DURATION); -} - void Film::send_dcp_to_tms () { @@ -651,31 +338,10 @@ Film::encoded_frames () const return N; } -void -Film::set_with_subtitles (bool w) -{ - _state.with_subtitles = w; - signal_changed (WITH_SUBTITLES); -} - -void -Film::set_subtitle_offset (int o) -{ - _state.subtitle_offset = o; - signal_changed (SUBTITLE_OFFSET); -} - -void -Film::set_subtitle_scale (float s) -{ - _state.subtitle_scale = s; - signal_changed (SUBTITLE_SCALE); -} - pair Film::thumb_subtitle (int n) const { - string sub_file = _state.thumb_base(n) + ".sub"; + string sub_file = thumb_base(n) + ".sub"; if (!filesystem::exists (sub_file)) { return pair (); } @@ -689,79 +355,9 @@ Film::thumb_subtitle (int n) const sub.first.x = lexical_cast (i->second); } else if (i->first == "y") { sub.first.y = lexical_cast (i->second); - sub.second = String::compose ("%1.sub.png", _state.thumb_base(n)); + sub.second = String::compose ("%1.sub.png", thumb_base(n)); } } return sub; } - -void -Film::set_audio_language (string v) -{ - _state.audio_language = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_subtitle_language (string v) -{ - _state.subtitle_language = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_territory (string v) -{ - _state.territory = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_rating (string v) -{ - _state.rating = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_studio (string v) -{ - _state.studio = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_facility (string v) -{ - _state.facility = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_package_type (string v) -{ - _state.package_type = v; - signal_changed (DCI_METADATA); -} - -void -Film::set_use_dci_name (bool v) -{ - _state.use_dci_name = v; - signal_changed (USE_DCI_NAME); -} - -void -Film::set_audio_stream (int id) -{ - _state.audio_stream = id; - signal_changed (AUDIO_STREAM); -} - -void -Film::set_subtitle_stream (int id) -{ - _state.subtitle_stream = id; - signal_changed (SUBTITLE_STREAM); -} diff --git a/src/lib/film.h b/src/lib/film.h index 14731046a..e96c60308 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -30,7 +30,6 @@ #include #include #include -#include extern "C" { #include } @@ -49,235 +48,18 @@ class ExamineContentJob; * A representation of a piece of video (with sound), including naming, * the source content file, and how it should be presented in a DCP. */ -class Film +class Film : public FilmState { public: Film (std::string d, bool must_exist = true); - Film (Film const &); ~Film (); - void write_metadata () const; - - /** @return complete path to directory containing the film metadata */ - std::string directory () const { - return _state.directory; - } - - std::string content () const; - ContentType content_type () const; - - /** @return name for DVD-o-matic */ - std::string name () const { - return _state.name; - } - - /** @return name to give the DCP */ - std::string dcp_name () const { - return _state.dcp_name (); - } - - /** @return true to use a DCI-spec name for the DCP */ - bool use_dci_name () const { - return _state.use_dci_name; - } - - /** @return number of pixels to crop from the sides of the original picture */ - Crop crop () const { - return _state.crop; - } - - /** @return the format to present this film in (flat, scope, etc.) */ - Format const * format () const { - return _state.format; - } - - /** @return video filters that should be used when generating DCPs */ - std::vector filters () const { - return _state.filters; - } - - /** @return scaler algorithm to use */ - Scaler const * scaler () const { - return _state.scaler; - } - - /** @return number of frames to put in the DCP, or 0 for all */ - int dcp_frames () const { - return _state.dcp_frames; - } - - /** @return what to do with the end of an encode when trimming */ - TrimAction dcp_trim_action () const { - return _state.dcp_trim_action; - } - - /** @return true to create an A/B comparison DCP, where the left half of the image - * is the video without any filters or post-processing, and the right half - * has the specified filters and post-processing. - */ - bool dcp_ab () const { - return _state.dcp_ab; - } - - /** @return gain that should be applied to the audio when making a DCP - (in dB). - */ - float audio_gain () const { - return _state.audio_gain; - } - - /** @return delay to apply to audio (positive moves audio later) in milliseconds */ - int audio_delay () const { - return _state.audio_delay; - } - - /** @return duration to make still-sourced films (in seconds) */ - int still_duration () const { - return _state.still_duration; - } - - /** @return true to encode DCP with subtitles, if they are available */ - bool with_subtitles () const { - return _state.with_subtitles; - } - - /** @return offset to move subtitles by, in source pixels; +ve moves - them down the image, -ve moves them up. - */ - int subtitle_offset () const { - return _state.subtitle_offset; - } - - /** @return scaling factor to apply to subtitle images */ - float subtitle_scale () const { - return _state.subtitle_scale; - } - - void set_filters (std::vector const &); - - void set_scaler (Scaler const *); - - /** @return the type of content that this Film represents (feature, trailer etc.) */ - DCPContentType const * dcp_content_type () { - return _state.dcp_content_type; - } - - std::vector audio_streams () const { - return _state.audio_streams; - } - - int audio_stream () const { - return _state.audio_stream; - } - - std::vector subtitle_streams () const { - return _state.subtitle_streams; - } - - int subtitle_stream () const { - return _state.subtitle_stream; - } - - void set_dcp_frames (int); - void set_dcp_trim_action (TrimAction); - void set_dcp_ab (bool); - - void set_name (std::string); - void set_use_dci_name (bool); - void set_content (std::string); - void set_top_crop (int); - void set_bottom_crop (int); - void set_left_crop (int); - void set_right_crop (int); - void set_format (Format const *); - void set_dcp_content_type (DCPContentType const *); - void set_audio_gain (float); - void set_audio_delay (int); - void set_still_duration (int); - void set_with_subtitles (bool); - void set_subtitle_offset (int); - void set_subtitle_scale (float); - void set_audio_language (std::string); - void set_subtitle_language (std::string); - void set_territory (std::string); - void set_rating (std::string); - void set_studio (std::string); - void set_facility (std::string); - void set_package_type (std::string); - void set_audio_stream (int id); - void set_subtitle_stream (int id); - - /** @return size, in pixels, of the source (ignoring cropping) */ - Size size () const { - return _state.size; - } - - /** @return length, in video frames */ - int length () const { - return _state.length; - } - - /** @return nnumber of video frames per second */ - float frames_per_second () const { - return _state.frames_per_second; - } - - /** @return number of audio channels */ - int audio_channels () const { - return _state.audio_channels; - } - - /** @return audio sample rate, in Hz */ - int audio_sample_rate () const { - return _state.audio_sample_rate; - } - - /** @return format of the audio samples */ - AVSampleFormat audio_sample_format () const { - return _state.audio_sample_format; - } - - bool has_subtitles () const { - return _state.has_subtitles; - } - - std::string audio_language () const { - return _state.audio_language; - } - - std::string subtitle_language () const { - return _state.subtitle_language; - } - - std::string territory () const { - return _state.territory; - } - - std::string rating () const { - return _state.rating; - } - - std::string studio () const { - return _state.studio; - } - - std::string facility () const { - return _state.facility; - } - - std::string package_type () const { - return _state.package_type; - } - std::string j2k_dir () const; std::vector audio_files () const; void update_thumbs_pre_gui (); void update_thumbs_post_gui (); - int num_thumbs () const; - int thumb_frame (int) const; - std::string thumb_file (int) const; std::pair thumb_subtitle (int) const; void copy_from_dvd_post_gui (); @@ -286,45 +68,8 @@ public: void send_dcp_to_tms (); void copy_from_dvd (); - /** @return true if our metadata has been modified since it was last saved */ - bool dirty () const { - return _dirty; - } - void make_dcp (bool, int freq = 0); - enum Property { - NONE, - NAME, - CONTENT, - DCP_CONTENT_TYPE, - FORMAT, - CROP, - FILTERS, - SCALER, - DCP_FRAMES, - DCP_TRIM_ACTION, - DCP_AB, - AUDIO_STREAM, - AUDIO_GAIN, - AUDIO_DELAY, - THUMBS, - SIZE, - LENGTH, - FRAMES_PER_SECOND, - AUDIO_CHANNELS, - AUDIO_SAMPLE_RATE, - STILL_DURATION, - SUBTITLE_STREAM, - WITH_SUBTITLES, - SUBTITLE_OFFSET, - SUBTITLE_SCALE, - USE_DCI_NAME, - DCI_METADATA - }; - - boost::shared_ptr state_copy () const; - /** @return Logger. * It is safe to call this from any thread. */ @@ -333,25 +78,8 @@ public: } int encoded_frames () const; - - /** Emitted when some metadata property has changed */ - mutable sigc::signal1 Changed; private: - void read_metadata (); - std::string metadata_file () const; - void update_dimensions (); - void signal_changed (Property); - - /** The majority of our state. Kept in a separate object - * so that it can easily be copied for passing onto long-running - * jobs (which then have an unchanging set of parameters). - */ - FilmState _state; - - /** true if our metadata has changed since it was last written to disk */ - mutable bool _dirty; - /** Log to write to */ Log* _log; diff --git a/src/lib/film_state.cc b/src/lib/film_state.cc index 2717d55ee..f5eb24f86 100644 --- a/src/lib/film_state.cc +++ b/src/lib/film_state.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include "film_state.h" #include "scaler.h" #include "filter.h" @@ -37,6 +38,9 @@ #include "dcp_content_type.h" #include "util.h" #include "exceptions.h" +#include "options.h" +#include "decoder.h" +#include "decoder_factory.h" using namespace std; using namespace boost; @@ -45,31 +49,41 @@ using namespace boost; * @param f Stream to write to. */ void -FilmState::write_metadata (ofstream& f) const +FilmState::write_metadata () const { + filesystem::create_directories (directory()); + + string const m = file ("metadata"); + ofstream f (m.c_str ()); + if (!f.good ()) { + throw CreateFileError (m); + } + + /* XXX: reorder this */ + /* User stuff */ - f << "name " << name << "\n"; - f << "use_dci_name " << use_dci_name << "\n"; - f << "content " << content << "\n"; - if (dcp_content_type) { - f << "dcp_content_type " << dcp_content_type->pretty_name () << "\n"; - } - f << "frames_per_second " << frames_per_second << "\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::const_iterator i = filters.begin(); i != filters.end(); ++i) { + f << "name " << _name << "\n"; + f << "use_dci_name " << _use_dci_name << "\n"; + f << "content " << _content << "\n"; + if (_dcp_content_type) { + f << "dcp_content_type " << _dcp_content_type->pretty_name () << "\n"; + } + f << "frames_per_second " << _frames_per_second << "\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::const_iterator i = _filters.begin(); i != _filters.end(); ++i) { f << "filter " << (*i)->id () << "\n"; } - f << "scaler " << scaler->id () << "\n"; - f << "dcp_frames " << dcp_frames << "\n"; + f << "scaler " << _scaler->id () << "\n"; + f << "dcp_frames " << _dcp_frames << "\n"; f << "dcp_trim_action "; - switch (dcp_trim_action) { + switch (_dcp_trim_action) { case CUT: f << "cut\n"; break; @@ -78,45 +92,47 @@ FilmState::write_metadata (ofstream& f) const break; } - f << "dcp_ab " << (dcp_ab ? "1" : "0") << "\n"; - f << "selected_audio_stream " << audio_stream << "\n"; - f << "audio_gain " << audio_gain << "\n"; - f << "audio_delay " << audio_delay << "\n"; - f << "still_duration " << still_duration << "\n"; - f << "with_subtitles " << with_subtitles << "\n"; - f << "subtitle_offset " << subtitle_offset << "\n"; - f << "subtitle_scale " << subtitle_scale << "\n"; - f << "audio_language " << audio_language << "\n"; - f << "subtitle_language " << subtitle_language << "\n"; - f << "territory " << territory << "\n"; - f << "rating " << rating << "\n"; - f << "studio " << studio << "\n"; - f << "facility " << facility << "\n"; - f << "package_type " << package_type << "\n"; + f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n"; + f << "selected_audio_stream " << _audio_stream << "\n"; + f << "audio_gain " << _audio_gain << "\n"; + f << "audio_delay " << _audio_delay << "\n"; + f << "still_duration " << _still_duration << "\n"; + f << "with_subtitles " << _with_subtitles << "\n"; + f << "subtitle_offset " << _subtitle_offset << "\n"; + f << "subtitle_scale " << _subtitle_scale << "\n"; + f << "audio_language " << _audio_language << "\n"; + f << "subtitle_language " << _subtitle_language << "\n"; + f << "territory " << _territory << "\n"; + f << "rating " << _rating << "\n"; + f << "studio " << _studio << "\n"; + f << "facility " << _facility << "\n"; + f << "package_type " << _package_type << "\n"; /* Cached stuff; this is information about our content; we could look it up each time, but that's slow. */ - for (vector::const_iterator i = thumbs.begin(); i != thumbs.end(); ++i) { + for (vector::const_iterator i = _thumbs.begin(); i != _thumbs.end(); ++i) { f << "thumb " << *i << "\n"; } - f << "width " << size.width << "\n"; - f << "height " << size.height << "\n"; - f << "length " << length << "\n"; - f << "audio_channels " << audio_channels << "\n"; - f << "audio_sample_rate " << audio_sample_rate << "\n"; - f << "audio_sample_format " << audio_sample_format_to_string (audio_sample_format) << "\n"; - f << "content_digest " << content_digest << "\n"; - f << "selected_subtitle_stream " << subtitle_stream << "\n"; - f << "has_subtitles " << has_subtitles << "\n"; - - for (vector::const_iterator i = audio_streams.begin(); i != audio_streams.end(); ++i) { + f << "width " << _size.width << "\n"; + f << "height " << _size.height << "\n"; + f << "length " << _length << "\n"; + f << "audio_channels " << _audio_channels << "\n"; + f << "audio_sample_rate " << _audio_sample_rate << "\n"; + f << "audio_sample_format " << audio_sample_format_to_string (_audio_sample_format) << "\n"; + f << "content_digest " << _content_digest << "\n"; + f << "selected_subtitle_stream " << _subtitle_stream << "\n"; + f << "has_subtitles " << _has_subtitles << "\n"; + + for (vector::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) { f << "audio_stream " << i->to_string () << "\n"; } - for (vector::const_iterator i = subtitle_streams.begin(); i != subtitle_streams.end(); ++i) { + for (vector::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) { f << "subtitle_stream " << i->to_string () << "\n"; } + + _dirty = false; } /** Read state from a key / value pair. @@ -124,106 +140,114 @@ FilmState::write_metadata (ofstream& f) const * @param v Value. */ void -FilmState::read_metadata (string k, string v) -{ - /* User-specified stuff */ - if (k == "name") { - name = v; - } else if (k == "use_dci_name") { - use_dci_name = (v == "1"); - } else if (k == "content") { - content = v; - } else if (k == "dcp_content_type") { - dcp_content_type = DCPContentType::from_pretty_name (v); - } else if (k == "frames_per_second") { - frames_per_second = atof (v.c_str ()); - } else if (k == "format") { - format = Format::from_metadata (v); - } else if (k == "left_crop") { - crop.left = atoi (v.c_str ()); - } else if (k == "right_crop") { - crop.right = atoi (v.c_str ()); - } else if (k == "top_crop") { - crop.top = atoi (v.c_str ()); - } else if (k == "bottom_crop") { - crop.bottom = atoi (v.c_str ()); - } else if (k == "filter") { - filters.push_back (Filter::from_id (v)); - } else if (k == "scaler") { - scaler = Scaler::from_id (v); - } else if (k == "dcp_frames") { - dcp_frames = atoi (v.c_str ()); - } else if (k == "dcp_trim_action") { - if (v == "cut") { - dcp_trim_action = CUT; - } else if (v == "black_out") { - dcp_trim_action = BLACK_OUT; +FilmState::read_metadata () +{ + ifstream f (file("metadata").c_str()); + multimap kv = read_key_value (f); + for (multimap::const_iterator i = kv.begin(); i != kv.end(); ++i) { + string const k = i->first; + string const v = i->second; + + /* User-specified stuff */ + if (k == "name") { + _name = v; + } else if (k == "use_dci_name") { + _use_dci_name = (v == "1"); + } else if (k == "content") { + _content = v; + } else if (k == "dcp_content_type") { + _dcp_content_type = DCPContentType::from_pretty_name (v); + } else if (k == "frames_per_second") { + _frames_per_second = atof (v.c_str ()); + } else if (k == "format") { + _format = Format::from_metadata (v); + } else if (k == "left_crop") { + _crop.left = atoi (v.c_str ()); + } else if (k == "right_crop") { + _crop.right = atoi (v.c_str ()); + } else if (k == "top_crop") { + _crop.top = atoi (v.c_str ()); + } else if (k == "bottom_crop") { + _crop.bottom = atoi (v.c_str ()); + } else if (k == "filter") { + _filters.push_back (Filter::from_id (v)); + } else if (k == "scaler") { + _scaler = Scaler::from_id (v); + } else if (k == "dcp_frames") { + _dcp_frames = atoi (v.c_str ()); + } else if (k == "dcp_trim_action") { + if (v == "cut") { + _dcp_trim_action = CUT; + } else if (v == "black_out") { + _dcp_trim_action = BLACK_OUT; + } + } else if (k == "dcp_ab") { + _dcp_ab = (v == "1"); + } else if (k == "selected_audio_stream") { + _audio_stream = atoi (v.c_str ()); + } else if (k == "audio_gain") { + _audio_gain = atof (v.c_str ()); + } else if (k == "audio_delay") { + _audio_delay = atoi (v.c_str ()); + } else if (k == "still_duration") { + _still_duration = atoi (v.c_str ()); + } else if (k == "with_subtitles") { + _with_subtitles = (v == "1"); + } else if (k == "subtitle_offset") { + _subtitle_offset = atoi (v.c_str ()); + } else if (k == "subtitle_scale") { + _subtitle_scale = atof (v.c_str ()); + } else if (k == "selected_subtitle_stream") { + _subtitle_stream = atoi (v.c_str ()); + } else if (k == "audio_language") { + _audio_language = v; + } else if (k == "subtitle_language") { + _subtitle_language = v; + } else if (k == "territory") { + _territory = v; + } else if (k == "rating") { + _rating = v; + } else if (k == "studio") { + _studio = v; + } else if (k == "facility") { + _facility = v; + } else if (k == "package_type") { + _package_type = v; } - } else if (k == "dcp_ab") { - dcp_ab = (v == "1"); - } else if (k == "selected_audio_stream") { - audio_stream = atoi (v.c_str ()); - } else if (k == "audio_gain") { - audio_gain = atof (v.c_str ()); - } else if (k == "audio_delay") { - audio_delay = atoi (v.c_str ()); - } else if (k == "still_duration") { - still_duration = atoi (v.c_str ()); - } else if (k == "with_subtitles") { - with_subtitles = (v == "1"); - } else if (k == "subtitle_offset") { - subtitle_offset = atoi (v.c_str ()); - } else if (k == "subtitle_scale") { - subtitle_scale = atof (v.c_str ()); - } else if (k == "selected_subtitle_stream") { - subtitle_stream = atoi (v.c_str ()); - } else if (k == "audio_language") { - audio_language = v; - } else if (k == "subtitle_language") { - subtitle_language = v; - } else if (k == "territory") { - territory = v; - } else if (k == "rating") { - rating = v; - } else if (k == "studio") { - studio = v; - } else if (k == "facility") { - facility = v; - } else if (k == "package_type") { - package_type = v; - } - - /* Cached stuff */ - if (k == "thumb") { - int const n = atoi (v.c_str ()); - /* Only add it to the list if it still exists */ - if (filesystem::exists (thumb_file_for_frame (n))) { - thumbs.push_back (n); + + /* Cached stuff */ + if (k == "thumb") { + int const n = atoi (v.c_str ()); + /* Only add it to the list if it still exists */ + if (filesystem::exists (thumb_file_for_frame (n))) { + _thumbs.push_back (n); + } + } else if (k == "width") { + _size.width = atoi (v.c_str ()); + } else if (k == "height") { + _size.height = atoi (v.c_str ()); + } else if (k == "length") { + _length = atof (v.c_str ()); + } else if (k == "audio_channels") { + _audio_channels = atoi (v.c_str ()); + } else if (k == "audio_sample_rate") { + _audio_sample_rate = atoi (v.c_str ()); + } else if (k == "audio_sample_format") { + _audio_sample_format = audio_sample_format_from_string (v); + } else if (k == "content_digest") { + _content_digest = v; + } else if (k == "has_subtitles") { + _has_subtitles = (v == "1"); + } else if (k == "audio_stream") { + _audio_streams.push_back (Stream (v)); + } else if (k == "subtitle_stream") { + _subtitle_streams.push_back (Stream (v)); } - } else if (k == "width") { - size.width = atoi (v.c_str ()); - } else if (k == "height") { - size.height = atoi (v.c_str ()); - } else if (k == "length") { - length = atof (v.c_str ()); - } else if (k == "audio_channels") { - audio_channels = atoi (v.c_str ()); - } else if (k == "audio_sample_rate") { - audio_sample_rate = atoi (v.c_str ()); - } else if (k == "audio_sample_format") { - audio_sample_format = audio_sample_format_from_string (v); - } else if (k == "content_digest") { - content_digest = v; - } else if (k == "has_subtitles") { - has_subtitles = (v == "1"); - } else if (k == "audio_stream") { - audio_streams.push_back (Stream (v)); - } else if (k == "subtitle_stream") { - subtitle_streams.push_back (Stream (v)); } + + _dirty = false; } - /** @param n A thumb index. * @return The path to the thumb's image file. */ @@ -270,15 +294,15 @@ FilmState::thumb_base_for_frame (int n) const int FilmState::thumb_frame (int n) const { - assert (n < int (thumbs.size ())); - return thumbs[n]; + assert (n < int (_thumbs.size ())); + return _thumbs[n]; } Size FilmState::cropped_size (Size s) const { - s.width -= crop.left + crop.right; - s.height -= crop.top + crop.bottom; + s.width -= _crop.left + _crop.right; + s.height -= _crop.top + _crop.bottom; return s; } @@ -289,7 +313,7 @@ string FilmState::dir (string d) const { filesystem::path p; - p /= directory; + p /= _directory; p /= d; filesystem::create_directories (p); return p.string (); @@ -300,28 +324,31 @@ string FilmState::file (string f) const { filesystem::path p; - p /= directory; + p /= _directory; p /= f; return p.string (); } +/** @return full path of the content (actual video) file + * of the Film. + */ string FilmState::content_path () const { - if (filesystem::path(content).has_root_directory ()) { - return content; + if (filesystem::path(_content).has_root_directory ()) { + return _content; } - return file (content); + return file (_content); } ContentType FilmState::content_type () const { #if BOOST_FILESYSTEM_VERSION == 3 - string ext = filesystem::path(content).extension().string(); + string ext = filesystem::path(_content).extension().string(); #else - string ext = filesystem::path(content).extension(); + string ext = filesystem::path(_content).extension(); #endif transform (ext.begin(), ext.end(), ext.begin(), ::tolower); @@ -337,7 +364,7 @@ FilmState::content_type () const int FilmState::bytes_per_sample () const { - switch (audio_sample_format) { + switch (_audio_sample_format) { case AV_SAMPLE_FMT_S16: return 2; default: @@ -351,13 +378,13 @@ int FilmState::target_sample_rate () const { /* Resample to a DCI-approved sample rate */ - double t = dcp_audio_sample_rate (audio_sample_rate); + double t = dcp_audio_sample_rate (_audio_sample_rate); /* Compensate for the fact that video will be rounded to the nearest integer number of frames per second. */ - if (rint (frames_per_second) != frames_per_second) { - t *= frames_per_second / rint (frames_per_second); + if (rint (_frames_per_second) != _frames_per_second) { + t *= _frames_per_second / rint (_frames_per_second); } return rint (t); @@ -366,11 +393,11 @@ FilmState::target_sample_rate () const int FilmState::dcp_length () const { - if (dcp_frames) { - return dcp_frames; + if (_dcp_frames) { + return _dcp_frames; } - return length; + return _length; } /** @return a DCI-compliant name for a DCP of this film */ @@ -379,7 +406,7 @@ FilmState::dci_name () const { stringstream d; - string fixed_name = to_upper_copy (name); + string fixed_name = to_upper_copy (_name); for (size_t i = 0; i < fixed_name.length(); ++i) { if (fixed_name[i] == ' ') { fixed_name[i] = '-'; @@ -393,18 +420,18 @@ FilmState::dci_name () const d << fixed_name << "_"; - if (dcp_content_type) { - d << dcp_content_type->dci_name() << "_"; + if (_dcp_content_type) { + d << _dcp_content_type->dci_name() << "_"; } - if (format) { - d << format->dci_name() << "_"; + if (_format) { + d << _format->dci_name() << "_"; } - if (!audio_language.empty ()) { - d << audio_language; - if (!subtitle_language.empty() && with_subtitles) { - d << "-" << subtitle_language; + if (!_audio_language.empty ()) { + d << _audio_language; + if (!_subtitle_language.empty() && _with_subtitles) { + d << "-" << _subtitle_language; } else { d << "-XX"; } @@ -412,15 +439,15 @@ FilmState::dci_name () const d << "_"; } - if (!territory.empty ()) { - d << territory; - if (!rating.empty ()) { - d << "-" << rating; + if (!_territory.empty ()) { + d << _territory; + if (!_rating.empty ()) { + d << "-" << _rating; } d << "_"; } - switch (audio_channels) { + switch (_audio_channels) { case 1: d << "10_"; break; @@ -434,19 +461,19 @@ FilmState::dci_name () const d << "2K_"; - if (!studio.empty ()) { - d << studio << "_"; + if (!_studio.empty ()) { + d << _studio << "_"; } gregorian::date today = gregorian::day_clock::local_day (); d << gregorian::to_iso_string (today) << "_"; - if (!facility.empty ()) { - d << facility << "_"; + if (!_facility.empty ()) { + d << _facility << "_"; } - if (!package_type.empty ()) { - d << package_type; + if (!_package_type.empty ()) { + d << _package_type; } return d.str (); @@ -456,11 +483,382 @@ FilmState::dci_name () const string FilmState::dcp_name () const { - if (use_dci_name) { + if (_use_dci_name) { return dci_name (); } - return name; + return _name; +} + + +void +FilmState::set_directory (string d) +{ + _directory = d; + _dirty = true; +} + +void +FilmState::set_name (string n) +{ + _name = n; + signal_changed (NAME); +} + +void +FilmState::set_use_dci_name (bool u) +{ + _use_dci_name = u; + signal_changed (USE_DCI_NAME); } +void +FilmState::set_content (string c) +{ + string check = _directory; + +#if BOOST_FILESYSTEM_VERSION == 3 + 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 (filesystem::path(c).has_root_directory () && starts_with (c, check)) { + c = c.substr (_directory.length() + 1); + } + + if (c == _content) { + return; + } + + /* Create a temporary decoder so that we can get information + about the content. + */ + + shared_ptr s = state_copy (); + s->_content = c; + shared_ptr o (new Options ("", "", "")); + o->out_size = Size (1024, 1024); + + shared_ptr d = decoder_factory (s, o, 0, 0); + + set_size (d->native_size ()); + set_length (d->length_in_frames ()); + set_frames_per_second (d->frames_per_second ()); + set_audio_channels (d->audio_channels ()); + set_audio_sample_rate (d->audio_sample_rate ()); + set_audio_sample_format (d->audio_sample_format ()); + set_has_subtitles (d->has_subtitles ()); + set_audio_streams (d->audio_streams ()); + set_subtitle_streams (d->subtitle_streams ()); + set_audio_stream (audio_streams().empty() ? -1 : audio_streams().front().id); + set_subtitle_stream (subtitle_streams().empty() ? -1 : subtitle_streams().front().id); + set_content_digest (md5_digest (content_path ())); + + _content = c; + signal_changed (CONTENT); +} +void +FilmState::set_dcp_content_type (DCPContentType const * t) +{ + _dcp_content_type = t; + signal_changed (DCP_CONTENT_TYPE); +} + +void +FilmState::set_format (Format const * f) +{ + _format = f; + signal_changed (FORMAT); +} + +void +FilmState::set_crop (Crop c) +{ + _crop = c; + signal_changed (CROP); +} + +void +FilmState::set_left_crop (int c) +{ + if (_crop.left == c) { + return; + } + + _crop.left = c; + signal_changed (CROP); +} + +void +FilmState::set_right_crop (int c) +{ + if (_crop.right == c) { + return; + } + + _crop.right = c; + signal_changed (CROP); +} + +void +FilmState::set_top_crop (int c) +{ + if (_crop.top == c) { + return; + } + + _crop.top = c; + signal_changed (CROP); +} + +void +FilmState::set_bottom_crop (int c) +{ + if (_crop.bottom == c) { + return; + } + + _crop.bottom = c; + signal_changed (CROP); +} + +void +FilmState::set_filters (vector f) +{ + _filters = f; + signal_changed (FILTERS); +} + +void +FilmState::set_scaler (Scaler const * s) +{ + _scaler = s; + signal_changed (SCALER); +} + +void +FilmState::set_dcp_frames (int f) +{ + _dcp_frames = f; + signal_changed (DCP_FRAMES); +} + +void +FilmState::set_dcp_trim_action (TrimAction a) +{ + _dcp_trim_action = a; + signal_changed (DCP_TRIM_ACTION); +} + +void +FilmState::set_dcp_ab (bool a) +{ + _dcp_ab = a; + signal_changed (DCP_AB); +} + +void +FilmState::set_audio_stream (int s) +{ + _audio_stream = s; + signal_changed (AUDIO_STREAM); +} + +void +FilmState::set_audio_gain (float g) +{ + _audio_gain = g; + signal_changed (AUDIO_GAIN); +} + +void +FilmState::set_audio_delay (int d) +{ + _audio_delay = d; + signal_changed (AUDIO_DELAY); +} + +void +FilmState::set_still_duration (int d) +{ + _still_duration = d; + signal_changed (STILL_DURATION); +} + +void +FilmState::set_subtitle_stream (int s) +{ + _subtitle_stream = s; + signal_changed (SUBTITLE_STREAM); +} + +void +FilmState::set_with_subtitles (bool w) +{ + _with_subtitles = w; + signal_changed (WITH_SUBTITLES); +} + +void +FilmState::set_subtitle_offset (int o) +{ + _subtitle_offset = o; + signal_changed (SUBTITLE_OFFSET); +} + +void +FilmState::set_subtitle_scale (float s) +{ + _subtitle_scale = s; + signal_changed (SUBTITLE_SCALE); +} + +void +FilmState::set_audio_language (string l) +{ + _audio_language = l; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_subtitle_language (string l) +{ + _subtitle_language = l; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_territory (string t) +{ + _territory = t; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_rating (string r) +{ + _rating = r; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_studio (string s) +{ + _studio = s; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_facility (string f) +{ + _facility = f; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_package_type (string p) +{ + _package_type = p; + signal_changed (DCI_METADATA); +} + +void +FilmState::set_thumbs (vector t) +{ + _thumbs = t; + signal_changed (THUMBS); +} + +void +FilmState::set_size (Size s) +{ + _size = s; + signal_changed (SIZE); +} + +void +FilmState::set_length (int l) +{ + _length = l; + signal_changed (LENGTH); +} + +void +FilmState::set_audio_channels (int c) +{ + _audio_channels = c; + signal_changed (AUDIO_CHANNELS); +} + +void +FilmState::set_audio_sample_rate (int r) +{ + _audio_sample_rate = r; + signal_changed (AUDIO_SAMPLE_RATE); +} + +void +FilmState::set_audio_sample_format (AVSampleFormat f) +{ + _audio_sample_format = f; + _dirty = true; +} + +void +FilmState::set_content_digest (string d) +{ + _content_digest = d; + _dirty = true; +} + +void +FilmState::set_has_subtitles (bool s) +{ + _has_subtitles = s; + signal_changed (HAS_SUBTITLES); +} + +void +FilmState::set_audio_streams (vector s) +{ + _audio_streams = s; + _dirty = true; +} + +void +FilmState::set_subtitle_streams (vector s) +{ + _subtitle_streams = s; + _dirty = true; +} + +void +FilmState::set_frames_per_second (float f) +{ + _frames_per_second = f; + signal_changed (FRAMES_PER_SECOND); +} + +void +FilmState::signal_changed (Property p) +{ + _dirty = true; + Changed (p); +} + +shared_ptr +FilmState::state_copy () const +{ + return shared_ptr (new FilmState (*this)); +} diff --git a/src/lib/film_state.h b/src/lib/film_state.h index 38176f224..2a00c844a 100644 --- a/src/lib/film_state.h +++ b/src/lib/film_state.h @@ -27,6 +27,7 @@ #ifndef DVDOMATIC_FILM_STATE_H #define DVDOMATIC_FILM_STATE_H +#include extern "C" { #include #include @@ -53,27 +54,28 @@ class FilmState { public: FilmState () - : use_dci_name (false) - , dcp_content_type (0) - , frames_per_second (0) - , format (0) - , scaler (Scaler::from_id ("bicubic")) - , dcp_frames (0) - , dcp_trim_action (CUT) - , dcp_ab (false) - , audio_stream (-1) - , audio_gain (0) - , audio_delay (0) - , still_duration (10) - , subtitle_stream (-1) - , with_subtitles (false) - , subtitle_offset (0) - , subtitle_scale (1) - , length (0) - , audio_channels (0) - , audio_sample_rate (0) - , audio_sample_format (AV_SAMPLE_FMT_NONE) - , has_subtitles (false) + : _use_dci_name (false) + , _dcp_content_type (0) + , _format (0) + , _scaler (Scaler::from_id ("bicubic")) + , _dcp_frames (0) + , _dcp_trim_action (CUT) + , _dcp_ab (false) + , _audio_stream (-1) + , _audio_gain (0) + , _audio_delay (0) + , _still_duration (10) + , _subtitle_stream (-1) + , _with_subtitles (false) + , _subtitle_offset (0) + , _subtitle_scale (1) + , _length (0) + , _audio_channels (0) + , _audio_sample_rate (0) + , _audio_sample_format (AV_SAMPLE_FMT_NONE) + , _has_subtitles (false) + , _frames_per_second (0) + , _dirty (false) {} std::string file (std::string f) const; @@ -91,8 +93,8 @@ public: int bytes_per_sample () const; int target_sample_rate () const; - void write_metadata (std::ofstream &) const; - void read_metadata (std::string, std::string); + void write_metadata () const; + void read_metadata (); Size cropped_size (Size) const; int dcp_length () const; @@ -100,89 +102,342 @@ public: std::string dcp_name () const; + boost::shared_ptr state_copy () const; + + bool dirty () const { + return _dirty; + } + + enum Property { + NONE, + NAME, + USE_DCI_NAME, + CONTENT, + DCP_CONTENT_TYPE, + FORMAT, + CROP, + FILTERS, + SCALER, + DCP_FRAMES, + DCP_TRIM_ACTION, + DCP_AB, + AUDIO_STREAM, + AUDIO_GAIN, + AUDIO_DELAY, + STILL_DURATION, + SUBTITLE_STREAM, + WITH_SUBTITLES, + SUBTITLE_OFFSET, + SUBTITLE_SCALE, + DCI_METADATA, + THUMBS, + SIZE, + LENGTH, + AUDIO_CHANNELS, + AUDIO_SAMPLE_RATE, + HAS_SUBTITLES, + AUDIO_STREAMS, + SUBTITLE_STREAMS, + FRAMES_PER_SECOND, + }; + + + /* GET */ + + std::string directory () const { + return _directory; + } + + std::string name () const { + return _name; + } + + bool use_dci_name () const { + return _use_dci_name; + } + + std::string content () const { + return _content; + } + + DCPContentType const * dcp_content_type () const { + return _dcp_content_type; + } + + Format const * format () const { + return _format; + } + + Crop crop () const { + return _crop; + } + + std::vector filters () const { + return _filters; + } + + Scaler const * scaler () const { + return _scaler; + } + + int dcp_frames () const { + return _dcp_frames; + } + + TrimAction dcp_trim_action () const { + return _dcp_trim_action; + } + + bool dcp_ab () const { + return _dcp_ab; + } + + int audio_stream () const { + return _audio_stream; + } + + float audio_gain () const { + return _audio_gain; + } + + int audio_delay () const { + return _audio_delay; + } + + int still_duration () const { + return _still_duration; + } + + int subtitle_stream () const { + return _subtitle_stream; + } + + bool with_subtitles () const { + return _with_subtitles; + } + + int subtitle_offset () const { + return _subtitle_offset; + } + + float subtitle_scale () const { + return _subtitle_scale; + } + + std::string audio_language () const { + return _audio_language; + } + + std::string subtitle_language () const { + return _subtitle_language; + } + + std::string territory () const { + return _territory; + } + + std::string rating () const { + return _rating; + } + + std::string studio () const { + return _studio; + } + + std::string facility () const { + return _facility; + } + + std::string package_type () const { + return _package_type; + } + + std::vector thumbs () const { + return _thumbs; + } + + Size size () const { + return _size; + } + + int length () const { + return _length; + } + + int audio_channels () const { + return _audio_channels; + } + + int audio_sample_rate () const { + return _audio_sample_rate; + } + + AVSampleFormat audio_sample_format () const { + return _audio_sample_format; + } + + std::string content_digest () const { + return _content_digest; + } + + bool has_subtitles () const { + return _has_subtitles; + } + + std::vector audio_streams () const { + return _audio_streams; + } + + std::vector subtitle_streams () const { + return _subtitle_streams; + } + + float frames_per_second () const { + return _frames_per_second; + } + + + /* SET */ + + void set_directory (std::string); + void set_name (std::string); + void set_use_dci_name (bool); + void set_content (std::string); + void set_dcp_content_type (DCPContentType const *); + void set_format (Format const *); + void set_crop (Crop); + void set_left_crop (int); + void set_right_crop (int); + void set_top_crop (int); + void set_bottom_crop (int); + void set_filters (std::vector); + void set_scaler (Scaler const *); + void set_dcp_frames (int); + void set_dcp_trim_action (TrimAction); + void set_dcp_ab (bool); + void set_audio_stream (int); + void set_audio_gain (float); + void set_audio_delay (int); + void set_still_duration (int); + void set_subtitle_stream (int); + void set_with_subtitles (bool); + void set_subtitle_offset (int); + void set_subtitle_scale (float); + void set_audio_language (std::string); + void set_subtitle_language (std::string); + void set_territory (std::string); + void set_rating (std::string); + void set_studio (std::string); + void set_facility (std::string); + void set_package_type (std::string); + void set_thumbs (std::vector); + void set_size (Size); + void set_length (int); + void set_audio_channels (int); + void set_audio_sample_rate (int); + void set_audio_sample_format (AVSampleFormat); + void set_content_digest (std::string); + void set_has_subtitles (bool); + void set_audio_streams (std::vector); + void set_subtitle_streams (std::vector); + void set_frames_per_second (float); + + /** Emitted when some property has changed */ + mutable sigc::signal1 Changed; + +private: + + std::string thumb_file_for_frame (int) const; + std::string thumb_base_for_frame (int) const; + void signal_changed (Property); + /** Complete path to directory containing the film metadata; - must not be relative. - */ - std::string directory; + * must not be relative. + */ + std::string _directory; /** Name for DVD-o-matic */ - std::string name; + std::string _name; /** True if a auto-generated DCI-compliant name should be used for our DCP */ - bool use_dci_name; + bool _use_dci_name; /** File or directory containing content; may be relative to our directory * or an absolute path. */ - std::string content; + std::string _content; /** The type of content that this Film represents (feature, trailer etc.) */ - DCPContentType const * dcp_content_type; - /** Frames per second of the source */ - float frames_per_second; + DCPContentType const * _dcp_content_type; /** The format to present this Film in (flat, scope, etc.) */ - Format const * format; - Crop crop; + Format const * _format; + /** The crop to apply to the source */ + Crop _crop; /** Video filters that should be used when generating DCPs */ - std::vector filters; + std::vector _filters; /** Scaler algorithm to use */ - Scaler const * scaler; + Scaler const * _scaler; /** Number of frames to put in the DCP, or 0 for all */ - int dcp_frames; - - TrimAction dcp_trim_action; - + int _dcp_frames; + /** What to do with audio when trimming DCPs */ + TrimAction _dcp_trim_action; /** true to create an A/B comparison DCP, where the left half of the image is the video without any filters or post-processing, and the right half has the specified filters and post-processing. */ - bool dcp_ab; - int audio_stream; + bool _dcp_ab; + /** The decoder's stream ID to use for audio, or -1 if there is none */ + int _audio_stream; /** Gain to apply to audio in dB */ - float audio_gain; + float _audio_gain; /** Delay to apply to audio (positive moves audio later) in milliseconds */ - int audio_delay; + int _audio_delay; /** Duration to make still-sourced films (in seconds) */ - int still_duration; - int subtitle_stream; + int _still_duration; + /** The decoder's stream ID to use for subtitles, or -1 if there are none */ + int _subtitle_stream; /** True if subtitles should be shown for this film */ - bool with_subtitles; + bool _with_subtitles; /** y offset for placing subtitles, in source pixels; +ve is further down the frame, -ve is further up. */ - int subtitle_offset; + int _subtitle_offset; /** scale factor to apply to subtitles */ - float subtitle_scale; + float _subtitle_scale; /* DCI naming stuff */ - std::string audio_language; - std::string subtitle_language; - std::string territory; - std::string rating; - std::string studio; - std::string facility; - std::string package_type; + std::string _audio_language; + std::string _subtitle_language; + std::string _territory; + std::string _rating; + std::string _studio; + std::string _facility; + std::string _package_type; - /* Data which is cached to speed things up */ + /* Data which are cached to speed things up */ /** Vector of frame indices for each of our `thumbnails' */ - std::vector thumbs; + std::vector _thumbs; /** Size, in pixels, of the source (ignoring cropping) */ - Size size; + Size _size; /** Length of the source in frames */ - int length; + int _length; /** Number of audio channels */ - int audio_channels; + int _audio_channels; /** Sample rate of the source audio, in Hz */ - int audio_sample_rate; + int _audio_sample_rate; /** Format of the audio samples */ - AVSampleFormat audio_sample_format; + AVSampleFormat _audio_sample_format; /** MD5 digest of our content file */ - std::string content_digest; + std::string _content_digest; /** true if the source has subtitles */ - bool has_subtitles; - std::vector audio_streams; - std::vector subtitle_streams; + bool _has_subtitles; + /** the audio streams that the source has */ + std::vector _audio_streams; + /** the subtitle streams that the source has */ + std::vector _subtitle_streams; + /** Frames per second of the source */ + float _frames_per_second; -private: - std::string thumb_file_for_frame (int) const; - std::string thumb_base_for_frame (int) const; + mutable bool _dirty; + + friend class paths_test; }; #endif diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc index 2518f8dc5..082fd13e8 100644 --- a/src/lib/imagemagick_encoder.cc +++ b/src/lib/imagemagick_encoder.cc @@ -53,7 +53,7 @@ ImageMagickEncoder::ImageMagickEncoder (shared_ptr s, shared_pt void ImageMagickEncoder::process_video (shared_ptr image, int frame, shared_ptr sub) { - shared_ptr scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _fs->scaler); + shared_ptr scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _fs->scaler()); shared_ptr compact (new CompactImage (scaled)); string tmp_file = _opt->frame_out_path (frame, true); @@ -63,8 +63,8 @@ ImageMagickEncoder::process_video (shared_ptr image, int frame, shared_pt filesystem::rename (tmp_file, _opt->frame_out_path (frame, false)); if (sub) { - float const x_scale = float (_opt->out_size.width) / _fs->size.width; - float const y_scale = float (_opt->out_size.height) / _fs->size.height; + float const x_scale = float (_opt->out_size.width) / _fs->size().width; + float const y_scale = float (_opt->out_size.height) / _fs->size().height; string tmp_metadata_file = _opt->frame_out_path (frame, false, ".sub"); ofstream metadata (tmp_metadata_file.c_str ()); @@ -72,7 +72,7 @@ ImageMagickEncoder::process_video (shared_ptr image, int frame, shared_pt Size new_size = sub->image()->size (); new_size.width *= x_scale; new_size.height *= y_scale; - shared_ptr scaled = sub->image()->scale (new_size, _fs->scaler); + shared_ptr scaled = sub->image()->scale (new_size, _fs->scaler()); shared_ptr compact (new CompactImage (scaled)); string tmp_sub_file = _opt->frame_out_path (frame, true, ".sub.png"); diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc index 2b8aca649..de2f1eb46 100644 --- a/src/lib/j2k_still_encoder.cc +++ b/src/lib/j2k_still_encoder.cc @@ -50,9 +50,9 @@ J2KStillEncoder::J2KStillEncoder (shared_ptr s, shared_ptr yuv, int frame, shared_ptr sub) { - pair const s = Filter::ffmpeg_strings (_fs->filters); + pair const s = Filter::ffmpeg_strings (_fs->filters()); DCPVideoFrame* f = new DCPVideoFrame ( - yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset, _fs->subtitle_scale, _fs->scaler, 0, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset(), _fs->subtitle_scale(), _fs->scaler(), 0, _fs->frames_per_second(), s.second, Config::instance()->colour_lut_index(), Config::instance()->j2k_bandwidth(), _log ); @@ -63,7 +63,7 @@ J2KStillEncoder::process_video (shared_ptr yuv, int frame, shared_ptrframe_out_path (0, false); - for (int i = 1; i < (_fs->still_duration * ImageMagickDecoder::static_frames_per_second()); ++i) { + for (int i = 1; i < (_fs->still_duration() * ImageMagickDecoder::static_frames_per_second()); ++i) { if (!boost::filesystem::exists (_opt->frame_out_path (i, false))) { string const link = _opt->frame_out_path (i, false); #ifdef DVDOMATIC_POSIX diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc index e2a3a5ed7..e5d120ad6 100644 --- a/src/lib/j2k_wav_encoder.cc +++ b/src/lib/j2k_wav_encoder.cc @@ -56,9 +56,9 @@ J2KWAVEncoder::J2KWAVEncoder (shared_ptr s, shared_ptraudio_channels; ++i) { + for (int i = 0; i < _fs->audio_channels(); ++i) { SF_INFO sf_info; - sf_info.samplerate = dcp_audio_sample_rate (_fs->audio_sample_rate); + sf_info.samplerate = dcp_audio_sample_rate (_fs->audio_sample_rate()); /* We write mono files */ sf_info.channels = 1; sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24; @@ -122,12 +122,12 @@ J2KWAVEncoder::process_video (shared_ptr yuv, int frame, shared_ptrframe_out_path (frame, false))) { - pair const s = Filter::ffmpeg_strings (_fs->filters); + pair const s = Filter::ffmpeg_strings (_fs->filters()); TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (boost::shared_ptr ( new DCPVideoFrame ( - yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset, _fs->subtitle_scale, - _fs->scaler, frame, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset(), _fs->subtitle_scale(), + _fs->scaler(), frame, _fs->frames_per_second(), s.second, Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (), _log ) @@ -224,11 +224,11 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server) void J2KWAVEncoder::process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) { - if (_fs->audio_sample_rate != _fs->target_sample_rate ()) { + if (_fs->audio_sample_rate() != _fs->target_sample_rate()) { #ifdef HAVE_SWRESAMPLE stringstream s; - s << "Will resample audio from " << _fs->audio_sample_rate << " to " << _fs->target_sample_rate(); + s << "Will resample audio from " << _fs->audio_sample_rate() << " to " << _fs->target_sample_rate(); _log->log (s.str ()); _swr_context = swr_alloc_set_opts ( @@ -238,7 +238,7 @@ J2KWAVEncoder::process_begin (int64_t audio_channel_layout, AVSampleFormat audio _fs->target_sample_rate(), audio_channel_layout, audio_sample_format, - _fs->audio_sample_rate, + _fs->audio_sample_rate(), 0, 0 ); @@ -309,7 +309,7 @@ J2KWAVEncoder::process_end () if (_swr_context) { while (1) { - uint8_t buffer[256 * _fs->bytes_per_sample() * _fs->audio_channels]; + uint8_t buffer[256 * _fs->bytes_per_sample() * _fs->audio_channels()]; uint8_t* out[2] = { buffer, 0 @@ -325,7 +325,7 @@ J2KWAVEncoder::process_end () break; } - write_audio (buffer, frames * _fs->bytes_per_sample() * _fs->audio_channels); + write_audio (buffer, frames * _fs->bytes_per_sample() * _fs->audio_channels()); } swr_free (&_swr_context); @@ -335,7 +335,7 @@ J2KWAVEncoder::process_end () close_sound_files (); /* Rename .wav.tmp files to .wav */ - for (int i = 0; i < _fs->audio_channels; ++i) { + for (int i = 0; i < _fs->audio_channels(); ++i) { if (boost::filesystem::exists (_opt->multichannel_audio_out_path (i, false))) { boost::filesystem::remove (_opt->multichannel_audio_out_path (i, false)); } @@ -366,11 +366,11 @@ J2KWAVEncoder::process_audio (uint8_t* data, int size) /* And here's frames (where 1 frame is a collection of samples, 1 for each channel, so for 5.1 a frame would be 6 samples) */ - int const frames = samples / _fs->audio_channels; + int const frames = samples / _fs->audio_channels(); /* Compute the resampled frame count and add 32 for luck */ - int const out_buffer_size_frames = ceil (frames * _fs->target_sample_rate() / _fs->audio_sample_rate) + 32; - int const out_buffer_size_bytes = out_buffer_size_frames * _fs->audio_channels * _fs->bytes_per_sample(); + int const out_buffer_size_frames = ceil (frames * _fs->target_sample_rate() / _fs->audio_sample_rate()) + 32; + int const out_buffer_size_bytes = out_buffer_size_frames * _fs->audio_channels() * _fs->bytes_per_sample(); out_buffer = new uint8_t[out_buffer_size_bytes]; uint8_t* out[2] = { @@ -386,7 +386,7 @@ J2KWAVEncoder::process_audio (uint8_t* data, int size) /* And point our variables at the resampled audio */ data = out_buffer; - size = out_frames * _fs->audio_channels * _fs->bytes_per_sample(); + size = out_frames * _fs->audio_channels() * _fs->bytes_per_sample(); } #endif @@ -403,7 +403,7 @@ J2KWAVEncoder::write_audio (uint8_t* data, int size) of the sample size and that size is a multiple of _fs->audio_channels * sample_size. */ - assert ((size % (_fs->audio_channels * _fs->bytes_per_sample())) == 0); + assert ((size % (_fs->audio_channels() * _fs->bytes_per_sample())) == 0); assert ((_deinterleave_buffer_size % _fs->bytes_per_sample()) == 0); /* XXX: this code is very tricksy and it must be possible to make it simpler ... */ @@ -414,17 +414,17 @@ J2KWAVEncoder::write_audio (uint8_t* data, int size) int position = 0; while (remaining > 0) { /* How many bytes of the deinterleaved data to do this time */ - int this_time = min (remaining / _fs->audio_channels, _deinterleave_buffer_size); - for (int i = 0; i < _fs->audio_channels; ++i) { + int this_time = min (remaining / _fs->audio_channels(), _deinterleave_buffer_size); + for (int i = 0; i < _fs->audio_channels(); ++i) { for (int j = 0; j < this_time; j += _fs->bytes_per_sample()) { for (int k = 0; k < _fs->bytes_per_sample(); ++k) { int const to = j + k; - int const from = position + (i * _fs->bytes_per_sample()) + (j * _fs->audio_channels) + k; + int const from = position + (i * _fs->bytes_per_sample()) + (j * _fs->audio_channels()) + k; _deinterleave_buffer[to] = data[from]; } } - switch (_fs->audio_sample_format) { + switch (_fs->audio_sample_format()) { case AV_SAMPLE_FMT_S16: sf_write_short (_sound_files[i], (const short *) _deinterleave_buffer, this_time / _fs->bytes_per_sample()); break; @@ -434,7 +434,7 @@ J2KWAVEncoder::write_audio (uint8_t* data, int size) } position += this_time; - remaining -= this_time * _fs->audio_channels; + remaining -= this_time * _fs->audio_channels(); } } diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index efd35ba44..83904fd60 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -52,7 +52,7 @@ MakeDCPJob::MakeDCPJob (shared_ptr s, shared_ptr string MakeDCPJob::name () const { - return String::compose ("Make DCP for %1", _fs->name); + return String::compose ("Make DCP for %1", _fs->name()); } string @@ -78,17 +78,20 @@ MakeDCPJob::run () int frames = 0; switch (_fs->content_type ()) { case VIDEO: - frames = _fs->dcp_frames ? _fs->dcp_frames : _fs->length; + frames = _fs->dcp_length (); break; case STILL: - frames = _fs->still_duration * ImageMagickDecoder::static_frames_per_second (); + frames = _fs->still_duration() * ImageMagickDecoder::static_frames_per_second (); break; } libdcp::DCP dcp (_fs->dir (_fs->dcp_name())); dcp.Progress.connect (sigc::mem_fun (*this, &MakeDCPJob::dcp_progress)); - shared_ptr cpl (new libdcp::CPL (_fs->dir (_fs->dcp_name()), _fs->dcp_name(), _fs->dcp_content_type->libdcp_kind (), frames, rint (_fs->frames_per_second))); + shared_ptr cpl ( + new libdcp::CPL (_fs->dir (_fs->dcp_name()), _fs->dcp_name(), _fs->dcp_content_type()->libdcp_kind (), frames, rint (_fs->frames_per_second())) + ); + dcp.add_cpl (cpl); descend (0.9); @@ -98,7 +101,7 @@ MakeDCPJob::run () _fs->dir (_fs->dcp_name()), "video.mxf", &dcp.Progress, - rint (_fs->frames_per_second), + rint (_fs->frames_per_second()), frames, _opt->out_size.width, _opt->out_size.height @@ -109,7 +112,7 @@ MakeDCPJob::run () shared_ptr sa; - if (_fs->audio_channels > 0) { + if (_fs->audio_channels() > 0) { descend (0.1); sa.reset ( new libdcp::SoundAsset ( @@ -117,9 +120,9 @@ MakeDCPJob::run () _fs->dir (_fs->dcp_name()), "audio.mxf", &dcp.Progress, - rint (_fs->frames_per_second), + rint (_fs->frames_per_second()), frames, - _fs->audio_channels + _fs->audio_channels() ) ); ascend (); diff --git a/src/lib/thumbs_job.cc b/src/lib/thumbs_job.cc index 16a8a7b01..845dc9675 100644 --- a/src/lib/thumbs_job.cc +++ b/src/lib/thumbs_job.cc @@ -44,7 +44,7 @@ ThumbsJob::ThumbsJob (shared_ptr s, shared_ptr o string ThumbsJob::name () const { - return String::compose ("Update thumbs for %1", _fs->name); + return String::compose ("Update thumbs for %1", _fs->name()); } void diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc index 101e0c047..27dd0d69c 100644 --- a/src/lib/tiff_decoder.cc +++ b/src/lib/tiff_decoder.cc @@ -205,7 +205,7 @@ TIFFDecoder::pixel_format () const int TIFFDecoder::time_base_numerator () const { - return rint (_fs->frames_per_second);; + return rint (_fs->frames_per_second()); } diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index a53a4b6ad..3776ea4c1 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -48,7 +48,7 @@ TranscodeJob::TranscodeJob (shared_ptr s, shared_ptrname); + return String::compose ("Transcode %1", _fs->name()); } void diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc index d3608059c..51b45f2d6 100644 --- a/src/tools/makedcp.cc +++ b/src/tools/makedcp.cc @@ -143,7 +143,7 @@ main (int argc, char* argv[]) film->log()->set_level ((Log::Level) log_level); cout << "\nMaking "; - if (film->dcp_ab ()) { + if (film->dcp_ab()) { cout << "A/B "; } cout << "DCP for " << film->name() << "\n"; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index c687975ba..7ed3a14c7 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -51,7 +51,7 @@ using namespace boost; /** @param f Film to edit */ FilmEditor::FilmEditor (Film* f, wxWindow* parent) : wxPanel (parent) - , _ignore_changes (Film::NONE) + , _ignore_changes (FilmState::NONE) , _film (f) { _sizer = new wxFlexGridSizer (2, 4, 4); @@ -273,9 +273,9 @@ FilmEditor::left_crop_changed (wxCommandEvent &) return; } - _ignore_changes = Film::CROP; + _ignore_changes = FilmState::CROP; _film->set_left_crop (_left_crop->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } /** Called when the right crop widget has been changed */ @@ -286,9 +286,9 @@ FilmEditor::right_crop_changed (wxCommandEvent &) return; } - _ignore_changes = Film::CROP; + _ignore_changes = FilmState::CROP; _film->set_right_crop (_right_crop->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } /** Called when the top crop widget has been changed */ @@ -299,9 +299,9 @@ FilmEditor::top_crop_changed (wxCommandEvent &) return; } - _ignore_changes = Film::CROP; + _ignore_changes = FilmState::CROP; _film->set_top_crop (_top_crop->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } /** Called when the bottom crop value has been changed */ @@ -312,9 +312,9 @@ FilmEditor::bottom_crop_changed (wxCommandEvent &) return; } - _ignore_changes = Film::CROP; + _ignore_changes = FilmState::CROP; _film->set_bottom_crop (_bottom_crop->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } /** Called when the content filename has been changed */ @@ -325,7 +325,7 @@ FilmEditor::content_changed (wxCommandEvent &) return; } - _ignore_changes = Film::CONTENT; + _ignore_changes = FilmState::CONTENT; try { _film->set_content (wx_to_std (_content->GetPath ())); @@ -334,7 +334,7 @@ FilmEditor::content_changed (wxCommandEvent &) error_dialog (this, String::compose ("Could not set content: %1", e.what ())); } - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; setup_visibility (); setup_formats (); @@ -350,9 +350,9 @@ FilmEditor::dcp_ab_toggled (wxCommandEvent &) return; } - _ignore_changes = Film::DCP_AB; + _ignore_changes = FilmState::DCP_AB; _film->set_dcp_ab (_dcp_ab->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } /** Called when the name widget has been changed */ @@ -363,9 +363,9 @@ FilmEditor::name_changed (wxCommandEvent &) return; } - _ignore_changes = Film::NAME; + _ignore_changes = FilmState::NAME; _film->set_name (string (_name->GetValue().mb_str())); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); } @@ -377,9 +377,9 @@ FilmEditor::subtitle_offset_changed (wxCommandEvent &) return; } - _ignore_changes = Film::SUBTITLE_OFFSET; + _ignore_changes = FilmState::SUBTITLE_OFFSET; _film->set_subtitle_offset (_subtitle_offset->GetValue ()); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } void @@ -389,9 +389,9 @@ FilmEditor::subtitle_scale_changed (wxCommandEvent &) return; } - _ignore_changes = Film::SUBTITLE_OFFSET; + _ignore_changes = FilmState::SUBTITLE_OFFSET; _film->set_subtitle_scale (_subtitle_scale->GetValue() / 100.0); - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; } @@ -400,7 +400,7 @@ FilmEditor::subtitle_scale_changed (wxCommandEvent &) * @param p Property of the Film that has changed. */ void -FilmEditor::film_changed (Film::Property p) +FilmEditor::film_changed (FilmState::Property p) { if (!_film || _ignore_changes == p) { return; @@ -409,16 +409,24 @@ FilmEditor::film_changed (Film::Property p) stringstream s; switch (p) { - case Film::NONE: + case FilmState::NONE: break; - case Film::CONTENT: + case FilmState::CONTENT: _content->SetPath (std_to_wx (_film->content ())); setup_visibility (); setup_formats (); setup_subtitle_button (); setup_streams (); break; - case Film::FORMAT: + case FilmState::HAS_SUBTITLES: + setup_subtitle_button (); + setup_streams (); + break; + case FilmState::AUDIO_STREAMS: + case FilmState::SUBTITLE_STREAMS: + setup_streams (); + break; + case FilmState::FORMAT: { int n = 0; vector::iterator i = _formats.begin (); @@ -430,13 +438,13 @@ FilmEditor::film_changed (Film::Property p) _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; } - case Film::CROP: + case FilmState::CROP: _left_crop->SetValue (_film->crop().left); _right_crop->SetValue (_film->crop().right); _top_crop->SetValue (_film->crop().top); _bottom_crop->SetValue (_film->crop().bottom); break; - case Film::FILTERS: + case FilmState::FILTERS: { pair p = Filter::ffmpeg_strings (_film->filters ()); if (p.first.empty () && p.second.empty ()) { @@ -448,20 +456,20 @@ FilmEditor::film_changed (Film::Property p) _sizer->Layout (); break; } - case Film::NAME: + case FilmState::NAME: _name->ChangeValue (std_to_wx (_film->name ())); _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; - case Film::FRAMES_PER_SECOND: + case FilmState::FRAMES_PER_SECOND: { stringstream s; s << fixed << setprecision(2) << _film->frames_per_second(); _frames_per_second->SetLabel (std_to_wx (s.str ())); break; } - case Film::AUDIO_CHANNELS: + case FilmState::AUDIO_CHANNELS: _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); - case Film::AUDIO_SAMPLE_RATE: + case FilmState::AUDIO_SAMPLE_RATE: if (_film->audio_channels() == 0 && _film->audio_sample_rate() == 0) { _audio->SetLabel (wxT ("")); } else { @@ -469,7 +477,7 @@ FilmEditor::film_changed (Film::Property p) _audio->SetLabel (std_to_wx (s.str ())); } break; - case Film::SIZE: + case FilmState::SIZE: if (_film->size().width == 0 && _film->size().height == 0) { _original_size->SetLabel (wxT ("")); } else { @@ -477,7 +485,7 @@ FilmEditor::film_changed (Film::Property p) _original_size->SetLabel (std_to_wx (s.str ())); } break; - case Film::LENGTH: + case FilmState::LENGTH: if (_film->frames_per_second() > 0 && _film->length() > 0) { s << _film->length() << " frames; " << seconds_to_hms (_film->length() / _film->frames_per_second()); } else if (_film->length() > 0) { @@ -485,13 +493,13 @@ FilmEditor::film_changed (Film::Property p) } _length->SetLabel (std_to_wx (s.str ())); break; - case Film::DCP_CONTENT_TYPE: + case FilmState::DCP_CONTENT_TYPE: _dcp_content_type->SetSelection (DCPContentType::as_index (_film->dcp_content_type ())); _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; - case Film::THUMBS: + case FilmState::THUMBS: break; - case Film::DCP_FRAMES: + case FilmState::DCP_FRAMES: if (_film->dcp_frames() == 0) { _dcp_range->SetLabel (wxT ("Whole film")); } else { @@ -501,46 +509,46 @@ FilmEditor::film_changed (Film::Property p) } _sizer->Layout (); break; - case Film::DCP_TRIM_ACTION: + case FilmState::DCP_TRIM_ACTION: break; - case Film::DCP_AB: + case FilmState::DCP_AB: _dcp_ab->SetValue (_film->dcp_ab ()); break; - case Film::SCALER: + case FilmState::SCALER: _scaler->SetSelection (Scaler::as_index (_film->scaler ())); break; - case Film::AUDIO_GAIN: + case FilmState::AUDIO_GAIN: _audio_gain->SetValue (_film->audio_gain ()); break; - case Film::AUDIO_DELAY: + case FilmState::AUDIO_DELAY: _audio_delay->SetValue (_film->audio_delay ()); break; - case Film::STILL_DURATION: + case FilmState::STILL_DURATION: _still_duration->SetValue (_film->still_duration ()); break; - case Film::WITH_SUBTITLES: + case FilmState::WITH_SUBTITLES: _with_subtitles->SetValue (_film->with_subtitles ()); _subtitle_scale->Enable (_film->with_subtitles ()); _subtitle_offset->Enable (_film->with_subtitles ()); _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; - case Film::SUBTITLE_OFFSET: + case FilmState::SUBTITLE_OFFSET: _subtitle_offset->SetValue (_film->subtitle_offset ()); break; - case Film::SUBTITLE_SCALE: + case FilmState::SUBTITLE_SCALE: _subtitle_scale->SetValue (_film->subtitle_scale() * 100); break; - case Film::USE_DCI_NAME: + case FilmState::USE_DCI_NAME: _use_dci_name->SetValue (_film->use_dci_name ()); _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; - case Film::DCI_METADATA: + case FilmState::DCI_METADATA: _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); break; - case Film::AUDIO_STREAM: + case FilmState::AUDIO_STREAM: set_selected_stream (_film->audio_streams(), _film->audio_stream(), _audio_stream); break; - case Film::SUBTITLE_STREAM: + case FilmState::SUBTITLE_STREAM: set_selected_stream (_film->subtitle_streams(), _film->subtitle_stream(), _subtitle_stream); break; } @@ -554,13 +562,13 @@ FilmEditor::format_changed (wxCommandEvent &) return; } - _ignore_changes = Film::FORMAT; + _ignore_changes = FilmState::FORMAT; int const n = _format->GetSelection (); if (n >= 0) { assert (n < int (_formats.size())); _film->set_format (_formats[n]); } - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); } @@ -573,12 +581,12 @@ FilmEditor::dcp_content_type_changed (wxCommandEvent &) return; } - _ignore_changes = Film::DCP_CONTENT_TYPE; + _ignore_changes = FilmState::DCP_CONTENT_TYPE; int const n = _dcp_content_type->GetSelection (); if (n >= 0) { _film->set_dcp_content_type (DCPContentType::from_index (n)); } - _ignore_changes = Film::NONE; + _ignore_changes = FilmState::NONE; _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); } @@ -601,29 +609,29 @@ FilmEditor::set_film (Film* f) FileChanged (""); } - film_changed (Film::NAME); - film_changed (Film::CONTENT); - film_changed (Film::DCP_CONTENT_TYPE); - film_changed (Film::FORMAT); - film_changed (Film::CROP); - film_changed (Film::FILTERS); - film_changed (Film::DCP_FRAMES); - film_changed (Film::DCP_TRIM_ACTION); - film_changed (Film::DCP_AB); - film_changed (Film::SIZE); - film_changed (Film::LENGTH); - film_changed (Film::FRAMES_PER_SECOND); - film_changed (Film::AUDIO_CHANNELS); - film_changed (Film::AUDIO_SAMPLE_RATE); - film_changed (Film::SCALER); - film_changed (Film::AUDIO_GAIN); - film_changed (Film::AUDIO_DELAY); - film_changed (Film::STILL_DURATION); - film_changed (Film::WITH_SUBTITLES); - film_changed (Film::SUBTITLE_OFFSET); - film_changed (Film::SUBTITLE_SCALE); - film_changed (Film::USE_DCI_NAME); - film_changed (Film::DCI_METADATA); + film_changed (FilmState::NAME); + film_changed (FilmState::CONTENT); + film_changed (FilmState::DCP_CONTENT_TYPE); + film_changed (FilmState::FORMAT); + film_changed (FilmState::CROP); + film_changed (FilmState::FILTERS); + film_changed (FilmState::DCP_FRAMES); + film_changed (FilmState::DCP_TRIM_ACTION); + film_changed (FilmState::DCP_AB); + film_changed (FilmState::SIZE); + film_changed (FilmState::LENGTH); + film_changed (FilmState::FRAMES_PER_SECOND); + film_changed (FilmState::AUDIO_CHANNELS); + film_changed (FilmState::AUDIO_SAMPLE_RATE); + film_changed (FilmState::SCALER); + film_changed (FilmState::AUDIO_GAIN); + film_changed (FilmState::AUDIO_DELAY); + film_changed (FilmState::STILL_DURATION); + film_changed (FilmState::WITH_SUBTITLES); + film_changed (FilmState::SUBTITLE_OFFSET); + film_changed (FilmState::SUBTITLE_SCALE); + film_changed (FilmState::USE_DCI_NAME); + film_changed (FilmState::DCI_METADATA); } /** Updates the sensitivity of lots of widgets to a given value. @@ -661,7 +669,7 @@ FilmEditor::set_things_sensitive (bool s) void FilmEditor::edit_filters_clicked (wxCommandEvent &) { - FilterDialog* d = new FilterDialog (this, _film->filters ()); + FilterDialog* d = new FilterDialog (this, _film->filters()); d->ActiveChanged.connect (sigc::mem_fun (*_film, &Film::set_filters)); d->ShowModal (); d->Destroy (); diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index b204385bc..b50bfd1f9 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -69,7 +69,7 @@ private: void subtitle_stream_changed (wxCommandEvent &); /* Handle changes to the model */ - void film_changed (Film::Property); + void film_changed (FilmState::Property); /* Button clicks */ void edit_filters_clicked (wxCommandEvent &); @@ -84,7 +84,7 @@ private: wxControl* video_control (wxControl *); wxControl* still_control (wxControl *); - Film::Property _ignore_changes; + FilmState::Property _ignore_changes; /** The film we are editing */ Film* _film; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index e2ab1db5d..614dd794b 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -50,7 +50,7 @@ public: /** Handle a paint event */ void paint_event (wxPaintEvent& ev) { - if (!_film || _film->num_thumbs() == 0) { + if (!_film || _film->thumbs().size() == 0) { wxPaintDC dc (this); return; } @@ -143,12 +143,14 @@ private: int vw, vh; GetSize (&vw, &vh); + Crop const fc = _film->crop (); + /* Cropped rectangle */ Rect cropped_area ( - _film->crop().left, - _film->crop().top, - _image->GetWidth() - (_film->crop().left + _film->crop().right), - _image->GetHeight() - (_film->crop().top + _film->crop().bottom) + fc.left, + fc.top, + _image->GetWidth() - (fc.left + fc.right), + _image->GetHeight() - (fc.top + fc.bottom) ); /* Target ratio */ @@ -232,7 +234,7 @@ FilmViewer::FilmViewer (Film* f, wxWindow* p) _thumb_panel = new ThumbPanel (this, f); _sizer->Add (_thumb_panel, 1, wxEXPAND); - int const m = max (1, f ? f->num_thumbs() - 1 : 0); + int const m = max (1LU, f ? f->thumbs().size() - 1 : 0); _slider = new wxSlider (this, wxID_ANY, 0, 0, m); _sizer->Add (_slider, 0, wxEXPAND | wxLEFT | wxRIGHT); set_thumbnail (0); @@ -245,7 +247,7 @@ FilmViewer::FilmViewer (Film* f, wxWindow* p) void FilmViewer::set_thumbnail (int n) { - if (_film == 0 || _film->num_thumbs() <= n) { + if (_film == 0 || int (_film->thumbs().size()) <= n) { return; } @@ -259,12 +261,12 @@ FilmViewer::slider_changed (wxCommandEvent &) } void -FilmViewer::film_changed (Film::Property p) +FilmViewer::film_changed (FilmState::Property p) { switch (p) { - case Film::THUMBS: - if (_film && _film->num_thumbs() > 1) { - _slider->SetRange (0, _film->num_thumbs () - 1); + case FilmState::THUMBS: + if (_film && _film->thumbs().size() > 1) { + _slider->SetRange (0, _film->thumbs().size() - 1); } else { _thumb_panel->clear (); _slider->SetRange (0, 1); @@ -273,16 +275,16 @@ FilmViewer::film_changed (Film::Property p) _slider->SetValue (0); set_thumbnail (0); break; - case Film::CONTENT: + case FilmState::CONTENT: setup_visibility (); _film->examine_content (); update_thumbs (); break; - case Film::CROP: - case Film::FORMAT: - case Film::WITH_SUBTITLES: - case Film::SUBTITLE_OFFSET: - case Film::SUBTITLE_SCALE: + case FilmState::CROP: + case FilmState::FORMAT: + case FilmState::WITH_SUBTITLES: + case FilmState::SUBTITLE_OFFSET: + case FilmState::SUBTITLE_SCALE: _thumb_panel->recompose (); break; default: diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 58474c6ba..d2e597637 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -41,7 +41,7 @@ private: void slider_changed (wxCommandEvent &); void update_thumbs (); void set_thumbnail (int); - void film_changed (Film::Property); + void film_changed (FilmState::Property); Film* _film; wxBoxSizer* _sizer; diff --git a/test/test.cc b/test/test.cc index 730aa8d3e..7ca6d0cd3 100644 --- a/test/test.cc +++ b/test/test.cc @@ -258,13 +258,15 @@ BOOST_AUTO_TEST_CASE (md5_digest_test) BOOST_AUTO_TEST_CASE (paths_test) { FilmState s; - s.directory = "build/test/a/b/c/d/e"; - s.thumbs.push_back (42); + s.set_directory ("build/test/a/b/c/d/e"); + vector thumbs; + thumbs.push_back (42); + s.set_thumbs (thumbs); BOOST_CHECK_EQUAL (s.thumb_file (0), "build/test/a/b/c/d/e/thumbs/00000042.png"); - s.content = "/foo/bar/baz"; + s._content = "/foo/bar/baz"; BOOST_CHECK_EQUAL (s.content_path(), "/foo/bar/baz"); - s.content = "foo/bar/baz"; + s._content = "foo/bar/baz"; BOOST_CHECK_EQUAL (s.content_path(), "build/test/a/b/c/d/e/foo/bar/baz"); } @@ -401,23 +403,23 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test) BOOST_AUTO_TEST_CASE (audio_sampling_rate_test) { FilmState fs; - fs.frames_per_second = 24; + fs.set_frames_per_second (24); - fs.audio_sample_rate = 48000; + fs.set_audio_sample_rate (48000); BOOST_CHECK_EQUAL (fs.target_sample_rate(), 48000); - fs.audio_sample_rate = 44100; + fs.set_audio_sample_rate (44100); BOOST_CHECK_EQUAL (fs.target_sample_rate(), 48000); - fs.audio_sample_rate = 80000; + fs.set_audio_sample_rate (80000); BOOST_CHECK_EQUAL (fs.target_sample_rate(), 96000); - fs.frames_per_second = 23.976; - fs.audio_sample_rate = 48000; + fs.set_frames_per_second (23.976); + fs.set_audio_sample_rate (48000); BOOST_CHECK_EQUAL (fs.target_sample_rate(), 47952); - fs.frames_per_second = 29.97; - fs.audio_sample_rate = 48000; + fs.set_frames_per_second (29.97); + fs.set_audio_sample_rate (48000); BOOST_CHECK_EQUAL (fs.target_sample_rate(), 47952); } -- 2.30.2