Fix VST build.
[ardour.git] / libs / ardour / playlist.cc
index 2c4fa5382bf1c713a7442e80d082a093b57241e7..971ed8b2e836173a56b0c8d91d24aa23c1e15e6d 100644 (file)
@@ -17,9 +17,7 @@
 
 */
 
-#define __STDC_LIMIT_MACROS
 #include <stdint.h>
-
 #include <set>
 #include <fstream>
 #include <algorithm>
@@ -33,6 +31,7 @@
 #include "pbd/failed_constructor.h"
 #include "pbd/stateful_diff_command.h"
 #include "pbd/xml++.h"
+#include "pbd/stacktrace.h"
 
 #include "ardour/debug.h"
 #include "ardour/playlist.h"
@@ -110,30 +109,55 @@ RegionListProperty::RegionListProperty (Playlist& pl)
         : SequenceProperty<std::list<boost::shared_ptr<Region> > > (Properties::regions.property_id, boost::bind (&Playlist::update, &pl, _1))
         , _playlist (pl)
 {
+       
 }
 
-boost::shared_ptr<Region>
-RegionListProperty::lookup_id (const ID& id)
+RegionListProperty::RegionListProperty (RegionListProperty const & p)
+       : PBD::SequenceProperty<std::list<boost::shared_ptr<Region> > > (p)
+       , _playlist (p._playlist)
 {
-        boost::shared_ptr<Region> ret =  _playlist.region_by_id (id);
-        
-        if (!ret) {
-                ret = RegionFactory::region_by_id (id);
-        }
 
-        return ret;
 }
 
-RegionListProperty* RegionListProperty::clone () const
+RegionListProperty *
+RegionListProperty::clone () const
 {
        return new RegionListProperty (*this);
 }
 
-RegionListProperty* RegionListProperty::create () const
+RegionListProperty *
+RegionListProperty::create () const
 {
        return new RegionListProperty (_playlist);
 }
 
+void
+RegionListProperty::get_content_as_xml (boost::shared_ptr<Region> region, XMLNode & node) const
+{
+       /* All regions (even those which are deleted) have their state saved by other
+          code, so we can just store ID here.
+       */
+       
+       node.add_property ("id", region->id().to_s ());
+}
+
+boost::shared_ptr<Region>
+RegionListProperty::get_content_from_xml (XMLNode const & node) const
+{
+       XMLProperty const * prop = node.property ("id");
+       assert (prop);
+
+       PBD::ID id (prop->value ());
+
+        boost::shared_ptr<Region> ret = _playlist.region_by_id (id);
+        
+        if (!ret) {
+                ret = RegionFactory::region_by_id (id);
+        }
+
+        return ret;
+}
+
 Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
        : SessionObject(sess, nom)
         , regions (*this)
@@ -301,7 +325,7 @@ Playlist::copy_regions (RegionList& newlist) const
        RegionLock rlock (const_cast<Playlist *> (this));
 
        for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
-               newlist.push_back (RegionFactory::RegionFactory::create (*i));
+               newlist.push_back (RegionFactory::RegionFactory::create (*i, true));
        }
 }
 
@@ -521,7 +545,7 @@ Playlist::notify_region_added (boost::shared_ptr<Region> r)
        /* the length change might not be true, but we have to act
           as though it could be.
        */
-        
+
        if (holding_state()) {
                pending_adds.insert (r);
                pending_contents_change = true;
@@ -686,7 +710,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, flo
        */
 
        for (int i = 0; i < itimes; ++i) {
-               boost::shared_ptr<Region> copy = RegionFactory::create (region);
+               boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
                add_region_internal (copy, pos);
                pos += region->length();
        }
@@ -1224,14 +1248,14 @@ Playlist::paste (boost::shared_ptr<Playlist> other, framepos_t position, float t
 
                while (itimes--) {
                        for (RegionList::iterator i = other->regions.begin(); i != other->regions.end(); ++i) {
-                               boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i);
+                               boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i, true);
 
                                /* put these new regions on top of all existing ones, but preserve
                                   the ordering they had in the original playlist.
                                */
 
                                copy_of_region->set_layer (copy_of_region->layer() + top_layer);
-                               add_region_internal (copy_of_region, copy_of_region->position() + pos);
+                               add_region_internal (copy_of_region, (*i)->position() + pos);
                        }
                        pos += shift;
                }
@@ -1260,7 +1284,7 @@ Playlist::duplicate (boost::shared_ptr<Region> region, framepos_t position, floa
        framepos_t pos = position + 1;
 
        while (itimes--) {
-               boost::shared_ptr<Region> copy = RegionFactory::create (region);
+               boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
                add_region_internal (copy, pos);
                pos += region->length();
        }
@@ -1476,8 +1500,8 @@ Playlist::core_splice (framepos_t at, framecnt_t distance, boost::shared_ptr<Reg
                        framepos_t new_pos = (*i)->position() + distance;
                        if (new_pos < 0) {
                                new_pos = 0;
-                       } else if (new_pos >= max_frames - (*i)->length()) {
-                               new_pos = max_frames - (*i)->length();
+                       } else if (new_pos >= max_framepos - (*i)->length()) {
+                               new_pos = max_framepos - (*i)->length();
                        }
 
                        (*i)->set_position (new_pos, this);
@@ -1665,6 +1689,21 @@ Playlist::regions_at (framepos_t frame)
        return find_regions_at (frame);
 }
 
+uint32_t
+Playlist::count_regions_at (framepos_t frame)
+{
+       RegionLock rlock (this);
+       uint32_t cnt = 0;
+
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+               if ((*i)->covers (frame)) {
+                       cnt++;
+               }
+       }
+
+       return cnt;
+}
+
 boost::shared_ptr<Region>
 Playlist::top_region_at (framepos_t frame)
 
