(1) remove most uses of MementoCommand for Playlist and Region (2) move frozen state...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 2 Mar 2010 18:05:26 +0000 (18:05 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 2 Mar 2010 18:05:26 +0000 (18:05 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6720 d708f5d6-7413-0410-9779-e7cbd77b26cf

35 files changed:
gtk2_ardour/audio_region_editor.cc
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_streamview.cc
gtk2_ardour/midi_time_axis.cc
gtk2_ardour/region_gain_line.cc
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/automation_list.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/region.h
libs/ardour/ardour/session.h
libs/ardour/ardour/track.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_track.cc
libs/ardour/audioregion.cc
libs/ardour/automation_list.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_track.cc
libs/ardour/playlist.cc
libs/ardour/region.cc
libs/ardour/region_factory.cc
libs/ardour/session.cc
libs/evoral/evoral/ControlList.hpp
libs/pbd/pbd/properties.h
libs/pbd/pbd/stateful.h
libs/pbd/stateful.cc
libs/surfaces/osc/osc_controllable.cc
libs/surfaces/osc/osc_controllable.h

index e246c04391327a346a1682588bf12ff210c05a8c..adbb1e04ea65038837232d65e9333a092466f5c0 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/session.h"
 #include "ardour/audioregion.h"
@@ -256,10 +257,9 @@ AudioRegionEditor::position_clock_changed ()
        boost::shared_ptr<Playlist> pl = _region->playlist();
 
        if (pl) {
-               XMLNode &before = pl->get_state();
+               _region->clear_history ();
                _region->set_position (position_clock.current_time(), this);
-               XMLNode &after = pl->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
+               _session->add_command(new StatefulDiffCommand (_region));
        }
 
        _session->commit_reversible_command ();
@@ -273,10 +273,9 @@ AudioRegionEditor::end_clock_changed ()
        boost::shared_ptr<Playlist> pl = _region->playlist();
 
        if (pl) {
-               XMLNode &before = pl->get_state();
+                _region->clear_history ();
                _region->trim_end (end_clock.current_time(), this);
-               XMLNode &after = pl->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
+               _session->add_command(new StatefulDiffCommand (_region));
        }
 
        _session->commit_reversible_command ();
@@ -294,10 +293,9 @@ AudioRegionEditor::length_clock_changed ()
        boost::shared_ptr<Playlist> pl = _region->playlist();
 
        if (pl) {
-               XMLNode &before = pl->get_state();
+                _region->clear_history ();
                _region->trim_end (_region->position() + frames - 1, this);
-               XMLNode &after = pl->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
+               _session->add_command(new StatefulDiffCommand (_region));
        }
 
        _session->commit_reversible_command ();
@@ -404,10 +402,9 @@ AudioRegionEditor::sync_offset_absolute_clock_changed ()
 {
        _session->begin_reversible_command (_("change region sync point"));
 
-       XMLNode& before = _region->get_state ();
+        _region->clear_history ();
        _region->set_sync_position (sync_offset_absolute_clock.current_time());
-       XMLNode& after = _region->get_state ();
-       _session->add_command (new MementoCommand<AudioRegion> (*_region.get(), &before, &after));
+       _session->add_command (new StatefulDiffCommand (_region));
        
        _session->commit_reversible_command ();
 }
@@ -417,10 +414,9 @@ AudioRegionEditor::sync_offset_relative_clock_changed ()
 {
        _session->begin_reversible_command (_("change region sync point"));
 
-       XMLNode& before = _region->get_state ();
+        _region->clear_history ();
        _region->set_sync_position (sync_offset_relative_clock.current_time() + _region->position ());
-       XMLNode& after = _region->get_state ();
-       _session->add_command (new MementoCommand<AudioRegion> (*_region.get(), &before, &after));
+       _session->add_command (new StatefulDiffCommand (_region));
        
        _session->commit_reversible_command ();
 }
index 438867c9dcdce41373530a3290be59954161e490..7a0e76606ef9d14a3cfa8fb4014112adaac78091 100644 (file)
@@ -267,8 +267,8 @@ AudioRegionView::audio_region() const
 void
 AudioRegionView::region_changed (const PropertyChange& what_changed)
 {
-       ENSURE_GUI_THREAD (*this, &AudioRegionView::region_changed, what_changed)
-       //cerr << "AudioRegionView::region_changed() called" << endl;
+       ENSURE_GUI_THREAD (*this, &AudioRegionView::region_changed, what_changed);
+        // cerr << "AudioRegionView::region_changed() called" << endl;
 
        RegionView::region_changed (what_changed);
 
@@ -276,7 +276,7 @@ AudioRegionView::region_changed (const PropertyChange& what_changed)
                region_scale_amplitude_changed ();
        }
        if (what_changed.contains (ARDOUR::Properties::fade_in)) {
-                       fade_in_changed ();
+                fade_in_changed ();
        }
        if (what_changed.contains (ARDOUR::Properties::fade_out)) {
                fade_out_changed ();
@@ -1022,6 +1022,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
 
        gain_line->view_to_model_coord (x, y);
 
+        /* XXX STATEFUL: can't convert to stateful diff until we 
+           can represent automation data with it.
+        */
+
        trackview.session()->begin_reversible_command (_("add gain control point"));
        XMLNode &before = audio_region()->envelope()->get_state();
 
index 640120516cd61a5e67cf3d76b2d3a65fef8206ef..ac95bf63c2cda15b30948568e9653619b02791c9 100644 (file)
@@ -660,10 +660,10 @@ AudioStreamView::update_rec_regions ()
 
                                        if (nlen != region->length()) {
 
-                                               region->freeze ();
+                                               region->suspend_property_changes ();
                                                region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
                                                region->set_length (nlen, this);
-                                               region->thaw ();
+                                               region->resume_property_changes ();
 
                                                if (origlen == 1) {
                                                        /* our special initial length */
@@ -685,10 +685,10 @@ AudioStreamView::update_rec_regions ()
 
                                        if (region->source_length(0) >= region->start() + nlen) {
 
-                                               region->freeze ();
+                                               region->suspend_property_changes ();
                                                region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
                                                region->set_length (nlen, this);
-                                               region->thaw ();
+                                               region->resume_property_changes ();
 
                                                if (origlen == 1) {
                                                        /* our special initial length */
index 05056f3829637a09349452d60fd62940ae10737b..201659d7b4246ca5df18ec3097224917d8b78d05 100644 (file)
@@ -29,6 +29,7 @@
 #include "pbd/pthread_utils.h"
 #include "pbd/basename.h"
 #include "pbd/shortpath.h"
+#include "pbd/stateful_diff_command.h"
 
 #include <gtkmm2ext/choice.h>
 
@@ -840,9 +841,9 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                boost::shared_ptr<Playlist> playlist = existing_track->diskstream()->playlist();
                boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
                begin_reversible_command (_("insert file"));
-               XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->add_region (copy, pos);
-               _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+               _session->add_command (new StatefulDiffCommand (playlist));
                commit_reversible_command ();
                break;
        }
index 2922ad19bba4cb52511f18fbdce0bdeec306c6fa..cd6e5148f63d55d9f61586e89228fe141af3da21 100644 (file)
@@ -1425,9 +1425,9 @@ RegionInsertDrag::finished (GdkEvent* /*event*/, bool /*movement_occurred*/)
        boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
 
        _editor->begin_reversible_command (_("insert region"));
-       XMLNode& before = playlist->get_state ();
+        playlist->clear_history ();
        playlist->add_region (_primary->region (), _last_frame_position);
-       _editor->session()->add_command (new MementoCommand<Playlist> (*playlist, &before, &playlist->get_state()));
+       _editor->session()->add_command (new StatefulDiffCommand (playlist));
        _editor->commit_reversible_command ();
 
        delete _primary;
@@ -1772,7 +1772,8 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
 
                for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
                        (*i)->fake_set_opaque(false);
-                       (*i)->region()->freeze ();
+                        (*i)->region()->clear_history ();
+                       (*i)->region()->suspend_property_changes ();
 
                        AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
 
@@ -1784,7 +1785,6 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
                        insert_result = _editor->motion_frozen_playlists.insert (pl);
 
                        if (insert_result.second) {
-                               _editor->session()->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
                                pl->freeze();
                        }
                }
@@ -1867,13 +1867,13 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
                        for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
                                _editor->thaw_region_after_trim (**i);
                                (*i)->fake_set_opaque (true);
+                                if (_have_transaction) {
+                                        _editor->session()->add_command (new StatefulDiffCommand ((*i)->region()));
+                                }
                        }
                }
                for (set<boost::shared_ptr<Playlist> >::iterator p = _editor->motion_frozen_playlists.begin(); p != _editor->motion_frozen_playlists.end(); ++p) {
                        (*p)->thaw ();
-                       if (_have_transaction) {
-                               _editor->session()->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
-                       }
                }
 
                _editor->motion_frozen_playlists.clear ();
index ea40b43f50efd60ab79ef80bc00430537a2b42ad..e6936232cddcfa9d998dd8a216d335ee55888edc 100644 (file)
 
 */
 
+#include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
+
 #include "ardour/audioregion.h"
 #include "ardour/playlist.h"
 #include "ardour/session.h"
 #include "ardour/location.h"
 
-#include "pbd/memento_command.h"
-
 #include "editor.h"
 #include "region_view.h"
 #include "selection.h"
@@ -33,6 +34,7 @@
 #include "i18n.h"
 
 using namespace ARDOUR;
+using namespace PBD;
 
 void
 Editor::kbd_driver (sigc::slot<void,GdkEvent*> theslot, bool use_track_canvas, bool use_time_canvas, bool can_select)
@@ -89,11 +91,9 @@ Editor::kbd_mute_unmute_region ()
 
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
-                       XMLNode &before = (*i)->region()->playlist()->get_state ();
+                       (*i)->region()->playlist()->clear_history ();
                        (*i)->region()->set_muted (!(*i)->region()->muted ());
-                       XMLNode &after = (*i)->region()->playlist()->get_state ();
-
-                       _session->add_command (new MementoCommand<ARDOUR::Playlist>(*((*i)->region()->playlist()), &before, &after));
+                       _session->add_command (new StatefulDiffCommand ((*i)->region()->playlist()));
 
                }
 
@@ -102,12 +102,9 @@ Editor::kbd_mute_unmute_region ()
        } else if (entered_regionview) {
 
                begin_reversible_command (_("mute region"));
-               XMLNode &before = entered_regionview->region()->playlist()->get_state();
-
+                entered_regionview->region()->playlist()->clear_history ();
                entered_regionview->region()->set_muted (!entered_regionview->region()->muted());
-
-               XMLNode &after = entered_regionview->region()->playlist()->get_state();
-               _session->add_command (new MementoCommand<ARDOUR::Playlist>(*(entered_regionview->region()->playlist()), &before, &after));
+               _session->add_command (new StatefulDiffCommand (entered_regionview->region()->playlist()));
                commit_reversible_command();
 
        }
index 5820218a2a59a8a451b8fac1682dd2919d31b571..ee28ff68047a7f4061d485e4df72576b47604064 100644 (file)
@@ -31,6 +31,7 @@
 #include <gtkmm2ext/tearoff.h>
 #include "pbd/memento_command.h"
 #include "pbd/basename.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour_ui.h"
 #include "actions.h"
@@ -2287,23 +2288,17 @@ Editor::point_trim (GdkEvent* event, nframes64_t new_bound)
                                }
 
                                if (!(*i)->region()->locked()) {
-                                       boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
-                                       XMLNode &before = pl->get_state();
-
+                                       (*i)->region()->clear_history ();
                                        (*i)->region()->trim_front (new_bound, this);
-
-                                       XMLNode &after = pl->get_state();
-                                       _session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
+                                       _session->add_command(new StatefulDiffCommand ((*i)->region()));
                                }
                        }
 
                } else {
                        if (!rv->region()->locked()) {
-                               boost::shared_ptr<Playlist> pl = rv->region()->playlist();
-                               XMLNode &before = pl->get_state();
+                               rv->region()->clear_history ();
                                rv->region()->trim_front (new_bound, this);
-                               XMLNode &after = pl->get_state();
-                               _session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
+                               _session->add_command(new StatefulDiffCommand (rv->region()));
                        }
                }
 
