diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-12-14 14:15:43 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-12-14 14:15:43 +0000 |
commit | af12adb34f62dc82f694a03ea3b2a6c99ba426ef (patch) | |
tree | 263ecb66462ee561c9e3741799541f0233f82e21 /libs | |
parent | c0924280e9be867253a1b93eb7274e0eb955de5f (diff) |
use shared_ptr for all Playlist handling; cleanup works again
git-svn-id: svn://localhost/ardour2/trunk@1209 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
28 files changed, 509 insertions, 367 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 5c24697972..7c00885228 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -90,9 +90,9 @@ class AudioDiskstream : public Diskstream } } - AudioPlaylist* audio_playlist () { return dynamic_cast<AudioPlaylist*>(_playlist); } + boost::shared_ptr<AudioPlaylist> audio_playlist () { return boost::dynamic_pointer_cast<AudioPlaylist>(_playlist); } - int use_playlist (Playlist *); + int use_playlist (boost::shared_ptr<Playlist>); int use_new_playlist (); int use_copy_playlist (); diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 383ec73531..2f1b127c5a 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -42,8 +42,10 @@ class AudioPlaylist : public ARDOUR::Playlist public: AudioPlaylist (Session&, const XMLNode&, bool hidden = false); AudioPlaylist (Session&, string name, bool hidden = false); - AudioPlaylist (const AudioPlaylist&, string name, bool hidden = false); - AudioPlaylist (const AudioPlaylist&, nframes_t start, nframes_t cnt, string name, bool hidden = false); + AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, string name, bool hidden = false); + AudioPlaylist (boost::shared_ptr<const AudioPlaylist>, nframes_t start, nframes_t cnt, string name, bool hidden = false); + + ~AudioPlaylist (); /* public should use unref() */ void clear (bool with_signals=true); @@ -70,9 +72,6 @@ class AudioPlaylist : public ARDOUR::Playlist void check_dependents (boost::shared_ptr<Region> region, bool norefresh); void remove_dependents (boost::shared_ptr<Region> region); - protected: - ~AudioPlaylist (); /* public should use unref() */ - private: Crossfades _crossfades; /* xfades currently in use */ Crossfades _pending_xfade_adds; diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 0d45d20c0d..7a88655afe 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -137,7 +137,7 @@ class AudioRegion : public Region void resume_fade_in (); void resume_fade_out (); - void set_playlist (Playlist *); + void set_playlist (boost::weak_ptr<Playlist>); private: friend class RegionFactory; diff --git a/libs/ardour/ardour/crossfade.h b/libs/ardour/ardour/crossfade.h index d29ba47056..0422698c5e 100644 --- a/libs/ardour/ardour/crossfade.h +++ b/libs/ardour/ardour/crossfade.h @@ -64,12 +64,13 @@ class Crossfade : public PBD::StatefulDestructible /* copy constructor to copy a crossfade with new regions. used (for example) - when a playlist copy is made */ + when a playlist copy is made + */ Crossfade (const Crossfade &, boost::shared_ptr<ARDOUR::AudioRegion>, boost::shared_ptr<ARDOUR::AudioRegion>); /* the usual XML constructor */ - Crossfade (const ARDOUR::Playlist&, XMLNode&); + Crossfade (const Playlist&, XMLNode&); virtual ~Crossfade(); bool operator== (const ARDOUR::Crossfade&); diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 6e0725033a..3f30cd9f0e 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -104,9 +104,9 @@ class IO; void set_speed (double); void non_realtime_set_speed (); - Playlist* playlist () { return _playlist; } + boost::shared_ptr<Playlist> playlist () { return _playlist; } - virtual int use_playlist (Playlist *); + virtual int use_playlist (boost::shared_ptr<Playlist>); virtual int use_new_playlist () = 0; virtual int use_copy_playlist () = 0; @@ -206,7 +206,7 @@ class IO; virtual void playlist_changed (Change); virtual void playlist_modified (); - virtual void playlist_deleted (Playlist*); + virtual void playlist_deleted (boost::weak_ptr<Playlist>); virtual void finish_capture (bool rec_monitors_input) = 0; virtual void transport_stopped (struct tm&, time_t, bool abort) = 0; @@ -246,7 +246,8 @@ class IO; ARDOUR::Session& _session; ARDOUR::IO* _io; uint32_t _n_channels; - Playlist* _playlist; + + boost::shared_ptr<Playlist> _playlist; mutable gint _record_enabled; double _visible_speed; @@ -300,7 +301,6 @@ class IO; sigc::connection ports_created_c; sigc::connection plmod_connection; - sigc::connection plstate_connection; sigc::connection plgone_connection; unsigned char _flags; diff --git a/libs/ardour/ardour/named_selection.h b/libs/ardour/ardour/named_selection.h index 87b71e73ff..fd5777ccf6 100644 --- a/libs/ardour/ardour/named_selection.h +++ b/libs/ardour/ardour/named_selection.h @@ -23,6 +23,7 @@ #include <string> #include <list> +#include <boost/shared_ptr.hpp> #include <pbd/stateful.h> @@ -35,12 +36,12 @@ class Playlist; struct NamedSelection : public Stateful { - NamedSelection (std::string, std::list<Playlist*>&); + NamedSelection (std::string, std::list<boost::shared_ptr<Playlist> >&); NamedSelection (Session&, const XMLNode&); virtual ~NamedSelection (); std::string name; - std::list<Playlist*> playlists; + std::list<boost::shared_ptr<Playlist> > playlists; XMLNode& get_state (void); diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 7b9ae718bc..50282f3331 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -26,6 +26,7 @@ #include <map> #include <list> #include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> #include <sys/stat.h> @@ -46,21 +47,25 @@ namespace ARDOUR { class Session; class Region; -class Playlist : public PBD::StatefulDestructible { +class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_from_this<Playlist> { public: typedef list<boost::shared_ptr<Region> > RegionList; Playlist (Session&, const XMLNode&, bool hidden = false); Playlist (Session&, string name, bool hidden = false); - Playlist (const Playlist&, string name, bool hidden = false); - Playlist (const Playlist&, nframes_t start, nframes_t cnt, string name, bool hidden = false); + Playlist (boost::shared_ptr<const Playlist>, string name, bool hidden = false); + Playlist (boost::shared_ptr<const Playlist>, nframes_t start, nframes_t cnt, string name, bool hidden = false); + + virtual ~Playlist (); + + void set_region_ownership (); virtual void clear (bool with_signals=true); virtual void dump () const; - void ref(); - void unref(); - uint32_t refcnt() const { return _refcnt; } + void use(); + void release(); + bool used () const { return _refcnt != 0; } std::string name() const { return _name; } void set_name (std::string str); @@ -89,9 +94,9 @@ class Playlist : public PBD::StatefulDestructible { void duplicate (boost::shared_ptr<Region>, nframes_t position, float times); void nudge_after (nframes_t start, nframes_t distance, bool forwards); - Playlist* cut (list<AudioRange>&, bool result_is_hidden = true); - Playlist* copy (list<AudioRange>&, bool result_is_hidden = true); - int paste (Playlist&, nframes_t position, float times); + boost::shared_ptr<Playlist> cut (list<AudioRange>&, bool result_is_hidden = true); + boost::shared_ptr<Playlist> copy (list<AudioRange>&, bool result_is_hidden = true); + int paste (boost::shared_ptr<Playlist>, nframes_t position, float times); RegionList* regions_at (nframes_t frame); RegionList* regions_touched (nframes_t start, nframes_t end); @@ -106,14 +111,11 @@ class Playlist : public PBD::StatefulDestructible { int set_state (const XMLNode&); XMLNode& get_template (); - sigc::signal<void,Playlist*,bool> InUse; - sigc::signal<void> Modified; - sigc::signal<void> NameChanged; - sigc::signal<void> LengthChanged; - sigc::signal<void> LayeringChanged; - sigc::signal<void> StatePushed; - - static sigc::signal<void,Playlist*> PlaylistCreated; + sigc::signal<void,bool> InUse; + sigc::signal<void> Modified; + sigc::signal<void> NameChanged; + sigc::signal<void> LengthChanged; + sigc::signal<void> LayeringChanged; static string bump_name (string old_name, Session&); static string bump_name_once (string old_name); @@ -139,7 +141,6 @@ class Playlist : public PBD::StatefulDestructible { protected: friend class Session; - virtual ~Playlist (); /* members of the public use unref() */ protected: struct RegionLock { @@ -240,26 +241,23 @@ class Playlist : public PBD::StatefulDestructible { boost::shared_ptr<Region> region_by_id (PBD::ID); - void add_region_internal (boost::shared_ptr<Region>, nframes_t position, bool delay_sort = false); - - int remove_region_internal (boost::shared_ptr<Region>, bool delay_sort = false); + void add_region_internal (boost::shared_ptr<Region>, nframes_t position); + + int remove_region_internal (boost::shared_ptr<Region>); RegionList *find_regions_at (nframes_t frame); void copy_regions (RegionList&) const; void partition_internal (nframes_t start, nframes_t end, bool cutting, RegionList& thawlist); nframes_t _get_maximum_extent() const; - Playlist* cut_copy (Playlist* (Playlist::*pmf)(nframes_t, nframes_t, bool), - list<AudioRange>& ranges, bool result_is_hidden); - Playlist *cut (nframes_t start, nframes_t cnt, bool result_is_hidden); - Playlist *copy (nframes_t start, nframes_t cnt, bool result_is_hidden); + boost::shared_ptr<Playlist> cut_copy (boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t, nframes_t, bool), + list<AudioRange>& ranges, bool result_is_hidden); + boost::shared_ptr<Playlist> cut (nframes_t start, nframes_t cnt, bool result_is_hidden); + boost::shared_ptr<Playlist> copy (nframes_t start, nframes_t cnt, bool result_is_hidden); int move_region_to_layer (layer_t, boost::shared_ptr<Region> r, int dir); void relayer (); - - static Playlist* copyPlaylist (const Playlist&, nframes_t start, nframes_t length, - string name, bool result_is_hidden); void unset_freeze_parent (Playlist*); void unset_freeze_child (Playlist*); diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index b27fef48a3..f0262777f3 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -162,9 +162,8 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro virtual uint32_t read_data_count() const { return _read_data_count; } - ARDOUR::Playlist* playlist() const { return _playlist; } - - virtual void set_playlist (ARDOUR::Playlist*); + boost::shared_ptr<ARDOUR::Playlist> playlist() const { return _playlist.lock(); } + virtual void set_playlist (boost::weak_ptr<ARDOUR::Playlist>); /* serialization */ @@ -217,7 +216,7 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro mutable RegionEditState _first_edit; int _frozen; Glib::Mutex lock; - ARDOUR::Playlist* _playlist; + boost::weak_ptr<ARDOUR::Playlist> _playlist; mutable uint32_t _read_data_count; // modified in read() Change pending_changed; uint64_t _last_layer_op; // timestamp diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 55376bcd77..6ce7f75832 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -604,8 +604,7 @@ class Session : public PBD::StatefulDestructible this playlist. */ - sigc::signal<int,ARDOUR::Playlist*> AskAboutPlaylistDeletion; - + sigc::signal<int,boost::shared_ptr<ARDOUR::Playlist> > AskAboutPlaylistDeletion; /* handlers should return !0 for use pending state, 0 for ignore it. @@ -613,24 +612,21 @@ class Session : public PBD::StatefulDestructible static sigc::signal<int> AskAboutPendingState; - sigc::signal<void,boost::shared_ptr<Source> > SourceAdded; - sigc::signal<void,boost::shared_ptr<Source> > SourceRemoved; - boost::shared_ptr<AudioFileSource> create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive); boost::shared_ptr<Source> source_by_id (const PBD::ID&); /* playlist management */ - Playlist* playlist_by_name (string name); - void add_playlist (Playlist *); - sigc::signal<void,Playlist*> PlaylistAdded; - sigc::signal<void,Playlist*> PlaylistRemoved; + boost::shared_ptr<Playlist> playlist_by_name (string name); + void add_playlist (boost::shared_ptr<Playlist>); + sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistAdded; + sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistRemoved; uint32_t n_playlists() const; - template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *)); - void get_playlists (std::vector<Playlist*>&); + template<class T> void foreach_playlist (T *obj, void (T::*func)(boost::shared_ptr<Playlist>)); + void get_playlists (std::vector<boost::shared_ptr<Playlist> >&); /* named selections */ @@ -1464,19 +1460,19 @@ class Session : public PBD::StatefulDestructible /* PLAYLISTS */ mutable Glib::Mutex playlist_lock; - typedef set<Playlist *> PlaylistList; + typedef set<boost::shared_ptr<Playlist> > PlaylistList; PlaylistList playlists; PlaylistList unused_playlists; int load_playlists (const XMLNode&); int load_unused_playlists (const XMLNode&); - void remove_playlist (Playlist *); - void track_playlist (Playlist *, bool); + void remove_playlist (boost::weak_ptr<Playlist>); + void track_playlist (bool, boost::weak_ptr<Playlist>); - Playlist *playlist_factory (string name); - Playlist *XMLPlaylistFactory (const XMLNode&); + boost::shared_ptr<Playlist> playlist_factory (string name); + boost::shared_ptr<Playlist> XMLPlaylistFactory (const XMLNode&); - void playlist_length_changed (Playlist *); + void playlist_length_changed (); void diskstream_playlist_changed (boost::shared_ptr<Diskstream>); /* NAMED SELECTIONS */ diff --git a/libs/ardour/ardour/session_playlist.h b/libs/ardour/ardour/session_playlist.h index 6f1b8dbd12..20cf4d8f2e 100644 --- a/libs/ardour/ardour/session_playlist.h +++ b/libs/ardour/ardour/session_playlist.h @@ -27,7 +27,7 @@ namespace ARDOUR { template<class T> void -Session::foreach_playlist (T *obj, void (T::*func)(Playlist *)) +Session::foreach_playlist (T *obj, void (T::*func)(boost::shared_ptr<Playlist>)) { Glib::Mutex::Lock lm (playlist_lock); for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); i++) { diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 15e814e946..91b856894d 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -54,8 +54,8 @@ class Source : public PBD::StatefulDestructible void use () { _in_use++; } void disuse () { if (_in_use) { _in_use--; } } - void add_playlist (ARDOUR::Playlist*); - void remove_playlist (ARDOUR::Playlist*); + void add_playlist (boost::shared_ptr<ARDOUR::Playlist>); + void remove_playlist (boost::weak_ptr<ARDOUR::Playlist>); uint32_t used() const; @@ -64,7 +64,7 @@ class Source : public PBD::StatefulDestructible string _name; time_t _timestamp; - std::set<ARDOUR::Playlist*> _playlists; + std::set<boost::shared_ptr<ARDOUR::Playlist> > _playlists; private: uint32_t _in_use; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index a2b0b9b90e..9c99ecfd25 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -120,13 +120,12 @@ class Track : public Route struct FreezeRecord { FreezeRecord() - : playlist(0) - , have_mementos(false) + : have_mementos(false) {} ~FreezeRecord(); - Playlist* playlist; + boost::shared_ptr<Playlist> playlist; vector<FreezeRecordInsertInfo*> insert_info; bool have_mementos; FreezeState state; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 5f682789ef..e30c683d8e 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -46,6 +46,7 @@ #include <ardour/send.h> #include <ardour/region_factory.h> #include <ardour/audioplaylist.h> +#include <ardour/playlist_factory.h> #include <ardour/cycle_timer.h> #include <ardour/audioregion.h> #include <ardour/source_factory.h> @@ -286,15 +287,13 @@ AudioDiskstream::get_input_sources () int AudioDiskstream::find_and_use_playlist (const string& name) { - Playlist* pl; - AudioPlaylist* playlist; + boost::shared_ptr<AudioPlaylist> playlist; - if ((pl = _session.playlist_by_name (name)) == 0) { - playlist = new AudioPlaylist(_session, name); - pl = playlist; + if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist> (_session.playlist_by_name (name))) == 0) { + playlist = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (_session, name)); } - if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) { + if (!playlist) { error << string_compose(_("AudioDiskstream: Playlist \"%1\" isn't an audio playlist"), name) << endmsg; return -1; } @@ -303,9 +302,9 @@ AudioDiskstream::find_and_use_playlist (const string& name) } int -AudioDiskstream::use_playlist (Playlist* playlist) +AudioDiskstream::use_playlist (boost::shared_ptr<Playlist> playlist) { - assert(dynamic_cast<AudioPlaylist*>(playlist)); + assert(boost::dynamic_pointer_cast<AudioPlaylist>(playlist)); Diskstream::use_playlist(playlist); @@ -316,7 +315,7 @@ int AudioDiskstream::use_new_playlist () { string newname; - AudioPlaylist* playlist; + boost::shared_ptr<AudioPlaylist> playlist; if (!in_set_state && destructive()) { return 0; @@ -328,9 +327,11 @@ AudioDiskstream::use_new_playlist () newname = Playlist::bump_name (_name, _session); } - if ((playlist = new AudioPlaylist (_session, newname, hidden())) != 0) { + if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (_session, newname, hidden()))) != 0) { + playlist->set_orig_diskstream_id (id()); return use_playlist (playlist); + } else { return -1; } @@ -351,11 +352,11 @@ AudioDiskstream::use_copy_playlist () } string newname; - AudioPlaylist* playlist; + boost::shared_ptr<AudioPlaylist> playlist; newname = Playlist::bump_name (_playlist->name(), _session); - if ((playlist = new AudioPlaylist (*audio_playlist(), newname)) != 0) { + if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist>(PlaylistFactory::create (audio_playlist(), newname))) != 0) { playlist->set_orig_diskstream_id (id()); return use_playlist (playlist); } else { diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index dd0f313fc4..0c35599332 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -45,39 +45,31 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden in_set_state++; set_state (node); in_set_state--; - - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } } AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden) : Playlist (session, name, hidden) { - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } - } -AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden) +AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, string name, bool hidden) : Playlist (other, name, hidden) { - RegionList::const_iterator in_o = other.regions.begin(); + RegionList::const_iterator in_o = other->regions.begin(); RegionList::iterator in_n = regions.begin(); - while (in_o != other.regions.end()) { + while (in_o != other->regions.end()) { boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*in_o); // We look only for crossfades which begin with the current region, so we don't get doubles - for (list<Crossfade *>::const_iterator xfades = other._crossfades.begin(); xfades != other._crossfades.end(); ++xfades) { + for (list<Crossfade *>::const_iterator xfades = other->_crossfades.begin(); xfades != other->_crossfades.end(); ++xfades) { if ((*xfades)->in() == ar) { // We found one! Now copy it! - RegionList::const_iterator out_o = other.regions.begin(); + RegionList::const_iterator out_o = other->regions.begin(); RegionList::const_iterator out_n = regions.begin(); - while (out_o != other.regions.end()) { + while (out_o != other->regions.end()) { boost::shared_ptr<AudioRegion>ar2 = boost::dynamic_pointer_cast<AudioRegion>(*out_o); @@ -99,13 +91,9 @@ AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidd in_o++; in_n++; } - - if (!hidden) { - PlaylistCreated (this); /* EMIT SIGNAL */ - } } -AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, nframes_t start, nframes_t cnt, string name, bool hidden) +AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden) : Playlist (other, start, cnt, name, hidden) { /* this constructor does NOT notify others (session) */ @@ -658,7 +646,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr<Region> region) x = xtmp; } - region->set_playlist (0); + region->set_playlist (boost::shared_ptr<Playlist>()); } for (c = _crossfades.begin(); c != _crossfades.end(); ) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index b5a18073f4..33bb478a1c 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -32,6 +32,7 @@ #include <ardour/route_group_specialized.h> #include <ardour/insert.h> #include <ardour/audioplaylist.h> +#include <ardour/playlist_factory.h> #include <ardour/panner.h> #include <ardour/utils.h> @@ -395,11 +396,11 @@ AudioTrack::set_state_part_two () _freeze_record.insert_info.clear (); if ((prop = fnode->property (X_("playlist"))) != 0) { - Playlist* pl = _session.playlist_by_name (prop->value()); + boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value()); if (pl) { - _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl); + _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl); } else { - _freeze_record.playlist = 0; + _freeze_record.playlist.reset (); _freeze_record.state = NoFreeze; return; } @@ -685,8 +686,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, nframes_t st Glib::RWLock::ReaderLock rlock (redirect_lock); - // FIXME - AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream->playlist()); + boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist()); assert(apl); if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) { @@ -791,12 +791,12 @@ AudioTrack::freeze (InterThreadInfo& itt) { vector<boost::shared_ptr<AudioSource> > srcs; string new_playlist_name; - Playlist* new_playlist; + boost::shared_ptr<Playlist> new_playlist; string dir; string region_name; boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream(); - if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream->playlist())) == 0) { + if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) { return; } @@ -853,7 +853,7 @@ AudioTrack::freeze (InterThreadInfo& itt) } } - new_playlist = new AudioPlaylist (_session, new_playlist_name, false); + new_playlist = PlaylistFactory::create (_session, new_playlist_name, false); region_name = new_playlist_name; /* create a new region from all filesources, keep it private */ @@ -868,7 +868,7 @@ AudioTrack::freeze (InterThreadInfo& itt) new_playlist->set_frozen (true); region->set_locked (true); - diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist)); + diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist)); diskstream->set_record_enabled (false); _freeze_record.state = Frozen; @@ -900,7 +900,7 @@ AudioTrack::unfreeze () } } - _freeze_record.playlist = 0; + _freeze_record.playlist.reset (); } _freeze_record.state = UnFrozen; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 1be0f66125..32bd6cd685 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -306,9 +306,11 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) AudioRegion::~AudioRegion () { - if (_playlist) { + boost::shared_ptr<Playlist> pl (playlist()); + + if (pl) { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { - (*i)->remove_playlist (_playlist); + (*i)->remove_playlist (pl); } } @@ -1159,11 +1161,13 @@ AudioRegion::exportme (Session& session, AudioExportSpecification& spec) boost::shared_ptr<Region> AudioRegion::get_parent() const { - if (_playlist) { + boost::shared_ptr<Playlist> pl (playlist()); + + if (pl) { boost::shared_ptr<AudioRegion> ar; boost::shared_ptr<AudioRegion const> grrr2 = boost::dynamic_pointer_cast<AudioRegion const> (shared_from_this()); - if (grrr2 && (ar = _playlist->session().find_whole_file_parent (grrr2))) { + if (grrr2 && (ar = pl->session().find_whole_file_parent (grrr2))) { return boost::static_pointer_cast<Region> (ar); } } @@ -1174,12 +1178,14 @@ AudioRegion::get_parent() const void AudioRegion::set_scale_amplitude (gain_t g) { + boost::shared_ptr<Playlist> pl (playlist()); + _scale_amplitude = g; /* tell the diskstream we're in */ - - if (_playlist) { - _playlist->Modified(); + + if (pl) { + pl->Modified(); } /* tell everybody else */ @@ -1246,8 +1252,10 @@ AudioRegion::normalize_to (float target_dB) /* tell the diskstream we're in */ - if (_playlist) { - _playlist->Modified(); + boost::shared_ptr<Playlist> pl (playlist()); + + if (pl) { + pl->Modified(); } /* tell everybody else */ @@ -1330,31 +1338,32 @@ AudioRegion::source_offset_changed () } void -AudioRegion::set_playlist (Playlist* pl) +AudioRegion::set_playlist (boost::weak_ptr<Playlist> wpl) { - if (pl == _playlist) { + boost::shared_ptr<Playlist> old_playlist = (_playlist.lock()); + boost::shared_ptr<Playlist> pl (wpl.lock()); + + if (old_playlist == pl) { return; } - Playlist* old_playlist = _playlist; - - Region::set_playlist (pl); + Region::set_playlist (wpl); if (pl) { if (old_playlist) { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { - (*i)->remove_playlist (old_playlist); - (*i)->add_playlist (_playlist); + (*i)->remove_playlist (_playlist); + (*i)->add_playlist (pl); } } else { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { - (*i)->add_playlist (_playlist); + (*i)->add_playlist (pl); } } } else { if (old_playlist) { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { - (*i)->remove_playlist (old_playlist); + (*i)->remove_playlist (_playlist); } } } diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index 0c5e8bc6a2..ce6bcd4143 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -75,7 +75,7 @@ AudioPlaylist& Auditioner::prepare_playlist () { // FIXME auditioner is still audio-only - AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(_diskstream->playlist()); + boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(_diskstream->playlist()); assert(apl); apl->clear (); diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 7b3db9aab4..62c3fffeb6 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -71,14 +71,12 @@ sigc::signal<void> Diskstream::DiskUnderrun; Diskstream::Diskstream (Session &sess, const string &name, Flag flag) : _name (name) , _session (sess) - , _playlist(NULL) { init (flag); } Diskstream::Diskstream (Session& sess, const XMLNode& node) : _session (sess) - , _playlist(NULL) { init (Recordable); } @@ -133,7 +131,7 @@ Diskstream::~Diskstream () //Glib::Mutex::Lock lm (state_lock); if (_playlist) - _playlist->unref (); + _playlist->release (); } void @@ -307,7 +305,7 @@ Diskstream::set_speed (double sp) } int -Diskstream::use_playlist (Playlist* playlist) +Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist) { { Glib::Mutex::Lock lm (state_lock); @@ -316,23 +314,22 @@ Diskstream::use_playlist (Playlist* playlist) return 0; } - plstate_connection.disconnect(); plmod_connection.disconnect (); plgone_connection.disconnect (); if (_playlist) { - _playlist->unref(); + _playlist->release(); } _playlist = playlist; - _playlist->ref(); + _playlist->use(); if (!in_set_state && recordable()) { reset_write_sources (false); } plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified)); - plgone_connection = _playlist->GoingAway.connect (bind (mem_fun (*this, &Diskstream::playlist_deleted), _playlist)); + plgone_connection = _playlist->GoingAway.connect (bind (mem_fun (*this, &Diskstream::playlist_deleted), boost::weak_ptr<Playlist>(_playlist))); } if (!overwrite_queued) { @@ -362,14 +359,21 @@ Diskstream::playlist_modified () } void -Diskstream::playlist_deleted (Playlist* pl) +Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl) { - /* this catches an ordering issue with session destruction. playlists - are destroyed before diskstreams. we have to invalidate any handles - we have to the playlist. - */ + boost::shared_ptr<Playlist> pl (wpl.lock()); - _playlist = 0; + if (pl == _playlist) { + + /* this catches an ordering issue with session destruction. playlists + are destroyed before diskstreams. we have to invalidate any handles + we have to the playlist. + */ + + if (_playlist) { + _playlist.reset (); + } + } } int diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 2d409e11f7..0d0a73c7a0 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -111,14 +111,14 @@ Session::import_audiofile (import_status& status) do { if (info.channels == 2) { if (n == 0) { - snprintf (buf, sizeof(buf), "%s%s-L.wav", sounds_dir.c_str(), basepath.c_str()); + snprintf (buf, sizeof(buf), "%s/%s-L.wav", sounds_dir.c_str(), basepath.c_str()); } else { - snprintf (buf, sizeof(buf), "%s%s-R.wav", sounds_dir.c_str(), basepath.c_str()); + snprintf (buf, sizeof(buf), "%s/%s-R.wav", sounds_dir.c_str(), basepath.c_str()); } } else if (info.channels > 1) { - snprintf (buf, sizeof(buf), "%s%s-c%lu.wav", sounds_dir.c_str(), basepath.c_str(), n+1); + snprintf (buf, sizeof(buf), "%s/%s-c%lu.wav", sounds_dir.c_str(), basepath.c_str(), n+1); } else { - snprintf (buf, sizeof(buf), "%s%s.wav", sounds_dir.c_str(), basepath.c_str()); + snprintf (buf, sizeof(buf), "%s/%s.wav", sounds_dir.c_str(), basepath.c_str()); } if (::access (buf, F_OK) == 0) { diff --git a/libs/ardour/named_selection.cc b/libs/ardour/named_selection.cc index 605d7cae13..ecce09692f 100644 --- a/libs/ardour/named_selection.cc +++ b/libs/ardour/named_selection.cc @@ -33,12 +33,14 @@ using namespace PBD; sigc::signal<void,NamedSelection*> NamedSelection::NamedSelectionCreated; -NamedSelection::NamedSelection (string n, list<Playlist*>& l) +typedef std::list<boost::shared_ptr<Playlist> > PlaylistList; + +NamedSelection::NamedSelection (string n, PlaylistList& l) : name (n) { playlists = l; - for (list<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) { - (*i)->ref(); + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + (*i)->use(); } NamedSelectionCreated (this); } @@ -65,13 +67,13 @@ NamedSelection::NamedSelection (Session& session, const XMLNode& node) const XMLNode* plnode; string playlist_name; - Playlist* playlist; + boost::shared_ptr<Playlist> playlist; plnode = *niter; if ((property = plnode->property ("name")) != 0) { if ((playlist = session.playlist_by_name (property->value())) != 0) { - playlist->ref(); + playlist->use(); playlists.push_back (playlist); } else { warning << string_compose (_("Chunk %1 uses an unknown playlist \"%2\""), name, property->value()) << endmsg; @@ -87,8 +89,8 @@ NamedSelection::NamedSelection (Session& session, const XMLNode& node) NamedSelection::~NamedSelection () { - for (list<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) { - (*i)->unref(); + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + (*i)->release(); } } @@ -107,7 +109,7 @@ NamedSelection::get_state () root->add_property ("name", name); child = root->add_child ("Playlists"); - for (list<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) { + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { XMLNode* plnode = new XMLNode ("Playlist"); plnode->add_property ("name", (*i)->name()); diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 77aee9392d..8c1c608e1b 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -36,6 +36,7 @@ #include <ardour/session.h> #include <ardour/region.h> #include <ardour/region_factory.h> +#include <ardour/playlist_factory.h> #include "i18n.h" @@ -43,14 +44,12 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -sigc::signal<void,Playlist*> Playlist::PlaylistCreated; - struct ShowMeTheList { - ShowMeTheList (Playlist *pl, const string& n) : playlist (pl), name (n) {} + ShowMeTheList (boost::shared_ptr<Playlist> pl, const string& n) : playlist (pl), name (n) {} ~ShowMeTheList () { cerr << ">>>>" << name << endl; playlist->dump(); cerr << "<<<<" << name << endl << endl; }; - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; string name; }; @@ -86,43 +85,42 @@ Playlist::Playlist (Session& sess, const XMLNode& node, bool hide) init (hide); _name = "unnamed"; /* reset by set_state */ - /* derived class calls set_state() */ + /* set state called by derived class */ } -Playlist::Playlist (const Playlist& other, string namestr, bool hide) - : _name (namestr), _session (other._session), _orig_diskstream_id(other._orig_diskstream_id) +Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, bool hide) + : _name (namestr), _session (other->_session), _orig_diskstream_id(other->_orig_diskstream_id) { init (hide); RegionList tmp; - other.copy_regions (tmp); + other->copy_regions (tmp); in_set_state++; for (list<boost::shared_ptr<Region> >::iterator x = tmp.begin(); x != tmp.end(); ++x) { - add_region_internal( (*x), (*x)->position() ); + add_region_internal( (*x), (*x)->position()); } in_set_state--; - _splicing = other._splicing; - _nudging = other._nudging; - _edit_mode = other._edit_mode; + _splicing = other->_splicing; + _nudging = other->_nudging; + _edit_mode = other->_edit_mode; in_set_state = 0; in_flush = false; in_partition = false; subcnt = 0; _read_data_count = 0; - _frozen = other._frozen; - - layer_op_counter = other.layer_op_counter; - freeze_length = other.freeze_length; + _frozen = other->_frozen; + layer_op_counter = other->layer_op_counter; + freeze_length = other->freeze_length; } -Playlist::Playlist (const Playlist& other, nframes_t start, nframes_t cnt, string str, bool hide) - : _name (str), _session (other._session), _orig_diskstream_id(other._orig_diskstream_id) +Playlist::Playlist (boost::shared_ptr<const Playlist> other, nframes_t start, nframes_t cnt, string str, bool hide) + : _name (str), _session (other->_session), _orig_diskstream_id(other->_orig_diskstream_id) { RegionLock rlock2 (&((Playlist&)other)); @@ -130,7 +128,7 @@ Playlist::Playlist (const Playlist& other, nframes_t start, nframes_t cnt, strin init (hide); - for (RegionList::const_iterator i = other.regions.begin(); i != other.regions.end(); i++) { + for (RegionList::const_iterator i = other->regions.begin(); i != other->regions.end(); i++) { boost::shared_ptr<Region> region; boost::shared_ptr<Region> new_region; @@ -177,32 +175,28 @@ Playlist::Playlist (const Playlist& other, nframes_t start, nframes_t cnt, strin new_region = RegionFactory::RegionFactory::create (region, offset, len, new_name, region->layer(), region->flags()); - add_region_internal (new_region, position, true); + add_region_internal (new_region, position); } /* this constructor does NOT notify others (session) */ } void -Playlist::ref () +Playlist::use () { ++_refcnt; - InUse (this, true); /* EMIT SIGNAL */ + InUse (true); /* EMIT SIGNAL */ } void -Playlist::unref () +Playlist::release () { if (_refcnt > 0) { _refcnt--; } + if (_refcnt == 0) { - InUse (this, false); /* EMIT SIGNAL */ - - if (_hidden) { - /* nobody knows we exist */ - delete this; - } + InUse (false); /* EMIT SIGNAL */ } } @@ -259,7 +253,7 @@ Playlist::~Playlist () RegionLock rl (this); for (set<boost::shared_ptr<Region> >::iterator i = all_regions.begin(); i != all_regions.end(); ++i) { - (*i)->set_playlist (0); + (*i)->set_playlist (boost::shared_ptr<Playlist>()); } } @@ -460,7 +454,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa nframes_t pos = position; if (itimes >= 1) { - add_region_internal (region, pos, true); + add_region_internal (region, pos); pos += region->length(); --itimes; } @@ -477,7 +471,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa for (int i = 0; i < itimes; ++i) { boost::shared_ptr<Region> copy = RegionFactory::create (region); - add_region_internal (copy, pos, true); + add_region_internal (copy, pos); pos += region->length(); } @@ -486,12 +480,24 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa string name; _session.region_name (name, region->name(), false); boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags()); - add_region_internal (sub, pos, true); + add_region_internal (sub, pos); + } +} + +void +Playlist::set_region_ownership () +{ + RegionLock rl (this); + RegionList::iterator i; + boost::weak_ptr<Playlist> pl (shared_from_this()); + + for (i = regions.begin(); i != regions.end(); ++i) { + (*i)->set_playlist (pl); } } void -Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t position, bool delay_sort) +Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t position) { RegionSortByPosition cmp; nframes_t old_length = 0; @@ -500,7 +506,11 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t posit old_length = _get_maximum_extent(); } - region->set_playlist (this); + if (!in_set_state) { + boost::shared_ptr<Playlist> foo (shared_from_this()); + region->set_playlist (boost::weak_ptr<Playlist>(foo)); + } + region->set_position (position, this); timestamp_layer_op (region); @@ -553,7 +563,7 @@ Playlist::remove_region (boost::shared_ptr<Region> region) } int -Playlist::remove_region_internal (boost::shared_ptr<Region>region, bool delay_sort) +Playlist::remove_region_internal (boost::shared_ptr<Region>region) { RegionList::iterator i; nframes_t old_length = 0; @@ -687,7 +697,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, pos2 - pos1, pos3 - pos2, new_name, regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit)); - add_region_internal (region, start, true); + add_region_internal (region, start); new_regions.push_back (region); } @@ -697,7 +707,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name, regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit)); - add_region_internal (region, end, true); + add_region_internal (region, end); new_regions.push_back (region); /* "front" ***** */ @@ -726,7 +736,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit)); - add_region_internal (region, start, true); + add_region_internal (region, start); new_regions.push_back (region); } @@ -760,7 +770,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, 0, pos3 - pos1, new_name, regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit)); - add_region_internal (region, pos1, true); + add_region_internal (region, pos1); new_regions.push_back (region); } @@ -802,20 +812,19 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi } } -Playlist* -Playlist::cut_copy (Playlist* (Playlist::*pmf)(nframes_t, nframes_t,bool), list<AudioRange>& ranges, bool result_is_hidden) +boost::shared_ptr<Playlist> +Playlist::cut_copy (boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t, nframes_t,bool), list<AudioRange>& ranges, bool result_is_hidden) { - Playlist* ret; - Playlist* pl; + boost::shared_ptr<Playlist> ret; + boost::shared_ptr<Playlist> pl; nframes_t start; if (ranges.empty()) { - return 0; + return boost::shared_ptr<Playlist>(); } start = ranges.front().start; - for (list<AudioRange>::iterator i = ranges.begin(); i != ranges.end(); ++i) { pl = (this->*pmf)((*i).start, (*i).length(), result_is_hidden); @@ -829,39 +838,31 @@ Playlist::cut_copy (Playlist* (Playlist::*pmf)(nframes_t, nframes_t,bool), list< chopped. */ - ret->paste (*pl, (*i).start - start, 1.0f); - delete pl; + ret->paste (pl, (*i).start - start, 1.0f); } } - if (ret) { - /* manually notify session of new playlist here - because the playlists were constructed without notifying - */ - PlaylistCreated (ret); - } - return ret; } -Playlist* +boost::shared_ptr<Playlist> Playlist::cut (list<AudioRange>& ranges, bool result_is_hidden) { - Playlist* (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::cut; + boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::cut; return cut_copy (pmf, ranges, result_is_hidden); } -Playlist* +boost::shared_ptr<Playlist> Playlist::copy (list<AudioRange>& ranges, bool result_is_hidden) { - Playlist* (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::copy; + boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::copy; return cut_copy (pmf, ranges, result_is_hidden); } -Playlist * +boost::shared_ptr<Playlist> Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden) { - Playlist *the_copy; + boost::shared_ptr<Playlist> the_copy; RegionList thawlist; char buf[32]; @@ -870,8 +871,8 @@ Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden) new_name += '.'; new_name += buf; - if ((the_copy = copyPlaylist (*this, start, cnt, new_name, result_is_hidden)) == 0) { - return 0; + if ((the_copy = PlaylistFactory::create (shared_from_this(), start, cnt, new_name, result_is_hidden)) == 0) { + return boost::shared_ptr<Playlist>(); } partition_internal (start, start+cnt-1, true, thawlist); @@ -884,7 +885,7 @@ Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden) return the_copy; } -Playlist * +boost::shared_ptr<Playlist> Playlist::copy (nframes_t start, nframes_t cnt, bool result_is_hidden) { char buf[32]; @@ -895,28 +896,28 @@ Playlist::copy (nframes_t start, nframes_t cnt, bool result_is_hidden) new_name += buf; cnt = min (_get_maximum_extent() - start, cnt); - return copyPlaylist (*this, start, cnt, new_name, result_is_hidden); + return PlaylistFactory::create (shared_from_this(), start, cnt, new_name, result_is_hidden); } int -Playlist::paste (Playlist& other, nframes_t position, float times) +Playlist::paste (boost::shared_ptr<Playlist> other, nframes_t position, float times) { times = fabs (times); nframes_t old_length; { RegionLock rl1 (this); - RegionLock rl2 (&other); + RegionLock rl2 (other.get()); old_length = _get_maximum_extent(); int itimes = (int) floor (times); nframes_t pos = position; - nframes_t shift = other._get_maximum_extent(); + nframes_t shift = other->_get_maximum_extent(); layer_t top_layer = regions.size(); while (itimes--) { - for (RegionList::iterator i = other.regions.begin(); i != other.regions.end(); ++i) { + for (RegionList::iterator i = other->regions.begin(); i != other->regions.end(); ++i) { boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i); /* put these new regions on top of all existing ones, but preserve @@ -955,7 +956,7 @@ Playlist::duplicate (boost::shared_ptr<Region> region, nframes_t position, float while (itimes--) { boost::shared_ptr<Region> copy = RegionFactory::create (region); - add_region_internal (copy, pos, true); + add_region_internal (copy, pos); pos += region->length(); } @@ -964,7 +965,7 @@ Playlist::duplicate (boost::shared_ptr<Region> region, nframes_t position, float string name; _session.region_name (name, region->name(), false); boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags()); - add_region_internal (sub, pos, true); + add_region_internal (sub, pos); } } @@ -999,7 +1000,7 @@ Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_pos _session.region_name (after_name, region->name(), false); right = RegionFactory::create (region, before, after, after_name, region->layer(), Region::Flag (region->flags()|Region::RightOfSplit)); - add_region_internal (left, region->position(), true); + add_region_internal (left, region->position()); add_region_internal (right, region->position() + before); uint64_t orig_layer_op = region->last_layer_op(); @@ -1016,7 +1017,7 @@ Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_pos finalize_split_region (region, left, right); - if (remove_region_internal (region, true)) { + if (remove_region_internal (region)) { return; } } diff --git a/libs/ardour/playlist_factory.cc b/libs/ardour/playlist_factory.cc index 4461783874..f5f19d5b5b 100644 --- a/libs/ardour/playlist_factory.cc +++ b/libs/ardour/playlist_factory.cc @@ -22,24 +22,75 @@ #include <ardour/playlist.h> #include <ardour/audioplaylist.h> +#include <ardour/playlist_factory.h> #include "i18n.h" using namespace ARDOUR; using namespace PBD; -Playlist* -Playlist::copyPlaylist (const Playlist& playlist, nframes_t start, nframes_t length, - string name, bool result_is_hidden) +sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistFactory::PlaylistCreated; + +boost::shared_ptr<Playlist> +PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden) +{ + boost::shared_ptr<Playlist> pl; + + pl = boost::shared_ptr<Playlist> (new AudioPlaylist (s, node, hidden)); + + pl->set_region_ownership (); + + if (!hidden) { + PlaylistCreated (pl); + } + return pl; +} + +boost::shared_ptr<Playlist> +PlaylistFactory::create (Session& s, string name, bool hidden) +{ + boost::shared_ptr<Playlist> pl; + + pl = boost::shared_ptr<Playlist> (new AudioPlaylist (s, name, hidden)); + + if (!hidden) { + PlaylistCreated (pl); + } + + return pl; +} + +boost::shared_ptr<Playlist> +PlaylistFactory::create (boost::shared_ptr<const Playlist> old, string name, bool hidden) { - const AudioPlaylist* apl; - - if ((apl = dynamic_cast<const AudioPlaylist*> (&playlist)) != 0) { - return new AudioPlaylist (*apl, start, length, name, result_is_hidden); - } else { - fatal << _("programming error: Playlist::copyPlaylist called with unknown Playlist type") - << endmsg; - /*NOTREACHED*/ - return 0; + boost::shared_ptr<Playlist> pl; + boost::shared_ptr<const AudioPlaylist> apl; + + if ((apl = boost::dynamic_pointer_cast<const AudioPlaylist> (old)) != 0) { + pl = boost::shared_ptr<Playlist> (new AudioPlaylist (apl, name, hidden)); + pl->set_region_ownership (); } + + if (!hidden) { + PlaylistCreated (pl); + } + + return pl; +} + +boost::shared_ptr<Playlist> +PlaylistFactory::create (boost::shared_ptr<const Playlist> old, nframes_t start, nframes_t cnt, string name, bool hidden) +{ + boost::shared_ptr<Playlist> pl; + boost::shared_ptr<const AudioPlaylist> apl; + + if ((apl = boost::dynamic_pointer_cast<const AudioPlaylist> (old)) != 0) { + pl = boost::shared_ptr<Playlist> (new AudioPlaylist (apl, start, cnt, name, hidden)); + pl->set_region_ownership (); + } + + + /* this factory method does NOT notify others */ + + return pl; } diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 5aeecca0e2..9d81cc5907 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -54,7 +54,6 @@ Region::Region (nframes_t start, nframes_t length, const string& name, layer_t l /* basic Region constructor */ _flags = flags; - _playlist = 0; _read_data_count = 0; _frozen = 0; pending_changed = Change (0); @@ -76,7 +75,6 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes _frozen = 0; pending_changed = Change (0); - _playlist = 0; _read_data_count = 0; _start = other->_start + offset; @@ -100,7 +98,6 @@ Region::Region (boost::shared_ptr<const Region> other) _frozen = 0; pending_changed = Change (0); - _playlist = 0; _read_data_count = 0; _first_edit = EditChangesID; @@ -126,7 +123,6 @@ Region::Region (const XMLNode& node) { _frozen = 0; pending_changed = Change (0); - _playlist = 0; _read_data_count = 0; _start = 0; _sync_position = _start; @@ -148,7 +144,7 @@ Region::~Region () } void -Region::set_playlist (Playlist* pl) +Region::set_playlist (boost::weak_ptr<Playlist> pl) { _playlist = pl; } @@ -206,9 +202,11 @@ Region::maybe_uncopy () void Region::first_edit () { - if (_first_edit != EditChangesNothing && _playlist) { + boost::shared_ptr<Playlist> pl (playlist()); - _name = _playlist->session().new_region_name (_name); + if (_first_edit != EditChangesNothing && pl) { + + _name = pl->session().new_region_name (_name); _first_edit = EditChangesNothing; send_change (NameChanged); @@ -219,7 +217,9 @@ Region::first_edit () bool Region::at_natural_position () const { - if (!_playlist) { + boost::shared_ptr<Playlist> pl (playlist()); + + if (!pl) { return false; } @@ -237,7 +237,9 @@ Region::at_natural_position () const void Region::move_to_natural_position (void *src) { - if (!_playlist) { + boost::shared_ptr<Playlist> pl (playlist()); + + if (!pl) { return; } @@ -297,7 +299,11 @@ Region::set_position_on_top (nframes_t pos, void *src) _position = pos; } - _playlist->raise_region_to_top (shared_from_this ()); + boost::shared_ptr<Playlist> pl (playlist()); + + if (pl) { + pl->raise_region_to_top (shared_from_this ()); + } /* do this even if the position is the same. this helps out a GUI that has moved its representation already. @@ -684,42 +690,37 @@ Region::sync_position() const void Region::raise () { - if (_playlist == 0) { - return; + boost::shared_ptr<Playlist> pl (playlist()); + if (pl) { + pl->raise_region (shared_from_this ()); } - - _playlist->raise_region (shared_from_this ()); } void Region::lower () { - if (_playlist == 0) { - return; + boost::shared_ptr<Playlist> pl (playlist()); + if (pl) { + pl->lower_region (shared_from_this ()); } - - _playlist->lower_region (shared_from_this ()); } void Region::raise_to_top () { - - if (_playlist == 0) { - return; + boost::shared_ptr<Playlist> pl (playlist()); + if (pl) { + pl->raise_region_to_top (shared_from_this()); } - - _playlist->raise_region_to_top (shared_from_this()); } void Region::lower_to_bottom () { - if (_playlist == 0) { - return; + boost::shared_ptr<Playlist> pl (playlist()); + if (pl) { + pl->lower_region_to_bottom (shared_from_this()); } - - _playlist->lower_region_to_bottom (shared_from_this()); } void diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 14c5bde996..caea881383 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -468,10 +468,24 @@ Session::~Session () tmp = i; ++tmp; - delete *i; + (*i)->drop_references (); + + i = tmp; + } + + for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) { + PlaylistList::iterator tmp; + + tmp = i; + ++tmp; + + (*i)->drop_references (); i = tmp; } + + playlists.clear (); + unused_playlists.clear (); #ifdef TRACK_DESTRUCTION cerr << "delete audio regions\n"; @@ -918,7 +932,7 @@ Session::hookup_io () } void -Session::playlist_length_changed (Playlist* pl) +Session::playlist_length_changed () { /* we can't just increase end_location->end() if pl->get_maximum_extent() if larger. if the playlist used to be the longest playlist, @@ -932,10 +946,10 @@ Session::playlist_length_changed (Playlist* pl) void Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream) { - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; if ((playlist = dstream->playlist()) != 0) { - playlist->LengthChanged.connect (sigc::bind (mem_fun (this, &Session::playlist_length_changed), playlist)); + playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed)); } /* see comment in playlist_length_changed () */ @@ -2268,7 +2282,7 @@ Session::get_maximum_extent () const boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) { - Playlist* pl = (*i)->playlist(); + boost::shared_ptr<Playlist> pl = (*i)->playlist(); if ((me = pl->get_maximum_extent()) > max) { max = me; } @@ -2671,17 +2685,11 @@ Session::add_source (boost::shared_ptr<Source> source) result = audio_sources.insert (entry); } - if (!result.second) { - cerr << "\tNOT inserted ? " << result.second << endl; + if (result.second) { + source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source))); + set_dirty(); } - - source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source))); - set_dirty(); - - SourceAdded (source); /* EMIT SIGNAL */ - } else { - cerr << "\tNOT AUDIO FILE\n"; - } + } } void @@ -2710,8 +2718,6 @@ Session::remove_source (boost::weak_ptr<Source> src) save_state (_current_snapshot_name); } - - SourceRemoved(source); /* EMIT SIGNAL */ } boost::shared_ptr<Source> @@ -2897,6 +2903,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool } else { snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str()); } + } else { spath += '/'; @@ -2940,6 +2947,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool string foo = buf; spath = discover_best_sound_dir (); + spath += '/'; string::size_type pos = foo.find_last_of ('/'); @@ -2961,7 +2969,7 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo /* Playlist management */ -Playlist * +boost::shared_ptr<Playlist> Session::playlist_by_name (string name) { Glib::Mutex::Lock lm (playlist_lock); @@ -2975,11 +2983,12 @@ Session::playlist_by_name (string name) return* i; } } - return 0; + + return boost::shared_ptr<Playlist>(); } void -Session::add_playlist (Playlist* playlist) +Session::add_playlist (boost::shared_ptr<Playlist> playlist) { if (playlist->hidden()) { return; @@ -2989,9 +2998,8 @@ Session::add_playlist (Playlist* playlist) Glib::Mutex::Lock lm (playlist_lock); if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) { playlists.insert (playlists.begin(), playlist); - // playlist->ref(); - playlist->InUse.connect (mem_fun (*this, &Session::track_playlist)); - playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), playlist)); + playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr<Playlist>(playlist))); + playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr<Playlist>(playlist))); } } @@ -3001,7 +3009,7 @@ Session::add_playlist (Playlist* playlist) } void -Session::get_playlists (vector<Playlist*>& s) +Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s) { { Glib::Mutex::Lock lm (playlist_lock); @@ -3015,15 +3023,25 @@ Session::get_playlists (vector<Playlist*>& s) } void -Session::track_playlist (Playlist* pl, bool inuse) +Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl) { + boost::shared_ptr<Playlist> pl(wpl.lock()); + + if (!pl) { + return; + } + PlaylistList::iterator x; + if (pl->hidden()) { + /* its not supposed to be visible */ + return; + } + { Glib::Mutex::Lock lm (playlist_lock); if (!inuse) { - //cerr << "shifting playlist to unused: " << pl->name() << endl; unused_playlists.insert (pl); @@ -3033,8 +3051,7 @@ Session::track_playlist (Playlist* pl, bool inuse) } else { - //cerr << "shifting playlist to used: " << pl->name() << endl; - + playlists.insert (pl); if ((x = unused_playlists.find (pl)) != unused_playlists.end()) { @@ -3045,26 +3062,33 @@ Session::track_playlist (Playlist* pl, bool inuse) } void -Session::remove_playlist (Playlist* playlist) +Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist) { if (_state_of_the_state & Deletion) { return; } + boost::shared_ptr<Playlist> playlist (weak_playlist.lock()); + + if (!playlist) { + return; + } + { Glib::Mutex::Lock lm (playlist_lock); - // cerr << "removing playlist: " << playlist->name() << endl; + cerr << "removing playlist: " << playlist->name() << endl; PlaylistList::iterator i; i = find (playlists.begin(), playlists.end(), playlist); - if (i != playlists.end()) { + cerr << "\tfound it in used playlist\n"; playlists.erase (i); } i = find (unused_playlists.begin(), unused_playlists.end(), playlist); if (i != unused_playlists.end()) { + cerr << "\tfound it in unused playlist\n"; unused_playlists.erase (i); } @@ -3617,7 +3641,7 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le bool overwrite, vector<boost::shared_ptr<AudioSource> >& srcs, InterThreadInfo& itt) { int ret = -1; - Playlist* playlist; + boost::shared_ptr<Playlist> playlist; boost::shared_ptr<AudioFileSource> fsource; uint32_t x; char buf[PATH_MAX+1]; diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index 3d2da887b0..06ed44f722 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -70,8 +70,9 @@ Command *Session::memento_command_factory(XMLNode *n) } else if (obj_T == typeid (TempoMap).name()) { return new MementoCommand<TempoMap>(*_tempo_map, before, after); } else if (obj_T == typeid (Playlist).name() || obj_T == typeid (AudioPlaylist).name()) { - if (Playlist *pl = playlist_by_name(child->property("name")->value())) - return new MementoCommand<Playlist>(*pl, before, after); + if (boost::shared_ptr<Playlist> pl = playlist_by_name(child->property("name")->value())) { + return new MementoCommand<Playlist>(*(pl.get()), before, after); + } } else if (obj_T == typeid (Route).name() || obj_T == typeid (AudioTrack).name()) { return new MementoCommand<Route>(*route_by_id(id), before, after); } else if (obj_T == typeid (Curve).name() || obj_T == typeid (AutomationList).name()) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 95449d6c1a..2ae8a833e1 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -83,6 +83,7 @@ #include <ardour/control_protocol_manager.h> #include <ardour/region_factory.h> #include <ardour/source_factory.h> +#include <ardour/playlist_factory.h> #include <control_protocol/control_protocol.h> @@ -236,7 +237,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region)); SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source)); - Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); + PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); @@ -380,6 +381,7 @@ Session::setup_raid_path (string path) if (fspath[fspath.length()-1] != '/') { fspath += '/'; } + fspath += sound_dir (false); AudioFileSource::set_search_path (fspath); @@ -1681,7 +1683,7 @@ Session::load_playlists (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; nlist = node.children(); @@ -1702,7 +1704,7 @@ Session::load_unused_playlists (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; nlist = node.children(); @@ -1717,22 +1719,22 @@ Session::load_unused_playlists (const XMLNode& node) // now manually untrack it - track_playlist (playlist, false); + track_playlist (false, boost::weak_ptr<Playlist> (playlist)); } return 0; } -Playlist * +boost::shared_ptr<Playlist> Session::XMLPlaylistFactory (const XMLNode& node) { try { - return new AudioPlaylist (*this, node); + return PlaylistFactory::create (*this, node); } catch (failed_constructor& err) { - return 0; + return boost::shared_ptr<Playlist>(); } } @@ -1792,7 +1794,6 @@ Session::sound_dir (bool with_path) const old_withpath = _path; old_withpath += old_sound_dir_name; - old_withpath += '/'; if (stat (old_withpath.c_str(), &statbuf) == 0) { if (with_path) @@ -1812,7 +1813,6 @@ Session::sound_dir (bool with_path) const res += legalize_for_path (_name); res += '/'; res += sound_dir_name; - res += '/'; return res; } @@ -2385,11 +2385,22 @@ Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_th return 0; } +struct RegionCounter { + typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList; + AudioSourceList::iterator iter; + boost::shared_ptr<Region> region; + uint32_t count; + + RegionCounter() : count (0) {} +}; + int Session::cleanup_sources (Session::cleanup_report& rep) { - vector<boost::shared_ptr<Source> > dead_sources; - vector<Playlist*> playlists_tbd; + typedef map<boost::shared_ptr<Source>, RegionCounter> SourceRegionMap; + SourceRegionMap dead_sources; + + vector<boost::shared_ptr<Playlist> > playlists_tbd; PathScanner scanner; string sound_path; vector<space_and_path>::iterator i; @@ -2428,74 +2439,114 @@ Session::cleanup_sources (Session::cleanup_report& rep) /* now delete any that were marked for deletion */ - for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) { - PlaylistList::iterator foo; - - if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) { - unused_playlists.erase (foo); - } - delete *x; + for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) { + (*x)->drop_references (); } + playlists_tbd.clear (); + /* step 2: find all un-referenced sources */ rep.paths.clear (); rep.space = 0; - for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) { - - AudioSourceList::iterator tmp; - - tmp = i; - ++tmp; + for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) { + + /* we expect the use_count() to be at least 2: one for the shared_ptr<> in the sources + list and one for the iterator. if its used by 1 region, we'd expect a value of 3. - /* only remove files that are not in use and have some size - to them. otherwise we remove the current "nascent" + do not bother with files that are zero size, otherwise we remove the current "nascent" capture files. */ - cerr << "checking out source " << i->second->name() << " use_count = " << i->second.use_count() << endl; + if (i->second.use_count() <= 3 && i->second->length() > 0) { - if (i->second.use_count() == 1 && i->second->length() > 0) { - dead_sources.push_back (i->second); + pair<boost::shared_ptr<Source>, RegionCounter> newpair; - /* remove this source from our own list to avoid us - adding it to the list of all sources below - */ - - audio_sources.erase (i); - } + newpair.first = i->second; + newpair.second.iter = i; - i = tmp; + dead_sources.insert (newpair); + } } - /* Step 3: get rid of all regions in the region list that use any dead sources - in case the sources themselves don't go away (they might be referenced in - other snapshots). - */ - - for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { + /* Search the region list to find out the state of the supposedly unreferenced regions + */ - for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) { - AudioRegionList::iterator tmp; - boost::shared_ptr<AudioRegion> ar; + for (SourceRegionMap::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { - tmp = r; - ++tmp; + for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ++r) { - ar = r->second; + boost::shared_ptr<AudioRegion> ar = r->second; for (uint32_t n = 0; n < ar->n_channels(); ++n) { - if (ar->source (n) == (*i)) { - /* this region is dead */ - remove_region (ar); + + if (ar->source (n) == i->first) { + + /* this region uses this source */ + + i->second.region = ar; + i->second.count++; + + if (i->second.count > 1) { + break; + } } } - - r = tmp; } } + /* next, get rid of all regions in the region list that use any dead sources + in case the sources themselves don't go away (they might be referenced in + other snapshots). + + this is also where we remove the apparently unused sources from our source + list. this doesn't rename them or delete them, but it means they are + potential candidates for renaming after we find all soundfiles + and scan for use across all snapshots (including this one). + */ + + for (SourceRegionMap::iterator i = dead_sources.begin(); i != dead_sources.end(); ) { + + SourceRegionMap::iterator tmp; + + tmp = i; + ++tmp; + + if (i->second.count == 0) { + + /* no regions use this source */ + + /* remove this source from our own list to avoid us + adding it to the list of all sources below + */ + + audio_sources.erase (i->second.iter); + + } else if (i->second.count == 1) { + + /* the use_count for the source was 3. this means that there is only reference to it in addition to the source + list and an iterator used to traverse that list. since there is a single region using the source, that + must be the extra reference. this implies that its a whole-file region + with no children, so remove the region and the source. + */ + + remove_region (i->second.region); + + /* remove this source from our own list to avoid us + adding it to the list of all sources below + */ + + audio_sources.erase (i->second.iter); + + } else { + /* more than one region uses this source, do not remove it */ + dead_sources.erase (i); + } + + i = tmp; + } + /* build a list of all the possible sound directories for the session */ for (i = session_dirs.begin(); i != session_dirs.end(); ) { @@ -2504,7 +2555,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) ++nexti; sound_path += (*i).path; - sound_path += sound_dir_name; + sound_path += sound_dir (false); if (nexti != session_dirs.end()) { sound_path += ':'; @@ -2512,7 +2563,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) i = nexti; } - + /* now do the same thing for the files that ended up in the sounds dir(s) but are not referenced as sources in any snapshot. */ @@ -2577,8 +2628,12 @@ Session::cleanup_sources (Session::cleanup_report& rep) on whichever filesystem it was already on. */ - newpath = Glib::path_get_dirname (*x); - newpath = Glib::path_get_dirname (newpath); + /* XXX this is a hack ... go up 4 levels */ + + newpath = Glib::path_get_dirname (*x); // "audiofiles" + newpath = Glib::path_get_dirname (newpath); // "session-name" + newpath = Glib::path_get_dirname (newpath); // "interchange" + newpath = Glib::path_get_dirname (newpath); // "session-dir" newpath += '/'; newpath += dead_sound_dir_name; @@ -2639,7 +2694,6 @@ Session::cleanup_sources (Session::cleanup_report& rep) goto out; } } - } ret = 0; diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 74ca0afcd4..39a83cb6de 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -110,15 +110,22 @@ Source::set_state (const XMLNode& node) } void -Source::add_playlist (Playlist* pl) +Source::add_playlist (boost::shared_ptr<Playlist> pl) { _playlists.insert (pl); + pl->GoingAway.connect (bind (mem_fun (*this, &Source::remove_playlist), boost::weak_ptr<Playlist> (pl))); } void -Source::remove_playlist (Playlist* pl) +Source::remove_playlist (boost::weak_ptr<Playlist> wpl) { - std::set<Playlist*>::iterator x; + boost::shared_ptr<Playlist> pl (wpl.lock()); + + if (!pl) { + return; + } + + std::set<boost::shared_ptr<Playlist> >::iterator x; if ((x = _playlists.find (pl)) != _playlists.end()) { _playlists.erase (x); diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index cb36d3cc35..9b8382c39f 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -83,10 +83,13 @@ boost::shared_ptr<Source> SourceFactory::create (Session& s, const XMLNode& node) { boost::shared_ptr<Source> ret (new SndFileSource (s, node)); + if (setup_peakfile (ret)) { return boost::shared_ptr<Source>(); } + SourceCreated (ret); + return ret; } @@ -141,12 +144,15 @@ boost::shared_ptr<Source> SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce) { boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags)); + if (setup_peakfile (ret)) { return boost::shared_ptr<Source>(); } + if (announce) { SourceCreated (ret); } + return ret; } |