*/
-#define __STDC_LIMIT_MACROS
#include <stdint.h>
-
#include <set>
#include <fstream>
#include <algorithm>
#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"
: 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::copy_for_history () const
+RegionListProperty *
+RegionListProperty::clone () const
+{
+ return new RegionListProperty (*this);
+}
+
+RegionListProperty *
+RegionListProperty::create () const
{
- RegionListProperty* copy = new RegionListProperty (_playlist);
- /* this is all we need */
- copy->_change = _change;
- return copy;
+ return new RegionListProperty (_playlist);
}
-void
-RegionListProperty::diff (PropertyList& undo, PropertyList& redo, Command* cmd) const
+void
+RegionListProperty::get_content_as_xml (boost::shared_ptr<Region> region, XMLNode & node) const
{
- if (changed()) {
- /* list of the removed/added regions since clear_history() was last called */
- RegionListProperty* a = copy_for_history ();
+ /* 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 ());
+}
- /* the same list, but with removed/added lists swapped (for undo purposes) */
- RegionListProperty* b = copy_for_history ();
- b->invert_changes ();
+boost::shared_ptr<Region>
+RegionListProperty::get_content_from_xml (XMLNode const & node) const
+{
+ XMLProperty const * prop = node.property ("id");
+ assert (prop);
- if (cmd) {
- /* whenever one of the regions emits DropReferences, make sure
- that the Destructible we've been told to notify hears about
- it. the Destructible is likely to be the Command being built
- with this diff().
- */
-
- for (set<boost::shared_ptr<Region> >::iterator i = a->change().added.begin(); i != a->change().added.end(); ++i) {
- (*i)->DropReferences.connect_same_thread (*cmd, boost::bind (&Destructible::drop_references, cmd));
- }
- }
+ PBD::ID id (prop->value ());
- undo.add (b);
- redo.add (a);
+ 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)
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));
}
}
/* 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;
pending_length = true;
} else {
- r->clear_history ();
+ r->clear_changes ();
pending_length = false;
LengthChanged (); /* EMIT SIGNAL */
pending_contents_change = false;
}
for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
- (*s)->clear_history ();
+ (*s)->clear_changes ();
RegionAdded (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
}
*/
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();
}
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;
}
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();
}
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);
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)
{
RegionLock rlock (this);
boost::shared_ptr<Region> ret;
- framepos_t closest = max_frames;
+ framepos_t closest = max_framepos;
bool end_iter = false;
break;
case SyncPoint:
pos = r->sync_position ();
- // r->adjust_to_sync (r->first_frame());
break;
}
{
RegionLock rlock (this);
- framepos_t closest = max_frames;
+ framepos_t closest = max_framepos;
framepos_t ret = -1;
if (dir > 0) {
}
}
-bool
-Playlist::set_property (const PropertyBase& prop)
-{
- if (prop == Properties::regions.property_id) {
- const RegionListProperty::ChangeRecord& change (dynamic_cast<const RegionListProperty*>(&prop)->change());
- regions.update (change);
- return (!change.added.empty() && !change.removed.empty());
- }
- return false;
-}
-
void
-Playlist::rdiff (vector<StatefulDiffCommand*>& cmds) const
+Playlist::rdiff (vector<Command*>& cmds) const
{
RegionLock rlock (const_cast<Playlist *> (this));
-
- for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
- if ((*i)->changed ()) {
- StatefulDiffCommand* sdc = new StatefulDiffCommand (*i);
- cmds.push_back (sdc);
- }
- }
+ Stateful::rdiff (cmds);
}
void
-Playlist::clear_owned_history ()
+Playlist::clear_owned_changes ()
{
RegionLock rlock (this);
-
- for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
- (*i)->clear_history ();
- }
+ Stateful::clear_owned_changes ();
}
void
thaw ();
}
-PropertyList*
-Playlist::property_factory (const XMLNode& history_node) const
-{
- const XMLNodeList& children (history_node.children());
- PropertyList* prop_list = 0;
-
- for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
-
- if ((*i)->name() == capitalize (regions.property_name())) {
-
- RegionListProperty* rlp = new RegionListProperty (*const_cast<Playlist*> (this));
-
- if (rlp->load_history_state (**i)) {
- if (!prop_list) {
- prop_list = new PropertyList();
- }
- prop_list->add (rlp);
- } else {
- delete rlp;
- }
- }
- }
-
- return prop_list;
-}
-
int
Playlist::set_state (const XMLNode& node, int version)
{
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;
}
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;
}
}
}
+ freeze ();
+
/* now reset the layers without holding the region lock */
for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
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;
}
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;
}
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 */
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;
+}