@@ -2318,22 +2313,18 @@ Editor::point_trim (GdkEvent* event, nframes64_t new_bound)
                        for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
                        {
                                if (!(*i)->region()->locked()) {
-                                       boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
-                                       XMLNode &before = pl->get_state();
+                                       (*i)->region()->clear_history();
                                        (*i)->region()->trim_end (new_bound, this);
-                                       XMLNode &after = pl->get_state();
-                                       _session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
+                                       _session->add_command(new StatefulDiffCommand ((*i)->region()));
                                }
                        }
 
                } else {
 
                        if (!rv->region()->locked()) {
-                               boost::shared_ptr<Playlist> pl = rv->region()->playlist();
-                               XMLNode &before = pl->get_state();
+                               rv->region()->clear_history ();
                                rv->region()->trim_end (new_bound, this);
-                               XMLNode &after = pl->get_state();
-                               _session->add_command (new MementoCommand<Playlist>(*pl.get(), &before, &after));
+                               _session->add_command (new StatefulDiffCommand (rv->region()));
                        }
                }
 
@@ -2354,7 +2345,7 @@ Editor::thaw_region_after_trim (RegionView& rv)
                return;
        }
 
-       region->thaw ();
+       region->resume_property_changes ();
 
        AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
 
@@ -2453,11 +2444,10 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes64_t pos)
        boost::shared_ptr<Playlist> playlist = rtv->playlist();
        double speed = rtv->get_diskstream()->speed();
 
-       XMLNode &before = playlist->get_state();
+        playlist->clear_history ();
        boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
-       playlist->add_region (new_region, (nframes64_t) (pos * speed));
-       XMLNode &after = playlist->get_state();
-       _session->add_command(new MementoCommand<Playlist>(*playlist.get(), &before, &after));
+        playlist->add_region (new_region, (nframes64_t) (pos * speed));
+       _session->add_command (new StatefulDiffCommand (playlist));
 
        // playlist is frozen, so we have to update manually XXX this is disgusting
 
@@ -2560,10 +2550,9 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
 
        boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
 
-       XMLNode *before = &(playlist->get_state());
+        playlist->clear_history ();
        clicked_routeview->playlist()->add_region (region, selection->time[clicked_selection].start);
-       XMLNode *after = &(playlist->get_state());
-       _session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
+       _session->add_command(new StatefulDiffCommand (playlist));
 
        commit_reversible_command ();
 
index c3800b21fbd64d56b273c5b975dbb61da880ea40..6eaf1fb41af88e7b8deb0a49f043b06f78c5a8fc 100644 (file)
@@ -323,10 +323,9 @@ Editor::nudge_forward (bool next, bool force_playhead)
                                distance = next_distance;
                        }
 
-                        XMLNode &before = r->playlist()->get_state();
+                        r->clear_history ();
                        r->set_position (r->position() + distance, this);
-                        XMLNode &after = r->playlist()->get_state();
-                       _session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+                       _session->add_command (new StatefulDiffCommand (r));
                }
 
                commit_reversible_command ();
@@ -403,16 +402,15 @@ Editor::nudge_backward (bool next, bool force_playhead)
                        if (next) {
                                distance = next_distance;
                        }
-
-                        XMLNode &before = r->playlist()->get_state();
+                        
+                        r->clear_history ();
 
                        if (r->position() > distance) {
                                r->set_position (r->position() - distance, this);
                        } else {
                                r->set_position (0, this);
                        }
-                        XMLNode &after = r->playlist()->get_state();
-                       _session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+                       _session->add_command (new StatefulDiffCommand (r));
                }
 
                commit_reversible_command ();
@@ -493,10 +491,9 @@ Editor::nudge_forward_capture_offset ()
                for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
                        boost::shared_ptr<Region> r ((*i)->region());
 
-                       XMLNode &before = r->playlist()->get_state();
+                        r->clear_history ();
                        r->set_position (r->position() + distance, this);
-                       XMLNode &after = r->playlist()->get_state();
-                       _session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+                       _session->add_command(new StatefulDiffCommand (r));
                }
 
                commit_reversible_command ();
@@ -523,15 +520,14 @@ Editor::nudge_backward_capture_offset ()
                for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
                        boost::shared_ptr<Region> r ((*i)->region());
 
-                        XMLNode &before = r->playlist()->get_state();
+                        r->clear_history ();
 
                        if (r->position() > distance) {
                                r->set_position (r->position() - distance, this);
                        } else {
                                r->set_position (0, this);
                        }
-                        XMLNode &after = r->playlist()->get_state();
-                       _session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+                       _session->add_command(new StatefulDiffCommand (r));
                }
 
                commit_reversible_command ();
@@ -2225,9 +2221,9 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
        snap_to (where);
 
        begin_reversible_command (_("insert dragged region"));
-        XMLNode &before = playlist->get_state();
+        playlist->clear_history ();
        playlist->add_region (RegionFactory::create (region), where, 1.0);
-       _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+       _session->add_command(new StatefulDiffCommand (playlist));
        commit_reversible_command ();
 }
 
@@ -2303,9 +2299,9 @@ Editor::insert_region_list_selection (float times)
        }
 
        begin_reversible_command (_("insert region"));
-       XMLNode &before = playlist->get_state();
+        playlist->clear_history ();
        playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times);
-       _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+       _session->add_command(new StatefulDiffCommand (playlist));
        commit_reversible_command ();
 }
 
