diff options
author | Carl Hetherington <carl@carlh.net> | 2010-08-26 01:44:11 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-08-26 01:44:11 +0000 |
commit | c243a02c998f585295f2179657673e2cf0fa4428 (patch) | |
tree | 1a18ca901b5f7fb1270938e2fb62f7e2636400ef /libs/ardour | |
parent | df2fd9491904aba95e08e1e26552be609530ee83 (diff) |
Fix crossfade undo using the stateful diff system. Fixes #3257.
git-svn-id: svn://localhost/ardour2/branches/3.0@7694 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/audioplaylist.h | 35 | ||||
-rw-r--r-- | libs/ardour/ardour/crossfade.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 2 | ||||
-rw-r--r-- | libs/ardour/audio_playlist.cc | 75 | ||||
-rw-r--r-- | libs/ardour/crossfade.cc | 4 | ||||
-rw-r--r-- | libs/ardour/globals.cc | 3 | ||||
-rw-r--r-- | libs/ardour/playlist.cc | 44 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 8 | ||||
-rw-r--r-- | libs/ardour/wscript | 2 |
10 files changed, 156 insertions, 25 deletions
diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index aee5fb3f64..f2d60bce8b 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -33,12 +33,39 @@ class Region; class AudioRegion; class Source; +namespace Properties { + /* fake the type, since crossfades are handled by SequenceProperty which doesn't + care about such things. + */ + extern PBD::PropertyDescriptor<bool> crossfades; +} + +class AudioPlaylist; + +class CrossfadeListProperty : public PBD::SequenceProperty<std::list<boost::shared_ptr<Crossfade> > > +{ +public: + CrossfadeListProperty (AudioPlaylist &); + + void get_content_as_xml (boost::shared_ptr<Crossfade>, XMLNode &) const; + boost::shared_ptr<Crossfade> get_content_from_xml (XMLNode const &) const; + +private: + CrossfadeListProperty* clone () const; + CrossfadeListProperty* create () const; + + friend class AudioPlaylist; + /* we live and die with our playlist, no lifetime management needed */ + AudioPlaylist& _playlist; +}; + + class AudioPlaylist : public ARDOUR::Playlist { - public: +public: typedef std::list<boost::shared_ptr<Crossfade> > Crossfades; + static void make_property_quarks (); - public: AudioPlaylist (Session&, const XMLNode&, bool hidden = false); AudioPlaylist (Session&, std::string name, bool hidden = false); AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, std::string name, bool hidden = false); @@ -59,6 +86,8 @@ class AudioPlaylist : public ARDOUR::Playlist bool destroy_region (boost::shared_ptr<Region>); + void update (const CrossfadeListProperty::ChangeRecord &); + protected: /* playlist "callbacks" */ @@ -72,7 +101,7 @@ class AudioPlaylist : public ARDOUR::Playlist void remove_dependents (boost::shared_ptr<Region> region); private: - Crossfades _crossfades; + CrossfadeListProperty _crossfades; Crossfades _pending_xfade_adds; void crossfade_invalidated (boost::shared_ptr<Region>); diff --git a/libs/ardour/ardour/crossfade.h b/libs/ardour/ardour/crossfade.h index 4c75a0226b..2ce504eacf 100644 --- a/libs/ardour/ardour/crossfade.h +++ b/libs/ardour/ardour/crossfade.h @@ -73,7 +73,7 @@ class Crossfade : public ARDOUR::AudioRegion /* the usual XML constructor */ - Crossfade (const Playlist&, XMLNode&); + Crossfade (const Playlist&, XMLNode const &); virtual ~Crossfade(); static void make_property_quarks (); diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 6473211126..a1a7bb752a 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -64,8 +64,8 @@ class RegionListProperty : public PBD::SequenceProperty<std::list<boost::shared_ RegionListProperty (Playlist&); RegionListProperty* clone () const; - - boost::shared_ptr<Region> lookup_id (const PBD::ID& id) const; + void get_content_as_xml (boost::shared_ptr<Region>, XMLNode &) const; + boost::shared_ptr<Region> get_content_from_xml (XMLNode const &) const; private: RegionListProperty* create () const; @@ -90,7 +90,7 @@ public: void update (const RegionListProperty::ChangeRecord&); void clear_owned_changes (); - void rdiff (std::vector<PBD::StatefulDiffCommand*>&) const; + void rdiff (std::vector<Command*>&) const; boost::shared_ptr<Region> region_by_id (const PBD::ID&) const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c408714c94..75b9fb1831 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -680,6 +680,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi _current_trans.top()->add_command (cmd); } + void add_commands (std::vector<Command*> const & cmds); + std::map<PBD::ID,PBD::StatefulDestructible*> registry; // these commands are implemented in libs/ardour/session_command.cc diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index cfc5a4028a..2ac3edff80 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -21,7 +21,6 @@ #include <cstdlib> - #include "ardour/types.h" #include "ardour/debug.h" #include "ardour/configuration.h" @@ -38,14 +37,70 @@ using namespace ARDOUR; using namespace std; using namespace PBD; +namespace ARDOUR { + namespace Properties { + PBD::PropertyDescriptor<bool> crossfades; + } +} + +void +AudioPlaylist::make_property_quarks () +{ + Properties::crossfades.property_id = g_quark_from_static_string (X_("crossfades")); + DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for crossfades = %1\n", Properties::crossfades.property_id)); +} + +CrossfadeListProperty::CrossfadeListProperty (AudioPlaylist& pl) + : SequenceProperty<std::list<boost::shared_ptr<Crossfade> > > (Properties::crossfades.property_id, boost::bind (&AudioPlaylist::update, &pl, _1)) + , _playlist (pl) +{ + +} + + +CrossfadeListProperty * +CrossfadeListProperty::create () const +{ + return new CrossfadeListProperty (_playlist); +} + +CrossfadeListProperty * +CrossfadeListProperty::clone () const +{ + return new CrossfadeListProperty (*this); +} + +void +CrossfadeListProperty::get_content_as_xml (boost::shared_ptr<Crossfade> xfade, XMLNode & node) const +{ + /* Crossfades are not written to any state when they are no + longer in use, so we must write their state here. + */ + + XMLNode& c = xfade->get_state (); + node.add_child_nocopy (c); +} + +boost::shared_ptr<Crossfade> +CrossfadeListProperty::get_content_from_xml (XMLNode const & node) const +{ + XMLNodeList const c = node.children (); + assert (c.size() == 1); + return boost::shared_ptr<Crossfade> (new Crossfade (_playlist, *c.front())); +} + + AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden) : Playlist (session, node, DataType::AUDIO, hidden) + , _crossfades (*this) { #ifndef NDEBUG const XMLProperty* prop = node.property("type"); assert(!prop || DataType(prop->value()) == DataType::AUDIO); #endif + add_property (_crossfades); + in_set_state++; set_state (node, Stateful::loading_state_version); in_set_state--; @@ -53,12 +108,17 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden) : Playlist (session, name, DataType::AUDIO, hidden) + , _crossfades (*this) { + add_property (_crossfades); } AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden) : Playlist (other, name, hidden) + , _crossfades (*this) { + add_property (_crossfades); + RegionList::const_iterator in_o = other->regions.begin(); RegionList::iterator in_n = regions.begin(); @@ -99,7 +159,10 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, stri AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden) : Playlist (other, start, cnt, name, hidden) + , _crossfades (*this) { + add_property (_crossfades); + /* this constructor does NOT notify others (session) */ } @@ -795,3 +858,13 @@ AudioPlaylist::foreach_crossfade (boost::function<void (boost::shared_ptr<Crossf s (*i); } } + +void +AudioPlaylist::update (const CrossfadeListProperty::ChangeRecord& change) +{ + for (CrossfadeListProperty::ChangeContainer::const_iterator i = change.added.begin(); i != change.added.end(); ++i) { + add_crossfade (*i); + } + + /* don't remove crossfades here; they will be dealt with by the dependency code */ +} diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index 601ea86f6b..eb1148fa2c 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -124,7 +124,7 @@ Crossfade::Crossfade (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioR initialize (); } -Crossfade::Crossfade (const Playlist& playlist, XMLNode& node) +Crossfade::Crossfade (const Playlist& playlist, XMLNode const & node) : AudioRegion (playlist.session(), 0, 0, "unnamed crossfade") , CROSSFADE_DEFAULT_PROPERTIES , _fade_in (Evoral::Parameter(FadeInAutomation)) // linear (gain coefficient) => -inf..+6dB @@ -132,7 +132,7 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node) { boost::shared_ptr<Region> r; - XMLProperty* prop; + XMLProperty const * prop; LocaleGuard lg (X_("POSIX")); /* we have to find the in/out regions before we can do anything else */ diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 2ecea550b5..0e12883d82 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -69,7 +69,7 @@ #include "ardour/debug.h" #include "ardour/filesystem_paths.h" #include "ardour/mix.h" -#include "ardour/playlist.h" +#include "ardour/audioplaylist.h" #include "ardour/plugin_manager.h" #include "ardour/process_thread.h" #include "ardour/profile.h" @@ -251,6 +251,7 @@ ARDOUR::init (bool use_vst, bool try_optimization) AudioRegion::make_property_quarks (); RouteGroup::make_property_quarks (); Playlist::make_property_quarks (); + AudioPlaylist::make_property_quarks (); /* this is a useful ready to use PropertyChange that many things need to check. This avoids having to compose diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 93a4d520e8..1b2d64baba 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -110,28 +110,46 @@ RegionListProperty::RegionListProperty (Playlist& pl) : SequenceProperty<std::list<boost::shared_ptr<Region> > > (Properties::regions.property_id, boost::bind (&Playlist::update, &pl, _1)) , _playlist (pl) { + } -boost::shared_ptr<Region> -RegionListProperty::lookup_id (const ID& id) const +RegionListProperty * +RegionListProperty::clone () const { - boost::shared_ptr<Region> ret = _playlist.region_by_id (id); - - if (!ret) { - ret = RegionFactory::region_by_id (id); - } + return new RegionListProperty (*this); +} - return ret; +RegionListProperty * +RegionListProperty::create () const +{ + return new RegionListProperty (_playlist); } -RegionListProperty* RegionListProperty::clone () const +void +RegionListProperty::get_content_as_xml (boost::shared_ptr<Region> region, XMLNode & node) const { - return new RegionListProperty (*this); + /* All regions (even those which are deleted) have their state saved by other + code, so we can just store ID here. + */ + + node.add_property ("id", region->id().to_s ()); } -RegionListProperty* RegionListProperty::create () const +boost::shared_ptr<Region> +RegionListProperty::get_content_from_xml (XMLNode const & node) const { - return new RegionListProperty (_playlist); + XMLProperty const * prop = node.property ("id"); + assert (prop); + + PBD::ID id (prop->value ()); + + boost::shared_ptr<Region> ret = _playlist.region_by_id (id); + + if (!ret) { + ret = RegionFactory::region_by_id (id); + } + + return ret; } Playlist::Playlist (Session& sess, string nom, DataType type, bool hide) @@ -2100,7 +2118,7 @@ Playlist::mark_session_dirty () } void -Playlist::rdiff (vector<StatefulDiffCommand*>& cmds) const +Playlist::rdiff (vector<Command*>& cmds) const { RegionLock rlock (const_cast<Playlist *> (this)); Stateful::rdiff (cmds); diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 31282a210f..225b7c1909 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2313,6 +2313,14 @@ Session::finish_reversible_command (UndoTransaction& ut) } void +Session::add_commands (vector<Command*> const & cmds) +{ + for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) { + add_command (*i); + } +} + +void Session::begin_reversible_command(const string& name) { UndoTransaction* trans = new UndoTransaction(); diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 051054c9a7..f877f3c3be 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -286,7 +286,7 @@ def build(bld): obj.includes = ['.', '../surfaces/control_protocol', '..'] obj.name = 'libardour' obj.target = 'ardour' - obj.uselib = 'GLIBMM GTHREAD AUBIO SIGCPP XML UUID JACK SNDFILE SAMPLERATE LRDF OSX COREAUDIO' + obj.uselib = 'GLIBMM GTHREAD AUBIO SIGCPP XML UUID JACK SNDFILE SAMPLERATE LRDF OSX COREAUDIO CURL DL' obj.uselib_local = 'libpbd libmidipp libevoral libvamphost libvampplugin libtaglib librubberband libaudiographer' obj.vnum = LIBARDOUR_LIB_VERSION obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3') |