diff options
| author | Carl Hetherington <cth@carlh.net> | 2023-05-09 01:33:45 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2023-05-10 16:06:35 +0200 |
| commit | 9fc01974fec9a61fd1239f7c05af143843b2ca1c (patch) | |
| tree | 0658709065f1eaaff0e6c199113ce61d58453522 | |
| parent | b168d211622f94a5240c945c1df03b0bed48d3bc (diff) | |
Allow signals to be blocked and resumed, and so make sure that a set
of content changes taken from an examiner are handled at the same
time.
Should fix DoM #2523.
| -rw-r--r-- | src/lib/change_signaller.cc | 24 | ||||
| -rw-r--r-- | src/lib/change_signaller.h | 102 | ||||
| -rw-r--r-- | src/lib/content.cc | 1 | ||||
| -rw-r--r-- | src/lib/content.h | 3 | ||||
| -rw-r--r-- | src/lib/dcp_content.cc | 8 | ||||
| -rw-r--r-- | src/lib/film.h | 2 | ||||
| -rw-r--r-- | src/lib/wscript | 1 |
7 files changed, 126 insertions, 15 deletions
diff --git a/src/lib/change_signaller.cc b/src/lib/change_signaller.cc new file mode 100644 index 000000000..a1f093d14 --- /dev/null +++ b/src/lib/change_signaller.cc @@ -0,0 +1,24 @@ +/* + Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "change_signaller.h" + + diff --git a/src/lib/change_signaller.h b/src/lib/change_signaller.h index 8612cf426..1d7d482df 100644 --- a/src/lib/change_signaller.h +++ b/src/lib/change_signaller.h @@ -23,6 +23,10 @@ #define DCPOMATIC_CHANGE_SIGNALLER_H +#include <boost/thread.hpp> +#include <vector> + + enum class ChangeType { PENDING, @@ -32,29 +36,103 @@ enum class ChangeType template <class T, class P> +class ChangeSignal +{ +public: + ChangeSignal(T* thing_, P property_, ChangeType type_) + : thing(thing_) + , property(property_) + , type(type_) + {} + + T* thing; + P property; + ChangeType type; +}; + + +class ChangeSignalDespatcherBase +{ +protected: + static boost::mutex _instance_mutex; +}; + + +template <class T, class P> +class ChangeSignalDespatcher : public ChangeSignalDespatcherBase +{ +public: + ChangeSignalDespatcher() = default; + + ChangeSignalDespatcher(ChangeSignalDespatcher const&) = delete; + ChangeSignalDespatcher& operator=(ChangeSignalDespatcher const&) = delete; + + void signal_change(ChangeSignal<T, P> const& signal) + { + if (_suspended) { + boost::mutex::scoped_lock lm(_mutex); + _pending.push_back(signal); + } else { + signal.thing->signal_change(signal.type, signal.property); + } + } + + void suspend() + { + boost::mutex::scoped_lock lm(_mutex); + _suspended = true; + } + + void resume() + { + boost::mutex::scoped_lock lm(_mutex); + auto pending = _pending; + lm.unlock(); + + for (auto signal: pending) { + signal.thing->signal_change(signal.type, signal.property); + } + + lm.lock(); + _pending.clear(); + _suspended = false; + } + + static ChangeSignalDespatcher* instance() + { + static boost::mutex _instance_mutex; + static boost::mutex::scoped_lock lm(_instance_mutex); + static ChangeSignalDespatcher<T, P>* _instance; + if (!_instance) { + _instance = new ChangeSignalDespatcher<T, P>(); + } + return _instance; + } + +private: + std::vector<ChangeSignal<T, P>> _pending; + bool _suspended = false; + boost::mutex _mutex; +}; + + +template <class T, class P> class ChangeSignaller { public: ChangeSignaller (T* t, P p) - : _thing (t) - , _property (p) - , _done (true) + : _thing(t) + , _property(p) + , _done(true) { - _thing->signal_change (ChangeType::PENDING, _property); + ChangeSignalDespatcher<T, P>::instance()->signal_change({_thing, _property, ChangeType::PENDING}); } ~ChangeSignaller () { - if (_done) { - _thing->signal_change (ChangeType::DONE, _property); - } else { - _thing->signal_change (ChangeType::CANCELLED, _property); - } + ChangeSignalDespatcher<T, P>::instance()->signal_change({_thing, _property, _done ? ChangeType::DONE : ChangeType::CANCELLED}); } - ChangeSignaller (ChangeSignaller const&) = delete; - ChangeSignaller& operator= (ChangeSignaller const&) = delete; - void abort () { _done = false; diff --git a/src/lib/content.cc b/src/lib/content.cc index e77a3638c..9b5baa59f 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -257,6 +257,7 @@ Content::set_trim_start(shared_ptr<const Film> film, ContentTime t) audio->modify_trim_start(film, t); } + std::cout << "TRIM_START from set_trim_start\n"; ContentChangeSignaller cc (this, ContentProperty::TRIM_START); { diff --git a/src/lib/content.h b/src/lib/content.h index 0ce87ed9b..f2fecddf0 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -234,7 +234,7 @@ private: friend struct best_dcp_frame_rate_test_double; friend struct audio_sampling_rate_test; friend struct subtitle_font_id_change_test2; - template<class, class> friend class ChangeSignaller; + template<class, class> friend class ChangeSignalDespatcher; void signal_change (ChangeType, int); @@ -256,6 +256,7 @@ private: typedef ChangeSignaller<Content, int> ContentChangeSignaller; +typedef ChangeSignalDespatcher<Content, int> ContentChangeSignalDespatcher; #endif diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index 231a93bd0..cad775b24 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2022 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2023 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -31,6 +31,7 @@ #include "job.h" #include "log.h" #include "overlaps.h" +#include "scope_guard.h" #include "text_content.h" #include "video_content.h" #include <dcp/dcp.h> @@ -213,6 +214,11 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job) bool const needed_kdm = needs_kdm (); string const old_name = name (); + ContentChangeSignalDespatcher::instance()->suspend(); + ScopeGuard sg = []() { + ContentChangeSignalDespatcher::instance()->resume(); + }; + ContentChangeSignaller cc_texts (this, DCPContentProperty::TEXTS); ContentChangeSignaller cc_assets (this, DCPContentProperty::NEEDS_ASSETS); ContentChangeSignaller cc_kdm (this, DCPContentProperty::NEEDS_KDM); diff --git a/src/lib/film.h b/src/lib/film.h index b7a9f94ac..958c388b3 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -492,7 +492,7 @@ private: friend struct ::isdcf_name_with_atmos; friend struct ::recover_test_2d_encrypted; friend struct ::atmos_encrypted_passthrough_test; - template <class, class> friend class ChangeSignaller; + template <class, class> friend class ChangeSignalDespatcher; boost::filesystem::path info_file (dcpomatic::DCPTimePeriod p) const; diff --git a/src/lib/wscript b/src/lib/wscript index f8c2d5dc2..de7b947c2 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -51,6 +51,7 @@ sources = """ check_content_job.cc cinema.cc cinema_sound_processor.cc + change_signaller.cc collator.cc colour_conversion.cc config.cc |