@@ -2818,11 +2814,7 @@ Editor::separate_regions_between (const TimeSelection& ts)
 
                                if ((playlist = rtv->playlist()) != 0) {
 
-                                       XMLNode *before;
-                                       bool got_some;
-
-                                       before = &(playlist->get_state());
-                                       got_some = false;
+                                       playlist->clear_history ();
 
                                        /* XXX need to consider musical time selections here at some point */
 
@@ -2842,25 +2834,18 @@ Editor::separate_regions_between (const TimeSelection& ts)
 
                                                if (!latest_regionviews.empty()) {
 
-                                                       got_some = true;
-
                                                        rtv->view()->foreach_regionview (sigc::bind (
                                                                                sigc::ptr_fun (add_if_covered),
                                                                                &(*t), &new_selection));
-
+                                                        
                                                        if (!in_command) {
                                                                begin_reversible_command (_("separate"));
                                                                in_command = true;
                                                        }
 
-                                                       _session->add_command(new MementoCommand<Playlist>(
-                                                                       *playlist, before, &playlist->get_state()));
+                                                       _session->add_command(new StatefulDiffCommand (playlist));
                                                }
                                        }
-
-                                       if (!got_some) {
-                                               delete before;
-                                       }
                                }
                        }
                }
@@ -3022,10 +3007,9 @@ Editor::crop_region_to (nframes64_t start, nframes64_t end)
                the_end = min (end, the_end);
                cnt = the_end - the_start + 1;
 
-               XMLNode &before = (*i)->get_state();
+                region->clear_history ();
                region->trim_to (the_start, cnt, this);
-               XMLNode &after = (*i)->get_state();
-               _session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
+               _session->add_command (new StatefulDiffCommand (region));
        }
 
        commit_reversible_command ();
@@ -3063,9 +3047,9 @@ Editor::region_fill_track ()
                        return;
                }
 
-               XMLNode &before = pl->get_state();
+                pl->clear_history ();
                pl->add_region (RegionFactory::create (region), region->last_frame(), times);
-               _session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
+               _session->add_command (new StatefulDiffCommand (pl));
        }
 
        commit_reversible_command ();
@@ -3107,9 +3091,9 @@ Editor::region_fill_selection ()
                        continue;
                }
 
-                XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->add_region (RegionFactory::create (region), start, times);
-               _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+               _session->add_command (new StatefulDiffCommand (playlist));
        }
 
        commit_reversible_command ();
@@ -3142,10 +3126,9 @@ Editor::set_sync_point (nframes64_t where, const RegionSelection& rs)
                        in_command = true;
                }
 
-               XMLNode &before = region->playlist()->get_state();
+                region->clear_history ();
                region->set_sync_position (where);
-               XMLNode &after = region->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
+               _session->add_command(new StatefulDiffCommand (region));
        }
 
        if (in_command) {
@@ -3168,10 +3151,9 @@ Editor::remove_region_sync ()
        begin_reversible_command (_("remove sync"));
        for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
 
-                XMLNode &before = (*i)->region()->playlist()->get_state();
+                (*i)->region()->clear_history ();
                (*i)->region()->clear_sync_position ();
-                XMLNode &after = (*i)->region()->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*((*i)->region()->playlist()), &before, &after));
+               _session->add_command(new StatefulDiffCommand ((*i)->region()));
        }
        commit_reversible_command ();
 }
@@ -3290,10 +3272,9 @@ Editor::align_selection_relative (RegionPoint point, nframes64_t position, const
 
        /* move first one specially */
 
-       XMLNode &before = r->playlist()->get_state();
+        r->clear_history ();
        r->set_position (pos, this);
-       XMLNode &after = r->playlist()->get_state();
-       _session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+       _session->add_command(new StatefulDiffCommand (r));
 
        /* move rest by the same amount */
 
@@ -3303,16 +3284,15 @@ Editor::align_selection_relative (RegionPoint point, nframes64_t position, const
 
                boost::shared_ptr<Region> region ((*i)->region());
 
-                XMLNode &before = region->playlist()->get_state();
+                region->clear_history ();
 
                if (dir > 0) {
                        region->set_position (region->position() + distance, this);
                } else {
                        region->set_position (region->position() - distance, this);
                }
-
-                XMLNode &after = region->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
+                
+               _session->add_command(new StatefulDiffCommand (region));
 
        }
 
@@ -3346,7 +3326,7 @@ Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nfram
 void
 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes64_t position)
 {
-       XMLNode &before = region->playlist()->get_state();
+       region->clear_history ();
 
        switch (point) {
        case SyncPoint:
@@ -3364,8 +3344,7 @@ Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint poi
                break;
        }
 
-       XMLNode &after = region->playlist()->get_state();
-       _session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
+       _session->add_command(new StatefulDiffCommand (region));
 }
 
 void
@@ -3396,15 +3375,13 @@ Editor::trim_region (bool front)
 
        for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) {
                if (!(*i)->region()->locked()) {
-                       boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
-                       XMLNode &before = pl->get_state();
+                        (*i)->region()->clear_history ();
                        if (front) {
                                (*i)->region()->trim_front (where, this);
                        } else {
                                (*i)->region()->trim_end (where, this);
                        }
-                       XMLNode &after = pl->get_state();
-                       _session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
+                       _session->add_command (new StatefulDiffCommand ((*i)->region()));
                }
        }
 
@@ -3466,12 +3443,10 @@ Editor::trim_region_to_location (const Location& loc, const char* str)
 
                start = session_frame_to_track_frame (loc.start(), speed);
                end = session_frame_to_track_frame (loc.end(), speed);
-
-               XMLNode &before = rv->region()->playlist()->get_state();
+                
+               rv->region()->clear_history ();
                rv->region()->trim_to (start, (end - start), this);
-               XMLNode &after = rv->region()->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(
-                               *(rv->region()->playlist()), &before, &after));
+               _session->add_command(new StatefulDiffCommand (rv->region()));
        }
 
        commit_reversible_command ();
@@ -3507,11 +3482,9 @@ Editor::trim_region_to_edit_point ()
                        speed = tav->get_diskstream()->speed();
                }
 
-               XMLNode &before = rv->region()->playlist()->get_state();
+                rv->region()->clear_history ();
                rv->region()->trim_end (session_frame_to_track_frame(where, speed), this);
-               XMLNode &after = rv->region()->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(
-                               *(rv->region()->playlist()), &before, &after));
+               _session->add_command(new StatefulDiffCommand (rv->region()));
        }
 
        commit_reversible_command ();
@@ -3547,11 +3520,9 @@ Editor::trim_region_from_edit_point ()
                        speed = tav->get_diskstream()->speed();
                }
 
-               XMLNode &before = rv->region()->playlist()->get_state();
+                rv->region()->clear_history ();
                rv->region()->trim_front (session_frame_to_track_frame(where, speed), this);
-               XMLNode &after = rv->region()->playlist()->get_state();
-               _session->add_command(new MementoCommand<Playlist>(
-                               *(rv->region()->playlist()), &before, &after));
+               _session->add_command(new StatefulDiffCommand (rv->region()));
        }
 
        commit_reversible_command ();
@@ -3604,7 +3575,7 @@ Editor::trim_to_region(bool forward)
                boost::shared_ptr<Region> region = arv->region();
                boost::shared_ptr<Playlist> playlist (region->playlist());
 
-               XMLNode &before = playlist->get_state();
+                region->clear_history ();
 
                if(forward){
 
@@ -3630,8 +3601,7 @@ Editor::trim_to_region(bool forward)
                    arv->region_changed (ARDOUR::bounds_change);
                }
 
-               XMLNode &after = playlist->get_state();
-               _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+               _session->add_command(new StatefulDiffCommand (region));
        }
 
        commit_reversible_command ();
@@ -3658,7 +3628,7 @@ Editor::_freeze_thread (void* arg)
 void*
 Editor::freeze_thread ()
 {
-       clicked_routeview->audio_track()->freeze (*current_interthread_info);
+       clicked_routeview->audio_track()->freeze_me (*current_interthread_info);
        current_interthread_info->done = true;
        return 0;
 }
@@ -3747,7 +3717,7 @@ Editor::bounce_range_selection (bool replace, bool enable_processing)
                itt.cancel = false;
                itt.progress = false;
 
-                XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                boost::shared_ptr<Region> r = rtv->track()->bounce_range (start, start+cnt, itt, enable_processing);
 
                if (replace) {
@@ -3757,8 +3727,7 @@ Editor::bounce_range_selection (bool replace, bool enable_processing)
                        playlist->add_region (r, start);
                }
 
-                XMLNode &after = playlist->get_state();
-               _session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
+               _session->add_command (new StatefulDiffCommand (playlist));
        }
 
        commit_reversible_command ();
@@ -3994,10 +3963,9 @@ Editor::remove_clicked_region ()
        boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
 
        begin_reversible_command (_("remove region"));
-        XMLNode &before = playlist->get_state();
+        playlist->clear_history ();
        playlist->remove_region (clicked_regionview->region());
