diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 1530eede9f..bdf17eabf0 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -117,6 +117,13 @@ public: bool hidden() const { return _hidden; } bool empty() const; + + bool shared () const { return !_shared_with_ids.empty(); } + void share_with (const PBD::ID&); + void unshare_with (const PBD::ID&); + bool shared_with (const PBD::ID&) const; + void reset_shares (); + uint32_t n_regions() const; bool all_regions_empty() const; std::pair get_extent () const; @@ -311,6 +318,7 @@ public: uint32_t subcnt; PBD::ID _orig_track_id; uint32_t _combine_ops; + std::list _shared_with_ids; void init (bool hide); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 267338228a..c33b56f984 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -316,6 +316,7 @@ AudioDiskstream::use_copy_playlist () newname = Playlist::bump_name (_playlist->name(), _session); if ((playlist = boost::dynamic_pointer_cast(PlaylistFactory::create (audio_playlist(), newname))) != 0) { + playlist->reset_shares(); return use_playlist (playlist); } else { return -1; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index cc6c0d3f40..d38c8d57bd 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -26,6 +26,7 @@ #include "pbd/convert.h" #include "pbd/stateful_diff_command.h" +#include "pbd/strsplit.h" #include "pbd/xml++.h" #include "ardour/debug.h" @@ -157,6 +158,7 @@ Playlist::Playlist (boost::shared_ptr other, string namestr, boo , regions (*this) , _type(other->_type) , _orig_track_id (other->_orig_track_id) + , _shared_with_ids (other->_shared_with_ids) { init (hide); @@ -189,6 +191,7 @@ Playlist::Playlist (boost::shared_ptr other, framepos_t start, f , regions (*this) , _type(other->_type) , _orig_track_id (other->_orig_track_id) + , _shared_with_ids (other->_shared_with_ids) { RegionReadLock rlock2 (const_cast (other.get())); @@ -2234,6 +2237,16 @@ Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir) _frozen = string_is_affirmative (prop->value()); } else if (prop->name() == X_("combine-ops")) { _combine_ops = atoi (prop->value()); + } else if (prop->name() == X_("shared-with-ids")) { + string shared_ids = prop->value (); + if (!shared_ids.empty()) { + vector result; + ::split (shared_ids, result, ','); + vector::iterator it = result.begin(); + for (; it != result.end(); ++it) { + _shared_with_ids.push_back (PBD::ID(*it)); + } + } } } @@ -2321,6 +2334,17 @@ Playlist::state (bool full_state) _orig_track_id.print (buf, sizeof (buf)); node->add_property (X_("orig-track-id"), buf); + + string shared_ids; + list::const_iterator it = _shared_with_ids.begin(); + for (; it != _shared_with_ids.end(); ++it) { + shared_ids += "," + (*it).to_s(); + } + if (!shared_ids.empty()) { + shared_ids.erase(0,1); + } + + node->add_property (X_("shared-with-ids"), shared_ids); node->add_property (X_("frozen"), _frozen ? "yes" : "no"); if (full_state) { @@ -3317,9 +3341,56 @@ Playlist::max_source_level () const void Playlist::set_orig_track_id (const PBD::ID& id) { + if (shared_with(id)) { + // Swap 'shared_id' / origin_track_id + unshare_with (id); + share_with (_orig_track_id); + } _orig_track_id = id; } +void +Playlist::share_with (const PBD::ID& id) +{ + if (!shared_with(id)) { + _shared_with_ids.push_back (id); + } +} + +void +Playlist::unshare_with (const PBD::ID& id) +{ + list::iterator it = _shared_with_ids.begin (); + while (it != _shared_with_ids.end()) { + if (*it == id) { + _shared_with_ids.erase (it); + break; + } + ++it; + } +} + +bool +Playlist::shared_with (const PBD::ID& id) const +{ + bool shared = false; + list::const_iterator it = _shared_with_ids.begin (); + while (it != _shared_with_ids.end() && !shared) { + if (*it == id) { + shared = true; + } + ++it; + } + + return shared; +} + +void +Playlist::reset_shares () +{ + _shared_with_ids.clear(); +} + /** Take a list of ranges, coalesce any that can be coalesced, then call * check_crossfades for each one. */ diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 3575a5c152..f16324dca8 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3255,7 +3255,15 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i boost::shared_ptr playlist = playlists->by_name (playlist_name); // Use same name as Route::set_name_in_state so playlist copy // is picked up when creating the Route in XMLRouteFactory below - PlaylistFactory::create (playlist, string_compose ("%1.1", name)); + playlist = PlaylistFactory::create (playlist, string_compose ("%1.1", name)); + playlist->reset_shares (); + } + } else if (pd == SharePlaylist) { + XMLNode* ds_node = find_named_node (node_copy, "Diskstream"); + if (ds_node) { + const std::string playlist_name = ds_node->property (X_("playlist"))->value (); + boost::shared_ptr playlist = playlists->by_name (playlist_name); + playlist->share_with ((node_copy.property (X_("id")))->value()); } } diff --git a/libs/ardour/session_playlists.cc b/libs/ardour/session_playlists.cc index a7e3c26613..d7780ea9b5 100644 --- a/libs/ardour/session_playlists.cc +++ b/libs/ardour/session_playlists.cc @@ -527,7 +527,10 @@ SessionPlaylists::playlists_for_track (boost::shared_ptr tr) const vector > pl_tr; for (vector >::iterator i = pl.begin(); i != pl.end(); ++i) { - if (((*i)->get_orig_track_id() == tr->id()) || (tr->playlist()->id() == (*i)->id())) { + if ( ((*i)->get_orig_track_id() == tr->id()) || + (tr->playlist()->id() == (*i)->id()) || + ((*i)->shared_with (tr->id())) ) + { pl_tr.push_back (*i); } }