goodbye to MementoCommand for playlists

git-svn-id: svn://localhost/ardour2/branches/3.0@6726 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-03-04 13:15:04 +00:00
parent c2c224727e
commit 6dde6c5a8f
8 changed files with 108 additions and 57 deletions

View File

@ -155,7 +155,13 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
boost::shared_ptr<Playlist> 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> 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<Playlist> pl;
@ -4057,8 +4052,8 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
nframes64_t first_position = max_frames;
set<PlaylistState, lt_playlist> freezelist;
pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
typedef set<boost::shared_ptr<Playlist> > 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<Playlist> pl = (*x)->region()->playlist();
if (pl) {
set<PlaylistState, lt_playlist>::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<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
(*pl).playlist->thaw ();
_session->add_command (new MementoCommand<Playlist>(*(*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>(*playlist, &before, &after));
vector<StatefulDiffCommand*> cmds;
playlist->rdiff (cmds);
for (vector<StatefulDiffCommand*>::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<StatefulDiffCommand*> cmds;
pl->rdiff (cmds);
cerr << "Shift generated " << cmds.size() << " sdc's\n";
_session->add_command (new MementoCommand<Playlist> (*pl, &before, &after));
for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
_session->add_command (*c);
}
_session->add_command (new StatefulDiffCommand (pl));
commit = true;
}

View File

@ -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 <gtkmm/menu.h>
#include <gtkmm/menuitem.h>
@ -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>(*playlist.get(), &before, &playlist->get_state()));
vector<StatefulDiffCommand*> cmds;
playlist->rdiff (cmds);
for (vector<StatefulDiffCommand*>::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>(*playlist, &before, &playlist->get_state()));
vector<StatefulDiffCommand*> cmds;
playlist->rdiff (cmds);
for (vector<StatefulDiffCommand*>::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>(*playlist, &before, &playlist->get_state()));
_session->add_command (new StatefulDiffCommand (playlist));
return true;
}

View File

@ -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;
}

View File

@ -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<std::list<boost::shared_
};
class Playlist : public SessionObject
, public PBD::StatefulOwner
, public boost::enable_shared_from_this<Playlist> {
public:
typedef std::list<boost::shared_ptr<Region> > 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<PBD::StatefulDiffCommand*>&) const;
PBD::PropertyList* property_factory (const XMLNode&) const;

View File

@ -26,9 +26,9 @@
#include <climits>
#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<StatefulDiffCommand*>& cmds) const
{
RegionLock rlock (const_cast<Playlist *> (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)
{

View File

@ -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;

View File

@ -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; }

View File

@ -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