-        XMLNode &after = playlist->get_state();
-       _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+       _session->add_command(new StatefulDiffCommand (playlist));
        commit_reversible_command ();
 }
 
@@ -4034,7 +4002,7 @@ Editor::remove_selected_regions ()
                regions_to_remove.push_back ((*i)->region());
        }
 
-       vector<PlaylistState> playlists;
+        vector<boost::shared_ptr<Playlist> > playlists;
 
        for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
 
@@ -4045,33 +4013,31 @@ Editor::remove_selected_regions ()
                        continue;
                }
 
-               vector<PlaylistState>::iterator i;
+               vector<boost::shared_ptr<Playlist> >::iterator i;
 
-               //only take state if this is a new playlist.
+               //only prep history if this is a new playlist.
                for (i = playlists.begin(); i != playlists.end(); ++i) {
-                       if ((*i).playlist == playlist) {
+                       if ((*i) == playlist) {
                                break;
                        }
                }
 
                if (i == playlists.end()) {
 
-                       PlaylistState before;
-                       before.playlist = playlist;
-                       before.before = &playlist->get_state();
-
+                        playlist->clear_history ();
                        playlist->freeze ();
-                       playlists.push_back(before);
+
+                       playlists.push_back (playlist);
                }
 
                playlist->remove_region (*rl);
        }
 
-       vector<PlaylistState>::iterator pl;
+       vector<boost::shared_ptr<Playlist> >::iterator pl;
 
        for (pl = playlists.begin(); pl != playlists.end(); ++pl) {
-               (*pl).playlist->thaw ();
-               _session->add_command(new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
+               (*pl)->thaw ();
+               _session->add_command(new StatefulDiffCommand (*pl));
        }
 
        commit_reversible_command ();
@@ -4351,9 +4317,9 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
                sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
 
                playlist = (*i)->region()->playlist();
-                XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->duplicate (r, end_frame + (r->first_frame() - start_frame) + 1, times);
-               _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+               _session->add_command(new StatefulDiffCommand (playlist));
 
                c.disconnect ();
 
@@ -4392,10 +4358,9 @@ Editor::duplicate_selection (float times)
                if ((playlist = (*i)->playlist()) == 0) {
                        continue;
                }
-               XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
-               XMLNode &after = playlist->get_state();
-               _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
+               _session->add_command (new StatefulDiffCommand (playlist));
 
                ++ri;
                if (ri == new_regions.end()) {
@@ -4439,10 +4404,9 @@ void
 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
 {
        begin_reversible_command (_("clear playlist"));
-        XMLNode &before = playlist->get_state();
+        playlist->clear_history ();
        playlist->clear ();
-        XMLNode &after = playlist->get_state();
-       _session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
+       _session->add_command (new StatefulDiffCommand (playlist));
        commit_reversible_command ();
 }
 
@@ -4476,6 +4440,9 @@ Editor::nudge_track (bool use_edit, bool forwards)
                        continue;
                }
 
+                /* XXX STATEFUL this won't capture region moves if don't as a stateful diff
+                 */
+
                 XMLNode &before = playlist->get_state();
                playlist->nudge_after (start, distance, forwards);
                 XMLNode &after = playlist->get_state();
@@ -4555,9 +4522,10 @@ Editor::normalize_region ()
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
                if (!arv)
                        continue;
-               XMLNode &before = arv->region()->get_state();
+                arv->region()->clear_history ();
                arv->audio_region()->normalize_to (spin.get_value());
-               _session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
+               _session->add_command (new StatefulDiffCommand (arv->region()));
+                                       
        }
 
        commit_reversible_command ();
@@ -4588,9 +4556,9 @@ Editor::reset_region_scale_amplitude ()
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
                if (!arv)
                        continue;
-               XMLNode &before = arv->region()->get_state();
+                arv->region()->clear_history ();
                arv->audio_region()->set_scale_amplitude (1.0f);
-               _session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
+               _session->add_command (new StatefulDiffCommand (arv->region()));
        }
 
        commit_reversible_command ();
@@ -4615,10 +4583,12 @@ Editor::adjust_region_scale_amplitude (bool up)
 
        for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
-               if (!arv)
+               if (!arv) {
                        continue;
-               XMLNode &before = arv->region()->get_state();
+                }
 
+                arv->region()->clear_history ();
+                
                double fraction = gain_to_slider_position (arv->audio_region()->scale_amplitude ());
 
                if (up) {
@@ -4640,7 +4610,7 @@ Editor::adjust_region_scale_amplitude (bool up)
                }
 
                arv->audio_region()->set_scale_amplitude (fraction);
-               _session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
+               _session->add_command (new StatefulDiffCommand (arv->region()));
        }
 
        commit_reversible_command ();
@@ -4786,8 +4756,8 @@ Editor::apply_filter (Filter& filter, string command)
 
                        if (arv->audio_region()->apply (filter) == 0) {
 
-                               XMLNode &before = playlist->get_state();
-
+                               playlist->clear_history ();
+                                
                                if (filter.results.empty ()) {
 
                                        /* no regions returned; remove the old one */
@@ -4809,8 +4779,7 @@ Editor::apply_filter (Filter& filter, string command)
 
                                }
 
-                               XMLNode &after = playlist->get_state();
-                               _session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+                               _session->add_command(new StatefulDiffCommand (playlist));
                        } else {
                                goto out;
                        }
@@ -4918,10 +4887,9 @@ Editor::toggle_gain_envelope_visibility ()
        for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
                if (arv) {
-                       XMLNode &before = arv->region()->get_state ();
+                        arv->region()->clear_history ();
                        arv->set_envelope_visible (!arv->envelope_visible());
-                       XMLNode &after = arv->region()->get_state ();
-                       _session->add_command (new MementoCommand<Region> (*(arv->region().get()), &before, &after));
+                       _session->add_command (new StatefulDiffCommand (arv->region()));
                }
        }
 
@@ -4983,10 +4951,9 @@ Editor::set_region_lock_style (Region::PositionLockStyle ps)
        _session->begin_reversible_command (_("region lock style"));
 
        for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
-               XMLNode &before = (*i)->region()->get_state ();
+                (*i)->region()->clear_history ();
                (*i)->region()->set_position_lock_style (ps);
-               XMLNode &after = (*i)->region()->get_state ();
-               _session->add_command (new MementoCommand<Region> (*((*i)->region().get()), &before, &after));
+               _session->add_command (new StatefulDiffCommand ((*i)->region()));
        }
 
        _session->commit_reversible_command ();
@@ -5165,14 +5132,15 @@ Editor::toggle_fade_active (bool in)
                        have_switch = true;
                }
 
-               XMLNode &before = region->get_state();
+               region->clear_history ();
+
                if (in) {
                        region->set_fade_in_active (!yn);
                } else {
                        region->set_fade_out_active (!yn);
                }
-               XMLNode &after = region->get_state();
-               _session->add_command(new MementoCommand<AudioRegion>(*region.get(), &before, &after));
+               
+               _session->add_command(new StatefulDiffCommand (region));
        }
 
        commit_reversible_command ();
@@ -5265,13 +5233,10 @@ Editor::set_fade_in_active (bool yn)
 
 
                boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
-
-               XMLNode &before = ar->get_state();
-
+               
+                ar->clear_history ();
                ar->set_fade_in_active (yn);
-
-               XMLNode &after = ar->get_state();
-               _session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
+               _session->add_command (new StatefulDiffCommand (ar));
        }
 
        commit_reversible_command ();
@@ -5299,12 +5264,9 @@ Editor::set_fade_out_active (bool yn)
 
                boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
 
-               XMLNode &before = ar->get_state();
-
+                ar->clear_history ();
                ar->set_fade_out_active (yn);
-
-               XMLNode &after = ar->get_state();
-               _session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
+               _session->add_command(new StatefulDiffCommand (ar));
        }
 
        commit_reversible_command ();
@@ -5925,7 +5887,7 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList
 
        nframes64_t pos = r->position();
 
-       XMLNode& before (pl->get_state());
+        pl->clear_history ();
 
        x = positions.begin();
 
@@ -6007,9 +5969,7 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList
 
        pl->thaw ();
 
-       XMLNode& after (pl->get_state());
-
-       _session->add_command (new MementoCommand<Playlist>(*pl, &before, &after));
+       _session->add_command (new StatefulDiffCommand (pl));
 }
 
 void
