summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2011-05-22 16:11:00 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2011-05-22 16:11:00 +0000
commit9c733915a0bc4b5274fac749b1adc874da79a6ee (patch)
tree1db070ef198c7b7890cb98c84a37a1321c810183 /libs
parentd40ee9548661f88db1bc1dcda0b463220d59a8d8 (diff)
basic uncombining (no post-facto region trimming)
git-svn-id: svn://localhost/ardour2/branches/3.0@9566 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/playlist.h10
-rw-r--r--libs/ardour/ardour/playlist_source.h3
-rw-r--r--libs/ardour/ardour/region.h2
-rw-r--r--libs/ardour/ardour/region_factory.h20
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/playlist.cc55
-rw-r--r--libs/ardour/region.cc6
-rw-r--r--libs/ardour/region_factory.cc10
-rw-r--r--libs/ardour/session_state.cc60
9 files changed, 161 insertions, 6 deletions
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 6385def785..5d3d5d2504 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -139,7 +139,8 @@ public:
void partition (framepos_t start, framepos_t end, bool cut = false);
void duplicate (boost::shared_ptr<Region>, framepos_t position, float times);
void nudge_after (framepos_t start, framecnt_t distance, bool forwards);
- void join (const RegionList&, const std::string&);
+ void combine (const RegionList&, const std::string&);
+ void uncombine (boost::shared_ptr<Region>);
void shuffle (boost::shared_ptr<Region>, int dir);
void update_after_tempo_map_change ();
@@ -382,6 +383,13 @@ public:
typedef std::pair<boost::shared_ptr<Region>, boost::shared_ptr<Region> > TwoRegions;
virtual void copy_dependents (const std::vector<TwoRegions>&, boost::shared_ptr<Playlist>) { }
+
+ struct RegionInfo {
+ boost::shared_ptr<Region> region;
+ framepos_t position;
+ framecnt_t length;
+ framepos_t start;
+ };
};
} /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/playlist_source.h b/libs/ardour/ardour/playlist_source.h
index 8732870ec0..ed48fbabd5 100644
--- a/libs/ardour/ardour/playlist_source.h
+++ b/libs/ardour/ardour/playlist_source.h
@@ -36,7 +36,8 @@ class PlaylistSource : virtual public Source {
virtual ~PlaylistSource ();
int set_state (const XMLNode&, int version);
-
+ boost::shared_ptr<const Playlist> playlist() const { return _playlist; }
+
protected:
boost::shared_ptr<Playlist> _playlist;
frameoffset_t _playlist_offset;
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 719c00acf8..fdcaeaf249 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -228,6 +228,8 @@ class Region
void source_deleted (boost::weak_ptr<Source>);
+ bool is_compound () const;
+
boost::shared_ptr<Source> source (uint32_t n=0) const { return _sources[ (n < _sources.size()) ? n : 0 ]; }
uint32_t n_channels() const { return _sources.size(); }
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index 647e1fe7d8..979b499b3a 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -61,6 +61,7 @@ public:
/** create a region from a single Source */
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>,
const PBD::PropertyList&, bool announce = true);
+
/** create a region from a multiple sources */
static boost::shared_ptr<Region> create (const SourceList &,
const PBD::PropertyList&, bool announce = true);
@@ -91,6 +92,24 @@ public:
static int region_name (std::string &, std::string, bool new_level = false);
static std::string new_region_name (std::string);
+ /* when we make a compound region, for every region involved there
+ * are two "instances" - the original, which is removed from this
+ * playlist, and a copy, which is added to the playlist used as
+ * the source for the compound.
+ *
+ * when we uncombine, we want to put the originals back into this
+ * playlist after we remove the compound. this map lets us
+ * look them up easily. note that if the compound was trimmed or
+ * split, we may have to trim the originals
+ * and they may not be added back if the compound was trimmed
+ * or split sufficiently.
+ */
+
+ typedef std::map<boost::shared_ptr<Region>, boost::shared_ptr<Region> > CompoundAssociations;
+ static CompoundAssociations& compound_associations() { return _compound_associations; }
+
+ static void add_compound_association (boost::shared_ptr<Region>, boost::shared_ptr<Region>);
+
private:
static void region_changed (PBD::PropertyChange const &, boost::weak_ptr<Region>);
@@ -106,6 +125,7 @@ public:
static void update_region_name_map (boost::shared_ptr<Region>);
static PBD::ScopedConnectionList region_list_connections;
+ static CompoundAssociations _compound_associations;
};
}
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index dd282e6cf3..f1e73ed1fd 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1253,6 +1253,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
mutable Glib::Mutex region_lock;
int load_regions (const XMLNode& node);
+ int load_compounds (const XMLNode& node);
void route_group_changed ();
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index bc6e23e451..85935d4377 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -39,6 +39,7 @@
#include "ardour/region.h"
#include "ardour/region_factory.h"
#include "ardour/playlist_factory.h"
+#include "ardour/playlist_source.h"
#include "ardour/transient_detector.h"
#include "ardour/session_playlists.h"
#include "ardour/source_factory.h"
@@ -2335,7 +2336,8 @@ Playlist::set_state (const XMLNode& node, int version)
// So that layer_op ordering doesn't get screwed up
region->set_last_layer_op( region->layer());
region->resume_property_changes ();
- }
+
+ }
}
/* update dependents, which was not done during add_region_internal
@@ -3151,7 +3153,7 @@ Playlist::find_next_top_layer_position (framepos_t t) const
}
void
-Playlist::join (const RegionList& r, const std::string& name)
+Playlist::combine (const RegionList& r, const std::string& name)
{
PropertyList plist;
uint32_t channels = 0;
@@ -3180,6 +3182,8 @@ Playlist::join (const RegionList& r, const std::string& name)
old_and_new_regions.push_back (TwoRegions (original_region,copied_region));
+ RegionFactory::add_compound_association (original_region, copied_region);
+
/* make position relative to zero */
pl->add_region (copied_region, original_region->position() - earliest_position);
@@ -3235,6 +3239,52 @@ Playlist::join (const RegionList& r, const std::string& name)
thaw ();
}
+void
+Playlist::uncombine (boost::shared_ptr<Region> target)
+{
+ // (1) check that its really a compound region
+
+ boost::shared_ptr<PlaylistSource> pls;
+ boost::shared_ptr<const Playlist> pl;
+ vector<boost::shared_ptr<Region> > originals;
+
+ if ((pls = boost::dynamic_pointer_cast<PlaylistSource>(target->source (0))) == 0) {
+ return;
+ }
+
+ pl = pls->playlist();
+
+ // (2) get all the original regions
+
+ const RegionList& rl (pl->region_list().rlist());
+
+ RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
+
+ for (RegionList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
+ RegionFactory::CompoundAssociations::iterator ca = cassocs.find (*i);
+ if (ca != cassocs.end()) {
+ originals.push_back (ca->second);
+ }
+ }
+
+ in_partition = true;
+ freeze ();
+
+ // (3) remove the compound region
+
+ remove_region (target);
+
+ // (4) add the originals. This will reset their playlist reference back
+ // to us, which means they are no longer considered owned by the RegionFactory
+
+ for (vector<boost::shared_ptr<Region> >::iterator i = originals.begin(); i != originals.end(); ++i) {
+ add_region ((*i), (*i)->position());
+ }
+
+ in_partition = false;
+ thaw ();
+}
+
uint32_t
Playlist::max_source_level () const
{
@@ -3263,4 +3313,3 @@ Playlist::count_joined_regions () const
return cnt;
}
-
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 93223709e7..3fbe288b7a 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -1671,3 +1671,9 @@ Region::max_source_level () const
return lvl;
}
+
+bool
+Region::is_compound () const
+{
+ return max_source_level() > 0;
+}
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index eba237d0d2..513ec7301b 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -43,6 +43,7 @@ RegionFactory::RegionMap RegionFactory::region_map;
PBD::ScopedConnectionList RegionFactory::region_list_connections;
Glib::StaticMutex RegionFactory::region_name_map_lock;
std::map<std::string, uint32_t> RegionFactory::region_name_map;
+RegionFactory::CompoundAssociations RegionFactory::_compound_associations;
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<const Region> region, bool announce)
@@ -366,8 +367,8 @@ RegionFactory::clear_map ()
{
Glib::Mutex::Lock lm (region_map_lock);
region_map.clear ();
+ _compound_associations.clear ();
}
-
}
void
@@ -561,3 +562,10 @@ RegionFactory::remove_regions_using_source (boost::shared_ptr<Source> src)
}
}
}
+
+void
+RegionFactory::add_compound_association (boost::shared_ptr<Region> orig, boost::shared_ptr<Region> copy)
+{
+ Glib::Mutex::Lock lm (region_map_lock);
+ _compound_associations[copy] = orig;
+}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 82c2d5a31c..02aee5d3ef 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -1088,6 +1088,22 @@ Session::state(bool full_state)
child->add_child_nocopy (r->state ());
}
}
+
+ RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
+
+ if (!cassocs.empty()) {
+ XMLNode* ca = node->add_child (X_("CompoundAssociations"));
+
+ for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
+ char buf[64];
+ XMLNode* can = new XMLNode (X_("CompoundAssociation"));
+ i->first->id().print (buf, sizeof (buf));
+ can->add_property (X_("copy"), buf);
+ i->second->id().print (buf, sizeof (buf));
+ can->add_property (X_("original"), buf);
+ ca->add_child_nocopy (*can);
+ }
+ }
}
if (full_state) {
@@ -1318,6 +1334,12 @@ Session::set_state (const XMLNode& node, int version)
goto out;
}
+ if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
+ if (load_compounds (*child)) {
+ goto out;
+ }
+ }
+
if ((child = find_named_node (node, "NamedSelections")) != 0) {
if (load_named_selections (*child)) {
goto out;
@@ -1592,6 +1614,44 @@ Session::load_regions (const XMLNode& node)
return 0;
}
+int
+Session::load_compounds (const XMLNode& node)
+{
+ XMLNodeList calist = node.children();
+ XMLNodeConstIterator caiter;
+ XMLProperty *caprop;
+
+ for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
+ XMLNode* ca = *caiter;
+ ID orig_id;
+ ID copy_id;
+
+ if ((caprop = ca->property (X_("original"))) == 0) {
+ continue;
+ }
+ orig_id = caprop->value();
+
+ if ((caprop = ca->property (X_("copy"))) == 0) {
+ continue;
+ }
+ copy_id = caprop->value();
+
+ boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
+ boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
+
+ if (!orig || !copy) {
+ warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
+ orig_id, copy_id)
+ << endmsg;
+ continue;
+ }
+
+ RegionFactory::add_compound_association (orig, copy);
+ }
+
+ return 0;
+}
+
boost::shared_ptr<Region>
Session::XMLRegionFactory (const XMLNode& node, bool full)
{