Fix incorrect results when applying some timing operations to
authorCarl Hetherington <cth@carlh.net>
Fri, 28 Feb 2020 11:31:40 +0000 (12:31 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 28 Feb 2020 11:31:40 +0000 (12:31 +0100)
more than one piece of content at once (e.g. trim start).

src/wx/suspender.cc [new file with mode: 0644]
src/wx/suspender.h [new file with mode: 0644]
src/wx/timing_panel.cc
src/wx/timing_panel.h
src/wx/wscript

diff --git a/src/wx/suspender.cc b/src/wx/suspender.cc
new file mode 100644 (file)
index 0000000..9b1b64c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+    Copyright (C) 2020 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 "suspender.h"
+#include <boost/foreach.hpp>
+
+Suspender::Suspender(boost::function<void (int)> handler)
+       : _handler (handler)
+       , _count (0)
+{
+
+}
+
+Suspender::Block::Block (Suspender* s)
+       : _suspender (s)
+{
+       _suspender->increment ();
+}
+
+Suspender::Block::~Block ()
+{
+       _suspender->decrement ();
+}
+
+Suspender::Block
+Suspender::block ()
+{
+       return Block (this);
+}
+
+void
+Suspender::increment ()
+{
+       ++_count;
+}
+
+void
+Suspender::decrement ()
+{
+       --_count;
+       if (_count == 0) {
+               BOOST_FOREACH (int i, _pending) {
+                       _handler (i);
+               }
+               _pending.clear ();
+       }
+}
+
+bool
+Suspender::check (int property)
+{
+       if (_count == 0) {
+               return false;
+       }
+
+       _pending.insert (property);
+       return true;
+}
+
+
diff --git a/src/wx/suspender.h b/src/wx/suspender.h
new file mode 100644 (file)
index 0000000..3538951
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    Copyright (C) 2020 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 <boost/function.hpp>
+#include <set>
+
+class Suspender
+{
+public:
+       Suspender (boost::function<void (int)> handler);
+
+       bool check (int property);
+
+       class Block
+       {
+       public:
+               Block (Suspender* s);
+               ~Block ();
+       private:
+               Suspender* _suspender;
+       };
+
+       Block block ();
+
+private:
+       friend class Block;
+
+       void increment ();
+       void decrement ();
+
+       boost::function<void (int)> _handler;
+       int _count;
+       std::set<int> _pending;
+};
index 739cf25..184356a 100644 (file)
@@ -55,6 +55,7 @@ TimingPanel::TimingPanel (ContentPanel* p, weak_ptr<FilmViewer> viewer)
        /// TRANSLATORS: translate the word "Timing" here; do not include the "Timing|" prefix
        : ContentSubPanel (p, S_("Timing|Timing"))
        , _viewer (viewer)
+       , _film_content_changed_suspender (boost::bind(&TimingPanel::film_content_changed, this, _1))
 {
        wxSize size = TimecodeBase::size (this);
 
@@ -256,6 +257,10 @@ TimingPanel::update_play_length ()
 void
 TimingPanel::film_content_changed (int property)
 {
+       if (_film_content_changed_suspender.check(property)) {
+               return;
+       }
+
        int const film_video_frame_rate = _parent->film()->video_frame_rate ();
 
        /* Here we check to see if we have exactly one different value of various
@@ -405,7 +410,7 @@ TimingPanel::trim_start_changed ()
        optional<FrameRateChange> ref_frc;
        optional<DCPTime> ref_ph;
 
-
+       Suspender::Block bl = _film_content_changed_suspender.block ();
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
                if (i->position() <= ph && ph < i->end(_parent->film())) {
                        /* The playhead is in i.  Use it as a reference to work out
@@ -438,6 +443,7 @@ TimingPanel::trim_end_changed ()
 
        fv->set_coalesce_player_changes (true);
 
+       Suspender::Block bl = _film_content_changed_suspender.block ();
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
                ContentTime const trim = _trim_end->get (i->video_frame_rate().get_value_or(_parent->film()->video_frame_rate()));
                i->set_trim_end (trim);
@@ -455,6 +461,7 @@ void
 TimingPanel::play_length_changed ()
 {
        DCPTime const play_length = _play_length->get (_parent->film()->video_frame_rate());
+       Suspender::Block bl = _film_content_changed_suspender.block ();
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
                FrameRateChange const frc = _parent->film()->active_frame_rate_change (i->position ());
                i->set_trim_end (
@@ -491,6 +498,7 @@ TimingPanel::set_video_frame_rate ()
        if (_video_frame_rate->GetValue() != wxT("")) {
                fr = locale_convert<double> (wx_to_std (_video_frame_rate->GetValue ()));
        }
+       Suspender::Block bl = _film_content_changed_suspender.block ();
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
                if (fr) {
                        i->set_video_frame_rate (*fr);
index 962a7fe..e0be2d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -20,6 +20,7 @@
 
 #include "content_sub_panel.h"
 #include "timecode.h"
+#include "suspender.h"
 
 class FilmViewer;
 
@@ -72,4 +73,6 @@ private:
        wxStaticText* _video_frame_rate_label;
        wxTextCtrl* _video_frame_rate;
        wxButton* _set_video_frame_rate;
+
+       Suspender _film_content_changed_suspender;
 };
index 5dbf75e..2784070 100644 (file)
@@ -121,6 +121,7 @@ sources = """
           standard_controls.cc
           static_text.cc
           subtitle_appearance_dialog.cc
+          suspender.cc
           system_font_dialog.cc
           system_information_dialog.cc
           table_dialog.cc