@@ -6330,6 +6290,9 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt,
 
                if (pl) {
 
+                        /* XXX STATEFUL this won't capture region motion if done as stateful diff 
+                         */
+
                        XMLNode &before = pl->get_state();
 
                        if (opt == SplitIntersected) {
index aab6b676585a9ff54743a165e4bc5497bdad9bb0..fcd7e9baf4ebf5fb5055d0d6410ad3973bcb8977 100644 (file)
@@ -26,6 +26,7 @@
 #include "pbd/error.h"
 #include "pbd/pthread_utils.h"
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include <gtkmm2ext/utils.h>
 
@@ -80,11 +81,10 @@ Editor::time_stretch (RegionSelection& regions, float fraction)
                MidiStretch stretch(*_session, request);
                begin_reversible_command ("midi stretch");
                stretch.run(regions.front()->region());
-               XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->replace_region (regions.front()->region(), stretch.results[0],
                                regions.front()->region()->position());
-               XMLNode &after = playlist->get_state();
-               _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
+               _session->add_command (new StatefulDiffCommand (playlist));
                commit_reversible_command ();
        }
 
@@ -315,10 +315,9 @@ Editor::do_timefx (TimeFXDialog& dialog)
                                in_command = true;
                        }
 
-                       XMLNode &before = playlist->get_state();
+                        playlist->clear_history ();
                        playlist->replace_region (region, new_region, region->position());
-                       XMLNode &after = playlist->get_state();
-                       _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
+                       _session->add_command (new StatefulDiffCommand (playlist));
                }
 
                i = tmp;
index 4ea7aba4faaa88692abca2a88e564e01d7bc99a8..aec77df8c08a35146a47cc15023ab75177d444ea 100644 (file)
@@ -29,6 +29,7 @@
 #include <sigc++/signal.h>
 
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/playlist.h"
 #include "ardour/tempo.h"
@@ -2530,9 +2531,9 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
 
                trackview.session()->begin_reversible_command (_("paste"));
 
-               XMLNode& before (_region->get_state());
+                _region->clear_history ();
                _region->set_length (end_frame, this);
-               trackview.session()->add_command (new MementoCommand<Region>(*_region, &before, &_region->get_state()));
+               trackview.session()->add_command (new StatefulDiffCommand (_region));
        }
 
        apply_delta ();
index 19c1a53b3929b771aaceff70203cbdee120ffc4a..1ca63d0f53e5def59a840de4110d8d6e5dfb0f22 100644 (file)
@@ -558,10 +558,10 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
 
                                        if (nlen != region->length()) {
 
-                                               region->freeze ();
+                                               region->suspend_property_changes ();
                                                region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
                                                region->set_length (start + dur - region->position(), this);
-                                               region->thaw ();
+                                               region->resume_property_changes ();
 
                                                if (origlen == 1) {
                                                        /* our special initial length */
@@ -622,10 +622,10 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
 
                                        if (region->source_length(0) >= region->position() + nlen) {
 
-                                               region->freeze ();
+                                               region->suspend_property_changes ();
                                                region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
                                                region->set_length (nlen, this);
-                                               region->thaw ();
+                                               region->resume_property_changes ();
 
                                                if (origlen == 1) {
                                                        /* our special initial length */
index b1adb7c67eea5cb2d19cdcc8ab36dca22a76520f..5949541e56b9e0f4254313778808975fac48afa2 100644 (file)
@@ -31,6 +31,7 @@
 #include "pbd/basename.h"
 #include "pbd/enumwriter.h"
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/selector.h>
@@ -966,7 +967,7 @@ MidiTimeAxisView::add_region (nframes64_t pos)
        Editor* real_editor = dynamic_cast<Editor*> (&_editor);
 
        real_editor->begin_reversible_command (_("create region"));
-       XMLNode &before = playlist()->get_state();
+        playlist()->clear_history ();
 
        framepos_t start = pos;
        real_editor->snap_to (start, -1);
@@ -988,8 +989,7 @@ MidiTimeAxisView::add_region (nframes64_t pos)
        boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
 
        playlist()->add_region (region, start);
-       XMLNode &after = playlist()->get_state();
-       _session->add_command (new MementoCommand<Playlist> (*playlist().get(), &before, &after));
+       _session->add_command (new StatefulDiffCommand (playlist()));
 
        real_editor->commit_reversible_command();
 
index 827562524e29728833bb184a4ecd028270eb2ad3..30e19ec24a13efd122d0acda44dd6513393e0e83 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "evoral/Curve.hpp"
 #include "pbd/memento_command.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/audioregion.h"
 #include "ardour/session.h"
@@ -53,6 +54,8 @@ void
 AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction)
 {
        AutomationLine::start_drag_single (cp, x, fraction);
+
+        // XXX Stateful need to capture automation curve data
        
        if (!rv.audio_region()->envelope_active()) {
                trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
@@ -72,10 +75,9 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
        XMLNode &before = alist->get_state();
 
        if (!rv.audio_region()->envelope_active()) {
-               XMLNode &region_before = rv.audio_region()->get_state();
+                rv.audio_region()->clear_history ();
                rv.audio_region()->set_envelope_active(true);
-               XMLNode &region_after = rv.audio_region()->get_state();
-               trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &region_before, &region_after));
+               trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region()));
        }
 
        alist->erase (mr.start, mr.end);
index fc5b4255b3cf50f2f4e6737f2a2cc8654211a963..be8d988a419e1f05158b652b078cef11a32f3319 100644 (file)
@@ -49,7 +49,7 @@ class AudioTrack : public Track
 
        int export_stuff (BufferSet& bufs, sframes_t start_frame, nframes_t nframes, bool enable_processing = true);
 
-       void freeze (InterThreadInfo&);
+       void freeze_me (InterThreadInfo&);
        void unfreeze ();
 
        boost::shared_ptr<Region> bounce (InterThreadInfo&);
index 1778771c5fe54cb6d8fbb3cf0a17dadbd4cca55c..79acedebf39f4efe0e395f9a0785e7a14ea1c982 100644 (file)
@@ -50,7 +50,6 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
        AutomationList& operator= (const AutomationList&);
        bool operator== (const AutomationList&);
 
-       void freeze();
        void thaw ();
        void mark_dirty () const;
 
index bc636eea832bfcfc952d14aad459315ebfcb55b7..6f8fda78da69309c519e8ebf75f6dd6f43a75ef2 100644 (file)
@@ -53,7 +53,7 @@ public:
 
        int export_stuff (BufferSet& bufs, nframes_t nframes, sframes_t end_frame);
 
-       void freeze (InterThreadInfo&);
+       void freeze_me (InterThreadInfo&);
        void unfreeze ();
 
        boost::shared_ptr<Region> bounce (InterThreadInfo&);
index 1da185c6f29bfcc3d76d3cc64caf9f7c72f0a886..09dd8f203c2f0625b4dc7e4c88aac84437e5d3be 100644 (file)
@@ -93,9 +93,6 @@ class Region
 
         PBD::PropertyList* property_factory (const XMLNode&) const;
 
-       void unlock_property_changes () { _no_property_changes = false; }
-       void block_property_changes () { _no_property_changes = true; }
-       
        virtual ~Region();
        
        /** Note: changing the name of a Region does not constitute an edit */
@@ -156,8 +153,7 @@ class Region
        void set_position_lock_style (PositionLockStyle ps);
        void recompute_position_from_lock_style ();
 
-       void freeze ();
-       void thaw ();
+       void suspend_property_changes ();
 
        bool covers (framepos_t frame) const {
                return first_frame() <= frame && frame <= last_frame();
@@ -288,6 +284,7 @@ class Region
 
   protected:
        void send_change (const PBD::PropertyChange&);
+        void mid_thaw (const PBD::PropertyChange&);
 
        void trim_to_internal (framepos_t position, framecnt_t length, void *src);
        virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute);
@@ -304,7 +301,6 @@ class Region
        virtual void recompute_at_end () = 0;
        
        DataType                _type;
-       bool                    _no_property_changes;
 
        PBD::Property<bool>        _muted;
        PBD::Property<bool>        _opaque;
@@ -332,14 +328,11 @@ class Region
        framepos_t              _last_position;
        PositionLockStyle       _positional_lock_style;
        mutable RegionEditState _first_edit;
-       int                     _frozen;
        BBT_Time                _bbt_time;
        AnalysisFeatureList     _transients;
        bool                    _valid_transients;
        mutable uint64_t        _read_data_count;  ///< modified in read()
-       PBD::PropertyChange     _pending_changed;
        uint64_t                _last_layer_op;  ///< timestamp
-       Glib::Mutex             _lock;
        SourceList              _sources;
        /** Used when timefx are applied, so we can always use the original source */
        SourceList              _master_sources;
index d26c84a795fe06c2172de5e0e62e087b378be700..cf88f2e6bde11e07c4ac6678c1b11d9976b49057 100644 (file)
@@ -603,7 +603,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        boost::shared_ptr<Region> write_one_track (AudioTrack&, nframes_t start, nframes_t end,
                        bool overwrite, std::vector<boost::shared_ptr<Source> >&, InterThreadInfo& wot,
                        bool enable_processing = true);
-       int freeze (InterThreadInfo&);
+       int freeze_all (InterThreadInfo&);
 
        /* session-wide solo/mute/rec-enable */
 
index 0ed4b8c70bd51d20346095699e996312637ca322..eee9f03fe50a0e0def1fb1348bb4b1c6aaf00a0b 100644 (file)
@@ -74,7 +74,7 @@ class Track : public Route
 
        FreezeState freeze_state() const;
 
-       virtual void freeze (InterThreadInfo&) = 0;
+       virtual void freeze_me (InterThreadInfo&) = 0;
        virtual void unfreeze () = 0;
 
        virtual boost::shared_ptr<Region> bounce (InterThreadInfo&) = 0;
index f7a1240bddf7a69990ecb37db6eb668e1f703b96..1f77964d0d63565c11b2cea81bc4df07b210a969 100644 (file)
@@ -35,7 +35,7 @@
 #include "pbd/xml++.h"
 #include "pbd/memento_command.h"
 #include "pbd/enumwriter.h"
-#include "pbd/stacktrace.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/analyser.h"
 #include "ardour/ardour.h"
@@ -1497,7 +1497,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
 
                // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
 
-               XMLNode &before = _playlist->get_state();
+                _playlist->clear_history ();
                _playlist->freeze ();
 
                for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
@@ -1537,8 +1537,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
                }
 
                _playlist->thaw ();
