diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index b2174d1933..2866f82e61 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -155,7 +155,13 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions) boost::shared_ptr pl = (*a)->region()->playlist(); - if (! pl->frozen()) { + if (!pl) { + cerr << "region " << (*a)->region()->name() << " has no playlist!\n"; + a = tmp; + continue; + } + + if (!pl->frozen()) { /* we haven't seen this playlist before */ /* remember used playlists so we can thaw them later */ @@ -3934,17 +3940,6 @@ Editor::cut_copy_midi (CutCopyOp op) } } -struct PlaylistState { - boost::shared_ptr playlist; - XMLNode* before; -}; - -struct lt_playlist { - bool operator () (const PlaylistState& a, const PlaylistState& b) { - return a.playlist < b.playlist; - } -}; - struct PlaylistMapping { TimeAxisView* tv; boost::shared_ptr pl; @@ -4057,8 +4052,8 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) nframes64_t first_position = max_frames; - set freezelist; - pair::iterator,bool> insert_result; + typedef set > FreezeList; + FreezeList freezelist; /* get ordering correct before we cut/copy */ @@ -4072,21 +4067,19 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) boost::shared_ptr pl = (*x)->region()->playlist(); if (pl) { - set::iterator fl; + FreezeList::iterator fl; //only take state if this is a new playlist. for (fl = freezelist.begin(); fl != freezelist.end(); ++fl) { - if ((*fl).playlist == pl) { + if ((*fl) == pl) { break; } } if (fl == freezelist.end()) { - PlaylistState before; - before.playlist = pl; - before.before = &pl->get_state(); + pl->clear_history(); pl->freeze (); - insert_result = freezelist.insert (before); + freezelist.insert (pl); } } } @@ -4177,10 +4170,10 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) if (!foo.empty()) { cut_buffer->set (foo); } - - for (set::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) { - (*pl).playlist->thaw (); - _session->add_command (new MementoCommand(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state())); + + for (FreezeList::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) { + (*pl)->thaw (); + _session->add_command (new StatefulDiffCommand (*pl)); } } @@ -4440,13 +4433,20 @@ Editor::nudge_track (bool use_edit, bool forwards) continue; } - /* XXX STATEFUL this won't capture region moves if don't as a stateful diff - */ + playlist->clear_history (); + playlist->clear_owned_history (); - XMLNode &before = playlist->get_state(); playlist->nudge_after (start, distance, forwards); - XMLNode &after = playlist->get_state(); - _session->add_command (new MementoCommand(*playlist, &before, &after)); + + vector cmds; + + playlist->rdiff (cmds); + + for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { + _session->add_command (*c); + } + + _session->add_command (new StatefulDiffCommand (playlist)); } commit_reversible_command (); @@ -6290,10 +6290,8 @@ 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(); + pl->clear_history (); + pl->clear_owned_history (); if (opt == SplitIntersected) { pl->split (pos); @@ -6301,9 +6299,17 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, pl->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue); - XMLNode &after = pl->get_state(); + vector cmds; + + pl->rdiff (cmds); + + cerr << "Shift generated " << cmds.size() << " sdc's\n"; - _session->add_command (new MementoCommand (*pl, &before, &after)); + for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { + _session->add_command (*c); + } + + _session->add_command (new StatefulDiffCommand (pl)); commit = true; } diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 39bb1847a1..62a2b2b8a0 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -33,7 +33,7 @@ #include "pbd/whitespace.h" #include "pbd/memento_command.h" #include "pbd/enumwriter.h" -#include "pbd/stacktrace.h" +#include "pbd/stateful_diff_command.h" #include #include @@ -1385,12 +1385,22 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) } } - XMLNode &before = playlist->get_state(); + playlist->clear_history (); + playlist->clear_owned_history (); + switch (op) { case Cut: if ((what_we_got = playlist->cut (time)) != 0) { _editor.get_cut_buffer().add (what_we_got); - _session->add_command( new MementoCommand(*playlist.get(), &before, &playlist->get_state())); + + vector cmds; + + playlist->rdiff (cmds); + + for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { + _session->add_command (*c); + } + _session->add_command (new StatefulDiffCommand (playlist)); ret = true; } break; @@ -1402,7 +1412,14 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) case Clear: if ((what_we_got = playlist->cut (time)) != 0) { - _session->add_command( new MementoCommand(*playlist, &before, &playlist->get_state())); + vector cmds; + + playlist->rdiff (cmds); + + for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { + _session->add_command (*c); + } + _session->add_command (new StatefulDiffCommand (playlist)); what_we_got->release (); ret = true; } @@ -1432,9 +1449,9 @@ RouteTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size pos = session_frame_to_track_frame(pos, get_diskstream()->speed() ); } - XMLNode &before = playlist->get_state(); + playlist->clear_history (); playlist->paste (*p, pos, times); - _session->add_command( new MementoCommand(*playlist, &before, &playlist->get_state())); + _session->add_command (new StatefulDiffCommand (playlist)); return true; } diff --git a/gtk2_ardour/strip_silence_dialog.cc b/gtk2_ardour/strip_silence_dialog.cc index 56210c9373..4dd8f225f2 100644 --- a/gtk2_ardour/strip_silence_dialog.cc +++ b/gtk2_ardour/strip_silence_dialog.cc @@ -270,7 +270,7 @@ StripSilenceDialog::_detection_done (void* arg) bool StripSilenceDialog::detection_done () { - get_window()->set_cursor (Gdk::Cursor (Gdk::LEFT_PTR)); + // get_window()->set_cursor (Gdk::Cursor (Gdk::LEFT_PTR)); update_silence_rects (); return false; } @@ -287,22 +287,15 @@ StripSilenceDialog::detection_thread_work () { ARDOUR_UI::instance()->register_thread ("gui", pthread_self(), "silence", 32); - cerr << pthread_self() << ": thread exists\n"; - while (1) { run_lock.lock (); - cerr << pthread_self() << ": thread notes that its waiting\n"; thread_waiting->signal (); - cerr << pthread_self() << ": thread waits to run\n"; thread_run->wait (run_lock); - cerr << pthread_self() << ": silence thread active\n"; - if (thread_should_exit) { thread_waiting->signal (); run_lock.unlock (); - cerr << pthread_self() << ": silence thread exited\n"; break; } @@ -319,7 +312,6 @@ StripSilenceDialog::detection_thread_work () } } - cerr << pthread_self() << ": silence iteration done\n"; } return 0; @@ -349,9 +341,7 @@ StripSilenceDialog::start_silence_detection () pthread_create (&itt.thread, 0, StripSilenceDialog::_detection_thread_work, this); /* wait for it to get started */ - cerr << "Wait for new thread to be ready\n"; thread_waiting->wait (run_lock); - cerr << "\tits ready\n"; } else { @@ -361,11 +351,8 @@ StripSilenceDialog::start_silence_detection () current = 0; while (!itt.done) { - cerr << "tell existing thread to stop\n"; thread_run->signal (); - cerr << "wait for existing thread to stop\n"; thread_waiting->wait (run_lock); - cerr << "its stopped\n"; } } @@ -377,7 +364,6 @@ StripSilenceDialog::start_silence_detection () /* and start it up (again) */ - cerr << "signal thread to run again\n"; thread_run->signal (); /* change cursor */ @@ -398,4 +384,5 @@ StripSilenceDialog::stop_thread () thread_should_exit = true; thread_run->signal (); thread_waiting->wait (run_lock); + itt.thread = 0; } diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 3c79ec0ec4..bc896f35a4 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -35,6 +35,7 @@ #include "pbd/undo.h" #include "pbd/stateful.h" +#include "pbd/stateful_owner.h" #include "pbd/statefuldestructible.h" #include "pbd/sequence_property.h" @@ -83,6 +84,7 @@ class RegionListProperty : public PBD::SequenceProperty { public: typedef std::list > RegionList; @@ -97,6 +99,8 @@ class Playlist : public SessionObject bool set_property (const PBD::PropertyBase&); void update (const RegionListProperty::ChangeRecord&); + void clear_owned_history (); + void rdiff (std::vector&) const; PBD::PropertyList* property_factory (const XMLNode&) const; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 8d3b59427d..2b9ce7824f 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -26,9 +26,9 @@ #include #include "pbd/failed_constructor.h" +#include "pbd/stateful_diff_command.h" #include "pbd/stl_delete.h" #include "pbd/xml++.h" -#include "pbd/stacktrace.h" #include "ardour/debug.h" #include "ardour/playlist.h" @@ -2025,6 +2025,29 @@ Playlist::set_property (const PropertyBase& prop) return false; } +void +Playlist::rdiff (vector& cmds) const +{ + RegionLock rlock (const_cast (this)); + + for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->changed ()) { + StatefulDiffCommand* sdc = new StatefulDiffCommand (*i); + cmds.push_back (sdc); + } + } +} + +void +Playlist::clear_owned_history () +{ + RegionLock rlock (this); + + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + (*i)->clear_history (); + } +} + void Playlist::update (const RegionListProperty::ChangeRecord& change) { diff --git a/libs/pbd/pbd/property_basics.h b/libs/pbd/pbd/property_basics.h index c99fee1961..e818e36e90 100644 --- a/libs/pbd/pbd/property_basics.h +++ b/libs/pbd/pbd/property_basics.h @@ -95,6 +95,7 @@ public: const gchar*property_name () const { return g_quark_to_string (_property_id); } PropertyID property_id () const { return _property_id; } + bool changed() const { return _have_old; } bool operator==(PropertyID pid) const { return _property_id == pid; diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h index 93f353a095..5585b5c13b 100644 --- a/libs/pbd/pbd/stateful.h +++ b/libs/pbd/pbd/stateful.h @@ -71,6 +71,8 @@ class Stateful { void clear_history (); void diff (PropertyList&, PropertyList&) const; + bool changed() const; + /* create a property list from an XMLNode */ virtual PropertyList* property_factory(const XMLNode&) const { return 0; } diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc index 1bf8c17d83..89b22edd24 100644 --- a/libs/pbd/stateful.cc +++ b/libs/pbd/stateful.cc @@ -287,5 +287,16 @@ Stateful::resume_property_changes () send_change (what_changed); } +bool +Stateful::changed() const +{ + for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { + if (i->second->changed()) { + return true; + } + } + + return false; +} } // namespace PBD