summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-12-14 14:15:43 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-12-14 14:15:43 +0000
commitaf12adb34f62dc82f694a03ea3b2a6c99ba426ef (patch)
tree263ecb66462ee561c9e3741799541f0233f82e21 /libs
parentc0924280e9be867253a1b93eb7274e0eb955de5f (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')
-rw-r--r--libs/ardour/ardour/audio_diskstream.h4
-rw-r--r--libs/ardour/ardour/audioplaylist.h9
-rw-r--r--libs/ardour/ardour/audioregion.h2
-rw-r--r--libs/ardour/ardour/crossfade.h5
-rw-r--r--libs/ardour/ardour/diskstream.h10
-rw-r--r--libs/ardour/ardour/named_selection.h5
-rw-r--r--libs/ardour/ardour/playlist.h54
-rw-r--r--libs/ardour/ardour/region.h7
-rw-r--r--libs/ardour/ardour/session.h30
-rw-r--r--libs/ardour/ardour/session_playlist.h2
-rw-r--r--libs/ardour/ardour/source.h6
-rw-r--r--libs/ardour/ardour/track.h5
-rw-r--r--libs/ardour/audio_diskstream.cc25
-rw-r--r--libs/ardour/audio_playlist.cc28
-rw-r--r--libs/ardour/audio_track.cc20
-rw-r--r--libs/ardour/audioregion.cc45
-rw-r--r--libs/ardour/auditioner.cc2
-rw-r--r--libs/ardour/diskstream.cc32
-rw-r--r--libs/ardour/import.cc8
-rw-r--r--libs/ardour/named_selection.cc18
-rw-r--r--libs/ardour/playlist.cc147
-rw-r--r--libs/ardour/playlist_factory.cc75
-rw-r--r--libs/ardour/region.cc55
-rw-r--r--libs/ardour/session.cc88
-rw-r--r--libs/ardour/session_command.cc5
-rw-r--r--libs/ardour/session_state.cc170
-rw-r--r--libs/ardour/source.cc13
-rw-r--r--libs/ardour/source_factory.cc6
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;
}