-               XMLNode &after = _playlist->get_state();
-               _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
+               _session.add_command (new StatefulDiffCommand (_playlist));
        }
 
        mark_write_completed = true;
index ebc7a9be6676f52b2edbc9439edc1dc54d687d3f..245b122c1864c22f247cfe770a8642e72136273f 100644 (file)
@@ -692,7 +692,7 @@ AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt,
 }
 
 void
-AudioTrack::freeze (InterThreadInfo& itt)
+AudioTrack::freeze_me (InterThreadInfo& itt)
 {
        vector<boost::shared_ptr<Source> > srcs;
        string new_playlist_name;
index e30a3a59949347e8b37cf8dcc7b2354b2aa71014..abddffc12e887dce54a7f7fbbf9b11469817a839 100644 (file)
@@ -589,7 +589,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
        LocaleGuard lg (X_("POSIX"));
        boost::shared_ptr<Playlist> the_playlist (_playlist.lock());    
 
-       freeze ();
+       suspend_property_changes ();
 
        if (the_playlist) {
                the_playlist->freeze ();
@@ -612,7 +612,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
 
        /* Now find envelope description and other related child items */
 
-       _envelope->freeze ();
+        _envelope->freeze ();
 
        for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
                XMLNode *child;
@@ -677,9 +677,9 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
                }
        }
 
-       _envelope->thaw ();
-       thaw ();
-
+        _envelope->thaw ();
+       resume_property_changes ();
+        
        if (send) {
                send_change (what_changed);
        }
@@ -761,9 +761,9 @@ AudioRegion::set_fade_out_shape (FadeShape shape)
 void
 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
 {
-       _fade_in->freeze ();
+        _fade_in->freeze ();
        *_fade_in = *f;
-       _fade_in->thaw ();
+        _fade_in->thaw ();
        
        send_change (PropertyChange (Properties::fade_in));
 }
@@ -771,7 +771,7 @@ AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
 void
 AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
 {
-       _fade_in->freeze ();
+        _fade_in->freeze ();
        _fade_in->clear ();
 
        switch (shape) {
@@ -822,15 +822,15 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
                break;
        }
 
-       _fade_in->thaw ();
+        _fade_in->thaw ();
 }
 
 void
 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
 {
-       _fade_out->freeze ();
+        _fade_out->freeze ();
        *_fade_out = *f;
-       _fade_out->thaw ();
+        _fade_out->thaw ();
 
        send_change (PropertyChange (Properties::fade_in));
 }
@@ -838,7 +838,7 @@ AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
 void
 AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
 {
-       _fade_out->freeze ();
+        _fade_out->freeze ();
        _fade_out->clear ();
 
        switch (shape) {
@@ -887,7 +887,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
                break;
        }
 
-       _fade_out->thaw ();
+        _fade_out->thaw ();
 }
 
 void
@@ -977,11 +977,11 @@ AudioRegion::set_default_fades ()
 void
 AudioRegion::set_default_envelope ()
 {
-       _envelope->freeze ();
+        _envelope->freeze ();
        _envelope->clear ();
        _envelope->fast_simple_add (0, 1.0f);
        _envelope->fast_simple_add (_length, 1.0f);
-       _envelope->thaw ();
+        _envelope->thaw ();
 }
 
 void
@@ -991,10 +991,10 @@ AudioRegion::recompute_at_end ()
           based on the the existing curve.
        */
 
-       _envelope->freeze ();
+        _envelope->freeze ();
        _envelope->truncate_end (_length);
        _envelope->set_max_xval (_length);
-       _envelope->thaw ();
+        _envelope->thaw ();
 
        if (_fade_in->back()->when > _length) {
                _fade_in->extend_to (_length);
index 479674aee6a55aee94ad86aaca3dbaf54454e707..92a3d167da76e9ba9d3cd124020f560021a461e4 100644 (file)
@@ -170,7 +170,7 @@ AutomationList::maybe_signal_changed ()
 {
        ControlList::maybe_signal_changed ();
 
-       if (!_frozen) {
+       if (!ControlList::frozen()) {
                StateChanged (); /* EMIT SIGNAL */
        }
 }
@@ -207,12 +207,6 @@ AutomationList::stop_touch ()
        _new_value = false;
 }
 
-void
-AutomationList::freeze ()
-{
-       _frozen++;
-}
-
 void
 AutomationList::thaw ()
 {
@@ -313,7 +307,7 @@ AutomationList::deserialize_events (const XMLNode& node)
                return -1;
        }
 
-       freeze ();
+        ControlList::freeze ();
        clear ();
 
        stringstream str (content_node->content());
@@ -344,8 +338,8 @@ AutomationList::deserialize_events (const XMLNode& node)
                maybe_signal_changed ();
        }
 
-       thaw ();
-
+        ControlList::thaw ();
+        
        return 0;
 }
 
@@ -377,7 +371,7 @@ AutomationList::set_state (const XMLNode& node, int version)
                nframes_t x;
                double y;
 
-               freeze ();
+                ControlList::freeze ();
                clear ();
 
                for (i = elist.begin(); i != elist.end(); ++i) {
@@ -397,7 +391,7 @@ AutomationList::set_state (const XMLNode& node, int version)
                        fast_simple_add (x, y);
                }
 
-               thaw ();
+                ControlList::thaw ();
 
                return 0;
        }
index ccfaeaa5cd305ad98af39cae1d11de47a5f8200d..836fb05c8b2ff3d9b8a85c7df0b0eaae95213f19 100644 (file)
@@ -35,6 +35,7 @@
 #include "pbd/xml++.h"
 #include "pbd/memento_command.h"
 #include "pbd/enumwriter.h"
+#include "pbd/stateful_diff_command.h"
 
 #include "ardour/ardour.h"
 #include "ardour/audioengine.h"
@@ -1011,7 +1012,7 @@ MidiDiskstream::transport_stopped (struct tm& /*when*/, time_t /*twhen*/, bool a
 
                // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
 
-               XMLNode &before = _playlist->get_state();
+               _playlist->clear_history ();
                _playlist->freeze ();
 
                uint32_t buffer_position = 0;
@@ -1053,8 +1054,7 @@ MidiDiskstream::transport_stopped (struct tm& /*when*/, time_t /*twhen*/, bool a
                }
 
                _playlist->thaw ();
-               XMLNode &after = _playlist->get_state();
-               _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
+               _session.add_command (new StatefulDiffCommand(_playlist));
 
        }
 
index af66f2f40c3d69ce24245acbdf03e08b9c04bd10..9409e9f1439b14b0fb2c5e73c9947f82cf0da8fa 100644 (file)
@@ -556,7 +556,7 @@ MidiTrack::bounce_range (nframes_t /*start*/, nframes_t /*end*/, InterThreadInfo
 }
 
 void
-MidiTrack::freeze (InterThreadInfo& /*itt*/)
+MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
 {
 }
 
index 6169df8f030b93451626985ca9259b5f8fdba01f..eb21cdcde6483fdaff79470e21bd44108cb08c16 100644 (file)
@@ -855,7 +855,7 @@ Playlist::partition (framepos_t start, framepos_t end, bool cut)
        partition_internal (start, end, cut, thawlist);
 
        for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
-               (*i)->thaw ();
+               (*i)->resume_property_changes ();
        }
 }
 
@@ -972,7 +972,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re
 
                                /* "front" ***** */
 
-                               current->freeze ();
+                               current->suspend_property_changes ();
                                thawlist.push_back (current);
                                current->trim_end (pos2, this);
 
@@ -1011,7 +1011,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re
 
                                /* front ****** */
 
-                               current->freeze ();
+                               current->suspend_property_changes ();
                                thawlist.push_back (current);
                                current->trim_end (pos2, this);
 