@@ -1945,7 +1984,7 @@ Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
 {
        RegionLock rlock (this);
        boost::shared_ptr<Region> ret;
-       framepos_t closest = max_frames;
+       framepos_t closest = max_framepos;
 
        bool end_iter = false;
 
@@ -1966,7 +2005,6 @@ Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
                        break;
                case SyncPoint:
                        pos = r->sync_position ();
-                       // r->adjust_to_sync (r->first_frame());
                        break;
                }
 
@@ -2007,7 +2045,7 @@ Playlist::find_next_region_boundary (framepos_t frame, int dir)
 {
        RegionLock rlock (this);
 
-       framepos_t closest = max_frames;
+       framepos_t closest = max_framepos;
        framepos_t ret = -1;
 
        if (dir > 0) {
@@ -2085,7 +2123,7 @@ Playlist::mark_session_dirty ()
 }
 
 void
-Playlist::rdiff (vector<StatefulDiffCommand*>& cmds) const
+Playlist::rdiff (vector<Command*>& cmds) const
 {
        RegionLock rlock (const_cast<Playlist *> (this));
        Stateful::rdiff (cmds);
@@ -2271,20 +2309,20 @@ Playlist::n_regions() const
        return regions.size();
 }
 
-pair<framecnt_t, framecnt_t>
+pair<framepos_t, framepos_t>
 Playlist::get_extent () const
 {
        RegionLock rlock (const_cast<Playlist *>(this), false);
        return _get_extent ();
 }
 
-pair<framecnt_t, framecnt_t>
+pair<framepos_t, framepos_t>
 Playlist::_get_extent () const
 {
-       pair<framecnt_t, framecnt_t> ext (max_frames, 0);
+       pair<framepos_t, framepos_t> ext (max_framepos, 0);
 
        for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
-               pair<framecnt_t, framecnt_t> const e ((*i)->position(), (*i)->position() + (*i)->length());
+               pair<framepos_t, framepos_t> const e ((*i)->position(), (*i)->position() + (*i)->length());
                if (e.first < ext.first) {
                        ext.first = e.first;
                }
@@ -2463,10 +2501,10 @@ Playlist::relayer ()
 void
 Playlist::raise_region (boost::shared_ptr<Region> region)
 {
-       uint32_t rsz = regions.size();
+       uint32_t top = regions.size() - 1;
        layer_t target = region->layer() + 1U;
 
-       if (target >= rsz) {
+       if (target >= top) {
                /* its already at the effective top */
                return;
        }
@@ -2588,6 +2626,8 @@ Playlist::move_region_to_layer (layer_t target_layer, boost::shared_ptr<Region>
                }
        }
 
+        freeze ();
+
        /* now reset the layers without holding the region lock */
 
        for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
@@ -2596,15 +2636,16 @@ Playlist::move_region_to_layer (layer_t target_layer, boost::shared_ptr<Region>
 
        region->set_layer (target_layer);
 
-#if 0
-       /* now check all dependents */
+        /* now check all dependents, since we changed the layering */
 
        for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
                check_dependents (x->first, false);
        }
 
        check_dependents (region, false);
-#endif
+        notify_layering_changed ();
+
+        thaw ();
 
        return 0;
 }
@@ -2628,8 +2669,8 @@ Playlist::nudge_after (framepos_t start, framecnt_t distance, bool forwards)
 
                                if (forwards) {
 
-                                       if ((*i)->last_frame() > max_frames - distance) {
-                                               new_pos = max_frames - (*i)->length();
+                                       if ((*i)->last_frame() > max_framepos - distance) {
+                                               new_pos = max_framepos - (*i)->length();
                                        } else {
                                                new_pos = (*i)->position() + distance;
                                        }
@@ -2672,8 +2713,23 @@ Playlist::find_region (const ID& id) const
        return boost::shared_ptr<Region> ();
 }
 
+uint32_t
+Playlist::region_use_count (boost::shared_ptr<Region> r) const
+{
+       RegionLock rlock (const_cast<Playlist*> (this));
+        uint32_t cnt = 0;
+
+       for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
+               if ((*i) == r) {
+                        cnt++;
+               }
+       }
+
+       return cnt;
+}
+
 boost::shared_ptr<Region>
-Playlist::region_by_id (const ID& id)
+Playlist::region_by_id (const ID& id) const
 {
        /* searches all regions ever added to this playlist */
 
@@ -2925,3 +2981,27 @@ Playlist::remove_region_by_source (boost::shared_ptr<Source> s)
                i = j;
        }
 }
+
+/** Look from a session frame time and find the start time of the next region
+ *  which is on the top layer of this playlist.
+ *  @param t Time to look from.
+ *  @return Position of next top-layered region, or max_framepos if there isn't one.
+ */
+framepos_t
+Playlist::find_next_top_layer_position (framepos_t t) const
+{
+       RegionLock rlock (const_cast<Playlist *> (this));
+       
+       layer_t const top = top_layer ();
+
+       RegionList copy = regions.rlist ();
+       copy.sort (RegionSortByPosition ());
+
+       for (RegionList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
+               if ((*i)->position() >= t && (*i)->layer() == top) {
+                       return (*i)->position();
+               }
+       }
+
+       return max_framepos;
+}