From baf6bc63df6577d6efdc12ae605aa94754b73882 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 24 Oct 2012 20:01:57 +0100 Subject: [PATCH] Make Film state thread-safe. --- src/lib/film.cc | 279 ++++++++++++++++++++++++++++++++++++------------ src/lib/film.h | 43 +++++++- 2 files changed, 251 insertions(+), 71 deletions(-) diff --git a/src/lib/film.cc b/src/lib/film.cc index b76f9df71..8afa1e245 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -425,9 +425,11 @@ Film::thumb_subtitle (int n) const void Film::write_metadata () const { + boost::mutex::scoped_lock lm (_state_mutex); + filesystem::create_directories (directory()); - string const m = file ("metadata"); + string const m = file_locked ("metadata"); ofstream f (m.c_str ()); if (!f.good ()) { throw CreateFileError (m); @@ -510,7 +512,9 @@ Film::write_metadata () const void Film::read_metadata () { - ifstream f (file("metadata").c_str()); + boost::mutex::scoped_lock lm (_state_mutex); + + ifstream f (file_locked("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; @@ -658,6 +662,7 @@ Film::thumb_base_for_frame (int n) const int Film::thumb_frame (int n) const { + boost::mutex::scoped_lock lm (_state_mutex); assert (n < int (_thumbs.size ())); return _thumbs[n]; } @@ -665,6 +670,7 @@ Film::thumb_frame (int n) const Size Film::cropped_size (Size s) const { + boost::mutex::scoped_lock lm (_state_mutex); s.width -= _crop.left + _crop.right; s.height -= _crop.top + _crop.bottom; return s; @@ -676,6 +682,7 @@ Film::cropped_size (Size s) const string Film::dir (string d) const { + boost::mutex::scoped_lock lm (_state_mutex); filesystem::path p; p /= _directory; p /= d; @@ -686,6 +693,13 @@ Film::dir (string d) const /** Given a file or directory name, return its full path within the Film's directory */ string Film::file (string f) const +{ + boost::mutex::scoped_lock lm (_state_mutex); + return file_locked (f); +} + +string +Film::file_locked (string f) const { filesystem::path p; p /= _directory; @@ -699,11 +713,12 @@ Film::file (string f) const string Film::content_path () const { + boost::mutex::scoped_lock lm (_state_mutex); if (filesystem::path(_content).has_root_directory ()) { return _content; } - return file (_content); + return file_locked (_content); } ContentType @@ -729,13 +744,13 @@ int Film::target_audio_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); @@ -744,17 +759,19 @@ Film::target_audio_sample_rate () const int Film::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 */ string Film::dci_name () const { + boost::mutex::scoped_lock lm (_state_mutex); + stringstream d; string fixed_name = to_upper_copy (_name); @@ -837,17 +854,18 @@ Film::dci_name () const string Film::dcp_name () const { - if (_use_dci_name) { + if (use_dci_name()) { return dci_name (); } - return _name; + return name(); } void Film::set_directory (string d) { + boost::mutex::scoped_lock lm (_state_mutex); _directory = d; _dirty = true; } @@ -855,21 +873,27 @@ Film::set_directory (string d) void Film::set_name (string n) { - _name = n; + { + boost::mutex::scoped_lock lm (_state_mutex); + _name = n; + } signal_changed (NAME); } void Film::set_use_dci_name (bool u) { - _use_dci_name = u; + { + boost::mutex::scoped_lock lm (_state_mutex); + _use_dci_name = u; + } signal_changed (USE_DCI_NAME); } void Film::set_content (string c) { - string check = _directory; + string check = directory (); #if BOOST_FILESYSTEM_VERSION == 3 filesystem::path slash ("/"); @@ -890,15 +914,19 @@ Film::set_content (string c) c = c.substr (_directory.length() + 1); } - if (c == _content) { - return; - } + { + boost::mutex::scoped_lock lm (_state_mutex); + if (c == _content) { + return; + } + _content = c; + } + /* Create a temporary decoder so that we can get information about the content. */ - - _content = c; + shared_ptr o (new Options ("", "", "")); o->out_size = Size (1024, 1024); @@ -922,284 +950,397 @@ Film::set_content (string c) void Film::set_dcp_content_type (DCPContentType const * t) { - _dcp_content_type = t; + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_content_type = t; + } signal_changed (DCP_CONTENT_TYPE); } void Film::set_format (Format const * f) { - _format = f; + { + boost::mutex::scoped_lock lm (_state_mutex); + _format = f; + } signal_changed (FORMAT); } void Film::set_crop (Crop c) { - _crop = c; + { + boost::mutex::scoped_lock lm (_state_mutex); + _crop = c; + } signal_changed (CROP); } void Film::set_left_crop (int c) { - if (_crop.left == c) { - return; + { + boost::mutex::scoped_lock lm (_state_mutex); + + if (_crop.left == c) { + return; + } + + _crop.left = c; } - - _crop.left = c; signal_changed (CROP); } void Film::set_right_crop (int c) { - if (_crop.right == c) { - return; + { + boost::mutex::scoped_lock lm (_state_mutex); + if (_crop.right == c) { + return; + } + + _crop.right = c; } - - _crop.right = c; signal_changed (CROP); } void Film::set_top_crop (int c) { - if (_crop.top == c) { - return; + { + boost::mutex::scoped_lock lm (_state_mutex); + if (_crop.top == c) { + return; + } + + _crop.top = c; } - - _crop.top = c; signal_changed (CROP); } void Film::set_bottom_crop (int c) { - if (_crop.bottom == c) { - return; + { + boost::mutex::scoped_lock lm (_state_mutex); + if (_crop.bottom == c) { + return; + } + + _crop.bottom = c; } - - _crop.bottom = c; signal_changed (CROP); } void Film::set_filters (vector f) { - _filters = f; + { + boost::mutex::scoped_lock lm (_state_mutex); + _filters = f; + } signal_changed (FILTERS); } void Film::set_scaler (Scaler const * s) { - _scaler = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _scaler = s; + } signal_changed (SCALER); } void Film::set_dcp_frames (int f) { - _dcp_frames = f; + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_frames = f; + } signal_changed (DCP_FRAMES); } void Film::set_dcp_trim_action (TrimAction a) { - _dcp_trim_action = a; + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_trim_action = a; + } signal_changed (DCP_TRIM_ACTION); } void Film::set_dcp_ab (bool a) { - _dcp_ab = a; + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_ab = a; + } signal_changed (DCP_AB); } void Film::set_audio_stream (int s) { - _audio_stream = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_stream = s; + } signal_changed (AUDIO_STREAM); } void Film::set_audio_gain (float g) { - _audio_gain = g; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_gain = g; + } signal_changed (AUDIO_GAIN); } void Film::set_audio_delay (int d) { - _audio_delay = d; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_delay = d; + } signal_changed (AUDIO_DELAY); } void Film::set_still_duration (int d) { - _still_duration = d; + { + boost::mutex::scoped_lock lm (_state_mutex); + _still_duration = d; + } signal_changed (STILL_DURATION); } void Film::set_subtitle_stream (int s) { - _subtitle_stream = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _subtitle_stream = s; + } signal_changed (SUBTITLE_STREAM); } void Film::set_with_subtitles (bool w) { - _with_subtitles = w; + { + boost::mutex::scoped_lock lm (_state_mutex); + _with_subtitles = w; + } signal_changed (WITH_SUBTITLES); } void Film::set_subtitle_offset (int o) { - _subtitle_offset = o; + { + boost::mutex::scoped_lock lm (_state_mutex); + _subtitle_offset = o; + } signal_changed (SUBTITLE_OFFSET); } void Film::set_subtitle_scale (float s) { - _subtitle_scale = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _subtitle_scale = s; + } signal_changed (SUBTITLE_SCALE); } void Film::set_audio_language (string l) { - _audio_language = l; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_language = l; + } signal_changed (DCI_METADATA); } void Film::set_subtitle_language (string l) { - _subtitle_language = l; + { + boost::mutex::scoped_lock lm (_state_mutex); + _subtitle_language = l; + } signal_changed (DCI_METADATA); } void Film::set_territory (string t) { - _territory = t; + { + boost::mutex::scoped_lock lm (_state_mutex); + _territory = t; + } signal_changed (DCI_METADATA); } void Film::set_rating (string r) { - _rating = r; + { + boost::mutex::scoped_lock lm (_state_mutex); + _rating = r; + } signal_changed (DCI_METADATA); } void Film::set_studio (string s) { - _studio = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _studio = s; + } signal_changed (DCI_METADATA); } void Film::set_facility (string f) { - _facility = f; + { + boost::mutex::scoped_lock lm (_state_mutex); + _facility = f; + } signal_changed (DCI_METADATA); } void Film::set_package_type (string p) { - _package_type = p; + { + boost::mutex::scoped_lock lm (_state_mutex); + _package_type = p; + } signal_changed (DCI_METADATA); } void Film::set_thumbs (vector t) { - _thumbs = t; + { + boost::mutex::scoped_lock lm (_state_mutex); + _thumbs = t; + } signal_changed (THUMBS); } void Film::set_size (Size s) { - _size = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _size = s; + } signal_changed (SIZE); } void Film::set_length (int l) { - _length = l; + { + boost::mutex::scoped_lock lm (_state_mutex); + _length = l; + } signal_changed (LENGTH); } void Film::set_audio_sample_rate (int r) { - _audio_sample_rate = r; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_sample_rate = r; + } signal_changed (AUDIO_SAMPLE_RATE); } void Film::set_content_digest (string d) { - _content_digest = d; + { + boost::mutex::scoped_lock lm (_state_mutex); + _content_digest = d; + } _dirty = true; } void Film::set_has_subtitles (bool s) { - _has_subtitles = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _has_subtitles = s; + } signal_changed (HAS_SUBTITLES); } void Film::set_audio_streams (vector s) { - _audio_streams = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _audio_streams = s; + } _dirty = true; } void Film::set_subtitle_streams (vector s) { - _subtitle_streams = s; + { + boost::mutex::scoped_lock lm (_state_mutex); + _subtitle_streams = s; + } _dirty = true; } void Film::set_frames_per_second (float f) { - _frames_per_second = f; + { + boost::mutex::scoped_lock lm (_state_mutex); + _frames_per_second = f; + } signal_changed (FRAMES_PER_SECOND); } void Film::signal_changed (Property p) { - _dirty = true; + { + boost::mutex::scoped_lock lm (_state_mutex); + _dirty = true; + } ui_signaller->emit (boost::bind (boost::ref (Changed), p)); } int Film::audio_channels () const { + boost::mutex::scoped_lock lm (_state_mutex); if (_audio_stream == -1) { return 0; } - + return _audio_streams[_audio_stream].channels (); } diff --git a/src/lib/film.h b/src/lib/film.h index 795be29d6..bf5fb936d 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -81,8 +81,6 @@ public: std::string file (std::string f) const; std::string dir (std::string d) const; - - std::string content_path () const; ContentType content_type () const; @@ -144,156 +142,194 @@ public: /* GET */ std::string directory () const { + boost::mutex::scoped_lock lm (_state_mutex); return _directory; } std::string name () const { + boost::mutex::scoped_lock lm (_state_mutex); return _name; } bool use_dci_name () const { + boost::mutex::scoped_lock lm (_state_mutex); return _use_dci_name; } std::string content () const { + boost::mutex::scoped_lock lm (_state_mutex); return _content; } DCPContentType const * dcp_content_type () const { + boost::mutex::scoped_lock lm (_state_mutex); return _dcp_content_type; } Format const * format () const { + boost::mutex::scoped_lock lm (_state_mutex); return _format; } Crop crop () const { + boost::mutex::scoped_lock lm (_state_mutex); return _crop; } std::vector filters () const { + boost::mutex::scoped_lock lm (_state_mutex); return _filters; } Scaler const * scaler () const { + boost::mutex::scoped_lock lm (_state_mutex); return _scaler; } int dcp_frames () const { + boost::mutex::scoped_lock lm (_state_mutex); return _dcp_frames; } TrimAction dcp_trim_action () const { + boost::mutex::scoped_lock lm (_state_mutex); return _dcp_trim_action; } bool dcp_ab () const { + boost::mutex::scoped_lock lm (_state_mutex); return _dcp_ab; } int audio_stream_index () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_stream; } AudioStream audio_stream () const { + boost::mutex::scoped_lock lm (_state_mutex); assert (_audio_stream < int (_audio_streams.size())); return _audio_streams[_audio_stream]; } float audio_gain () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_gain; } int audio_delay () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_delay; } int still_duration () const { + boost::mutex::scoped_lock lm (_state_mutex); return _still_duration; } int subtitle_stream_index () const { + boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_stream; } SubtitleStream subtitle_stream () const { + boost::mutex::scoped_lock lm (_state_mutex); assert (_subtitle_stream < int (_subtitle_streams.size())); return _subtitle_streams[_subtitle_stream]; } bool with_subtitles () const { + boost::mutex::scoped_lock lm (_state_mutex); return _with_subtitles; } int subtitle_offset () const { + boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_offset; } float subtitle_scale () const { + boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_scale; } std::string audio_language () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_language; } std::string subtitle_language () const { + boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_language; } std::string territory () const { + boost::mutex::scoped_lock lm (_state_mutex); return _territory; } std::string rating () const { + boost::mutex::scoped_lock lm (_state_mutex); return _rating; } std::string studio () const { + boost::mutex::scoped_lock lm (_state_mutex); return _studio; } std::string facility () const { + boost::mutex::scoped_lock lm (_state_mutex); return _facility; } std::string package_type () const { + boost::mutex::scoped_lock lm (_state_mutex); return _package_type; } std::vector thumbs () const { + boost::mutex::scoped_lock lm (_state_mutex); return _thumbs; } Size size () const { + boost::mutex::scoped_lock lm (_state_mutex); return _size; } int length () const { + boost::mutex::scoped_lock lm (_state_mutex); return _length; } int audio_sample_rate () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_sample_rate; } std::string content_digest () const { + boost::mutex::scoped_lock lm (_state_mutex); return _content_digest; } bool has_subtitles () const { + boost::mutex::scoped_lock lm (_state_mutex); return _has_subtitles; } std::vector audio_streams () const { + boost::mutex::scoped_lock lm (_state_mutex); return _audio_streams; } std::vector subtitle_streams () const { + boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_streams; } float frames_per_second () const { + boost::mutex::scoped_lock lm (_state_mutex); return _frames_per_second; } @@ -355,6 +391,7 @@ private: std::string thumb_file_for_frame (int) const; std::string thumb_base_for_frame (int) const; void signal_changed (Property); + std::string file_locked (std::string) const; /** Complete path to directory containing the film metadata; * must not be relative. @@ -438,6 +475,8 @@ private: mutable bool _dirty; + mutable boost::mutex _state_mutex; + friend class paths_test; }; -- 2.30.2