@@ -1054,7 +1054,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re
 
                                /* end */
 
-                               current->freeze ();
+                               current->suspend_property_changes ();
                                thawlist.push_back (current);
                                current->trim_front (pos3, this);
                        } else if (overlap == OverlapExternal) {
@@ -1157,7 +1157,7 @@ Playlist::cut (framepos_t start, framecnt_t cnt, bool result_is_hidden)
        partition_internal (start, start+cnt-1, true, thawlist);
 
        for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
-               (*i)->thaw ();
+               (*i)->resume_property_changes();
        }
 
        return the_copy;
@@ -2123,15 +2123,15 @@ Playlist::set_state (const XMLNode& node, int version)
 
                        if ((region = region_by_id (id))) {
 
-                               region->freeze ();
+                               region->suspend_property_changes ();
 
                                if (region->set_state (*child, version)) {
-                                       region->thaw ();
+                                       region->resume_property_changes ();
                                        continue;
                                }
                                
                        } else if ((region = RegionFactory::create (_session, *child, true)) != 0) {
-                               region->freeze ();
+                               region->suspend_property_changes ();
                        } else {
                                error << _("Playlist: cannot create region from XML") << endmsg;
                                continue;
@@ -2141,7 +2141,7 @@ Playlist::set_state (const XMLNode& node, int version)
 
                        // So that layer_op ordering doesn't get screwed up
                        region->set_last_layer_op( region->layer());
-                       region->thaw ();
+                       region->resume_property_changes ();
                }
        }
 
index f59d076c59b76970872a6a1efbbc51525ee218f2..b89ad2854b575573b7a3a40f7bc63c92ea8c10c3 100644 (file)
@@ -199,13 +199,11 @@ Region::register_properties ()
 Region::Region (Session& s, framepos_t start, framecnt_t length, const string& name, DataType type)
        : SessionObject(s, name)
        , _type(type)
-       , _no_property_changes (true)
        , REGION_DEFAULT_STATE(start,length)
        , _last_length (length)
        , _last_position (0)
        , _positional_lock_style(AudioTime)
        , _first_edit (EditChangesNothing)
-       , _frozen(0)
        , _read_data_count(0)
        , _last_layer_op(0)
        , _pending_explicit_relayer (false)
@@ -219,13 +217,11 @@ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& n
 Region::Region (const SourceList& srcs)
        : SessionObject(srcs.front()->session(), "toBeRenamed")
        , _type (srcs.front()->type())
-       , _no_property_changes (true)
        , REGION_DEFAULT_STATE(0,0)
        , _last_length (0)
        , _last_position (0)
         , _positional_lock_style (_type == DataType::AUDIO ? AudioTime : MusicTime)
        , _first_edit (EditChangesNothing)
-       , _frozen (0)
        , _valid_transients(false)
        , _read_data_count(0)
        , _last_layer_op (0)
@@ -251,13 +247,11 @@ Region::Region (const SourceList& srcs)
 Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, bool offset_relative)
        : SessionObject(other->session(), other->name())
        , _type (other->data_type())
-       , _no_property_changes (true)
        , REGION_COPY_STATE (other)
        , _last_length (other->_last_length)
        , _last_position(other->_last_position) \
        , _positional_lock_style(other->_positional_lock_style) \
        , _first_edit (EditChangesNothing)
-       , _frozen (0)
        , _valid_transients(false)
        , _read_data_count(0)
        , _last_layer_op (0)
@@ -360,13 +354,11 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, boo
 Region::Region (boost::shared_ptr<const Region> other, const SourceList& srcs)
        : SessionObject (other->session(), other->name())
        , _type (srcs.front()->type())
-       , _no_property_changes (true)
        , REGION_COPY_STATE (other)
        , _last_length (other->_last_length)
        , _last_position (other->_last_position)
         , _positional_lock_style (other->_positional_lock_style)
        , _first_edit (EditChangesID)
-       , _frozen (0)
        , _valid_transients (false)
        , _read_data_count (0)
        , _last_layer_op (other->_last_layer_op)
@@ -393,13 +385,11 @@ Region::Region (boost::shared_ptr<const Region> other, const SourceList& srcs)
 Region::Region (boost::shared_ptr<const Region> other)
        : SessionObject(other->session(), other->name())
        , _type(other->data_type())
-       , _no_property_changes (true)
        , REGION_COPY_STATE (other)
        , _last_length (other->_last_length)
        , _last_position (other->_last_position)
         , _positional_lock_style (other->_positional_lock_style)
        , _first_edit (EditChangesID)
-       , _frozen(0)
        , _valid_transients(false)
        , _read_data_count(0)
        , _last_layer_op(other->_last_layer_op)
@@ -475,7 +465,7 @@ Region::set_length (framecnt_t len, void */*src*/)
                maybe_uncopy ();
                invalidate_transients ();
 
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        recompute_at_end ();
                }
 
@@ -803,7 +793,7 @@ Region::trim_front (framepos_t new_position, void *src)
                }
 
                trim_to_internal (new_position, newlen, src);
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        recompute_at_start ();
                }
        }
@@ -822,7 +812,7 @@ Region::trim_end (framepos_t new_endpoint, void */*src*/)
 
        if (new_endpoint > _position) {
                trim_to_internal (_position, new_endpoint - _position + 1, this);
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        recompute_at_end ();
                }
        }
@@ -837,7 +827,7 @@ Region::trim_to (framepos_t position, framecnt_t length, void *src)
 
        trim_to_internal (position, length, src);
 
-       if (!_frozen) {
+       if (!property_changes_suspended()) {
                recompute_at_start ();
                recompute_at_end ();
        }
@@ -890,14 +880,14 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/)
                what_changed.add (Properties::start);
        }
        if (_length != length) {
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        _last_length = _length;
                }
                _length = length;
                what_changed.add (Properties::length);
        }
        if (_position != position) {
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        _last_position = _position;
                }
                _position = position;
@@ -987,7 +977,7 @@ Region::set_sync_position (framepos_t absolute_pos)
        if (file_pos != _sync_position) {
                _sync_marked = true;
                _sync_position = file_pos;
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        maybe_uncopy ();
                }
                send_change (Properties::sync_position);
@@ -999,7 +989,7 @@ Region::clear_sync_position ()
 {
        if (sync_marked()) {
                _sync_marked = false;
-               if (!_frozen) {
+               if (!property_changes_suspended()) {
                        maybe_uncopy ();
                }
                send_change (Properties::sync_position);
@@ -1229,43 +1219,22 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang
 }
 
 void
-Region::freeze ()
+Region::suspend_property_changes ()
 {
-       _frozen++;
+        Stateful::suspend_property_changes ();
        _last_length = _length;
        _last_position = _position;
 }
 
 void
-Region::thaw ()
+Region::mid_thaw (const PropertyChange& what_changed)
 {
-       PropertyChange what_changed;
-
-       {
-               Glib::Mutex::Lock lm (_lock);
-
-               if (_frozen && --_frozen > 0) {
-                       return;
-               }
-
-               if (!_pending_changed.empty()) {
-                       what_changed = _pending_changed;
-                       _pending_changed.clear ();
-               }
-       }
-
-       if (what_changed.empty()) {
-               return;
-       }
-
        if (what_changed.contains (Properties::length)) {
                if (what_changed.contains (Properties::position)) {
                        recompute_at_start ();
                }
                recompute_at_end ();
        }
-
-       send_change (what_changed);
 }
 
 void
@@ -1275,15 +1244,7 @@ Region::send_change (const PropertyChange& what_changed)
                return;
        }
 
-       {
-               Glib::Mutex::Lock lm (_lock);
-               if (_frozen) {
-                       _pending_changed.add (what_changed);
-                       return;
-               }
-       }
-
-       PropertyChanged (what_changed);
+        Stateful::send_change (what_changed);
 
        if (!_no_property_changes) {
                
@@ -1294,12 +1255,10 @@ Region::send_change (const PropertyChange& what_changed)
                try {
                        boost::shared_ptr<Region> rptr = shared_from_this();
                        RegionPropertyChanged (rptr, what_changed);
-
                } catch (...) {
                        /* no shared_ptr available, relax; */
                }
        }
-
 }
 
 void
@@ -1584,16 +1543,26 @@ Region::set_property (const PropertyBase& prop)
        } else if (prop == Properties::position_locked.property_id) {
                _position_locked = dynamic_cast<const PropertyTemplate<bool>*>(&prop)->val();
        } else if (prop == Properties::start.property_id) {
-               _start = dynamic_cast<const PropertyTemplate<framepos_t>*>(&prop)->val();
+               framepos_t val = dynamic_cast<const PropertyTemplate<framepos_t>*>(&prop)->val();
+                if (val != _start) {
+                        DEBUG_TRACE (DEBUG::Properties, string_compose ("region %1 start changed from %2 to %3",
+                                                                       _name.val(), _start, val));
+                        _start = val;
+                        return true;
+                }
        } else if (prop == Properties::length.property_id) {
                framecnt_t val = dynamic_cast<const PropertyTemplate<framecnt_t>* > (&prop)->val();
                if (val != _length) {
+                       DEBUG_TRACE (DEBUG::Properties, string_compose ("region %1 length changed from %2 to %3",
+                                                                       _name.val(), _length, val));
                        _length = val;
                        return true;
                }
        } else if (prop == Properties::position.property_id) {
                framepos_t val = dynamic_cast<const PropertyTemplate<framepos_t>*>(&prop)->val();
                if (val != _position) {
+                       DEBUG_TRACE (DEBUG::Properties, string_compose ("region %1 position changed from %2 to %3",
+                                                                       _name.val(), _position, val));
                        _position = val;
                        return true;
                }
index d2c5fa1b221c343f03776bf142c03d417057483f..3f4af2462c28e31aacf6a29e9b1bdc0caee83889 100644 (file)
@@ -67,7 +67,6 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
        }
 
        if (ret) {
-               ret->unlock_property_changes ();
                map_add (ret);
 
                /* pure copy constructor - no property list */
@@ -106,10 +105,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, c
        }
 
        if (ret) {
-
                ret->set_properties (plist);
-               ret->unlock_property_changes ();
-
                map_add (ret);
 
                if (announce) {
@@ -149,10 +145,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
        }
 
        if (ret) {
-
                ret->set_properties (plist);
-               ret->unlock_property_changes ();
-
                map_add (ret);
 
                if (announce) {
@@ -195,8 +188,6 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
        if (ret) {
 
                ret->set_properties (plist);
-               ret->unlock_property_changes ();
-
                map_add (ret);
 
                if (announce) {
@@ -242,8 +233,6 @@ RegionFactory::create (const SourceList& srcs, const PropertyList& plist, bool a
        if (ret) {
 
                ret->set_properties (plist);
-               ret->unlock_property_changes ();
-
                map_add (ret);
 
                if (announce) {
@@ -290,7 +279,6 @@ RegionFactory::create (SourceList& srcs, const XMLNode& node)
                if (ret->set_state (node, Stateful::loading_state_version)) {
                        ret.reset ();
                } else {
-                       ret->unlock_property_changes ();
                        map_add (ret);
                        CheckNewRegion (ret);
                }
index 0c2f12d91dc9f7d7efb664f59b880a46c76f99db..53c8ea2350e75093bceb8241659ffecf7bb94e64 100644 (file)
@@ -3847,7 +3847,7 @@ Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, b
 }
 
 int
-Session::freeze (InterThreadInfo& itt)
+Session::freeze_all (InterThreadInfo& itt)
 {
        shared_ptr<RouteList> r = routes.reader ();
 
@@ -3859,7 +3859,7 @@ Session::freeze (InterThreadInfo& itt)
                        /* XXX this is wrong because itt.progress will keep returning to zero at the start
                           of every track.
                        */
-                       t->freeze (itt);
+                       t->freeze_me (itt);
                }
        }
 
index b4c8590cb65a7281536e74937a498d59bdddfd09..d68b6a3e5f9fe0e273d2cdc3b891266636400a9e 100644 (file)
@@ -94,8 +94,9 @@ public:
        ControlList& operator= (const ControlList&);
        bool operator== (const ControlList&);
 
-       void freeze();
-       void thaw ();
+       virtual void freeze();
+        virtual void thaw ();
+        bool frozen() const { return _frozen; }
 
        const Parameter& parameter() const                 { return _parameter; }
        void             set_parameter(const Parameter& p) { _parameter = p; }
index 274dfffd9c327150e19da26b42276646d551f614..8d2f465ebf217b33eff1d824c091570315c06a27 100644 (file)
@@ -122,8 +122,10 @@ protected:
        {}
 
        void set (T const& v) {
-               _old      = _current;
-               _have_old = true;
+                if (!_have_old) {
+                        _old      = _current;
+                        _have_old = true;
+                }
                _current  = v;
        }
 
index 78b9eb7b3b4057e897cfb9d743ef156ba399285f..93f353a095bbb710918784bfdf04c28d2201991f 100644 (file)
@@ -82,6 +82,12 @@ class Stateful {
        static int current_state_version;
        static int loading_state_version;
 
+       virtual void suspend_property_changes ();
+       virtual void resume_property_changes ();
+
+       void unlock_property_changes () { _no_property_changes = false; }
+       void block_property_changes () { _no_property_changes = true; }
+       
   protected:
 
        void add_instant_xml (XMLNode&, const sys::path& directory_path);
@@ -100,10 +106,21 @@ class Stateful {
 
        XMLNode *_extra_xml;
        XMLNode *_instant_xml;
-       PBD::ID _id;
+       PBD::ID  _id;
+        int32_t  _frozen;
+        bool     _no_property_changes;
+       PBD::PropertyChange     _pending_changed;
+        Glib::Mutex _lock;
 
        std::string _xml_node_name; ///< name of node to use for this object in XML
        OwnedPropertyList* _properties;
+
+        virtual void send_change (const PropertyChange&);
+        /** derived classes can implement this in order to process a property change
+            within thaw() just before send_change() is called.
+        */
+        virtual void mid_thaw (const PropertyChange&) { }
+        bool property_changes_suspended() const { return g_atomic_int_get (&_frozen) > 0; }
 };
 
 } // namespace PBD
index f2d9f9ee123493657c34ba48b604e235b875ef2d..1bf8c17d83e08f30d1b7913cee02be61c2de94ad 100644 (file)
@@ -39,7 +39,9 @@ int Stateful::current_state_version = 0;
 int Stateful::loading_state_version = 0;
 
 Stateful::Stateful ()
-        : _properties (new OwnedPropertyList)
+        : _frozen (0)
+        , _no_property_changes (false)
+        , _properties (new OwnedPropertyList)
 {
        _extra_xml = 0;
        _instant_xml = 0;
@@ -238,4 +240,52 @@ Stateful::add_property (PropertyBase& s)
         _properties->add (s);
 }
 
+void
+Stateful::send_change (const PropertyChange& what_changed)
+{
+       if (what_changed.empty()) {
+               return;
+       }
+
+       {
+               Glib::Mutex::Lock lm (_lock);
+               if (_frozen) {
+                       _pending_changed.add (what_changed);
+                       return;
+               }
+       }
+
+       PropertyChanged (what_changed);
+}
+
+void
+Stateful::suspend_property_changes ()
+{
+        _frozen++;
+}
+
+void
+Stateful::resume_property_changes ()
+{
+       PropertyChange what_changed;
+
+       {
+               Glib::Mutex::Lock lm (_lock);
+
+               if (_frozen && --_frozen > 0) {
+                       return;
+               }
+
+               if (!_pending_changed.empty()) {
+                       what_changed = _pending_changed;
+                       _pending_changed.clear ();
+               }
+       }
+
+        mid_thaw (what_changed);
+
+        send_change (what_changed);
+}
+
+
 } // namespace PBD
index baf888667e70539bdaabac004d3cc3b77d5f440c..001eca6f3e3fe8f4118fc1910633552ca2c46000 100644 (file)
@@ -36,7 +36,7 @@ OSCControllable::OSCControllable (lo_address a, const std::string& p, boost::sha
        , addr (a)
        , path (p)
 {
-       c->Changed.connect (changed_connection, boost::bind (&OSCControllable::send_change, this), OSC::instance());
+       c->Changed.connect (changed_connection, boost::bind (&OSCControllable::send_change_message, this), OSC::instance());
 }
 
 OSCControllable::~OSCControllable ()
@@ -58,7 +58,7 @@ OSCControllable::set_state (const XMLNode& /*node*/, int /*version*/)
 }
 
 void
-OSCControllable::send_change ()
+OSCControllable::send_change_message ()
 {
        lo_message msg = lo_message_new ();
        
@@ -84,7 +84,7 @@ OSCRouteControllable::~OSCRouteControllable ()
 }
 
 void
-OSCRouteControllable::send_change ()
+OSCRouteControllable::send_change_message ()
 {
        lo_message msg = lo_message_new ();
 
index 55e2815d35c7ce3dd49db9a0f4c8f7c2a73a56d6..828c3769f570a23c4412f5d8e098d8bcfbff0fea 100644 (file)
@@ -50,7 +50,7 @@ class OSCControllable : public PBD::Stateful
        lo_address addr;
        std::string path;
 
-       virtual void send_change ();
+       virtual void send_change_message ();
 };
 
 class OSCRouteControllable : public OSCControllable
@@ -67,7 +67,7 @@ class OSCRouteControllable : public OSCControllable
   private:
        boost::shared_ptr<ARDOUR::Route> _route;
 
-       void send_change ();
+       void send_change_message ();
 };
 
 #endif /* __osc_osccontrollable_h__ */