Set up layering_index immediately on an explicit layer, so that undo

works properly.  Stop the layer being a stateful property, as it is
always derived from layering_index, unambigiously, by relayer().


git-svn-id: svn://localhost/ardour2/branches/3.0@11120 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2011-12-30 20:05:48 +00:00
parent 2c23ff8ceb
commit dd53e7284a
9 changed files with 83 additions and 105 deletions

View File

@ -1047,7 +1047,7 @@ RegionMoveDrag::finished_no_copy (
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
if (dest_rtv->view()->layer_display() == Stacked || dest_rtv->view()->layer_display() == Expanded) {
rv->region()->set_pending_layer (dest_layer);
playlist->set_layer (rv->region(), dest_layer);
}
/* freeze playlist to avoid lots of relayering in the case of a multi-region drag */
@ -1192,7 +1192,7 @@ RegionMoveDrag::insert_region_into_playlist (
dest_playlist->add_region (region, where);
if (dest_rtv->view()->layer_display() == Stacked || dest_rtv->view()->layer_display() == Expanded) {
region->set_pending_layer (dest_layer);
dest_playlist->set_layer (region, dest_layer);
}
c.disconnect ();

View File

@ -223,6 +223,8 @@ public:
uint32_t combine_ops() const { return _combine_ops; }
uint64_t highest_layering_index () const;
void set_layer (boost::shared_ptr<Region>, double);
protected:
friend class Session;
@ -271,7 +273,7 @@ public:
bool save_on_thaw;
std::string last_save_reason;
uint32_t in_set_state;
bool in_update;
bool in_undo;
bool first_set_state;
bool _hidden;
bool _splicing;

View File

@ -294,10 +294,6 @@ class Region
void invalidate_transients ();
void set_pending_layer (double);
bool reset_pending_layer ();
boost::optional<double> pending_layer () const;
void drop_sources ();
protected:
@ -341,7 +337,6 @@ class Region
PBD::Property<framepos_t> _position;
/** Sync position relative to the start of our file */
PBD::Property<framepos_t> _sync_position;
PBD::Property<layer_t> _layer;
SourceList _sources;
/** Used when timefx are applied, so we can always use the original source */
@ -389,8 +384,7 @@ class Region
framepos_t _last_position;
mutable RegionEditState _first_edit;
Timecode::BBT_Time _bbt_time;
boost::optional<double> _pending_layer;
layer_t _layer;
void register_properties ();

View File

@ -1511,8 +1511,8 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
i_am_the_modifier++;
region->set_pending_layer (max_layer);
_playlist->add_region (region, (*ci)->start, 1, non_layered());
_playlist->set_layer (region, DBL_MAX);
i_am_the_modifier--;
buffer_position += (*ci)->frames;

View File

@ -113,6 +113,8 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden
throw failed_constructor();
}
in_set_state--;
relayer ();
}
AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)

View File

@ -1071,7 +1071,7 @@ AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr
plist.add (Properties::start, _start.val());
plist.add (Properties::length, _length.val());
plist.add (Properties::name, new_name);
plist.add (Properties::layer, _layer.val());
plist.add (Properties::layer, layer ());
v.push_back(RegionFactory::create (srcs, plist));
v.back()->set_whole_file (false);

View File

@ -57,6 +57,8 @@ MidiPlaylist::MidiPlaylist (Session& session, const XMLNode& node, bool hidden)
throw failed_constructor ();
}
in_set_state--;
relayer ();
}
MidiPlaylist::MidiPlaylist (Session& session, string name, bool hidden)

View File

@ -310,7 +310,7 @@ Playlist::init (bool hide)
_shuffling = false;
_nudging = false;
in_set_state = 0;
in_update = false;
in_undo = false;
_edit_mode = Config->get_edit_mode();
in_flush = false;
in_partition = false;
@ -396,7 +396,7 @@ Playlist::set_name (const string& str)
void
Playlist::begin_undo ()
{
in_update = true;
in_undo = true;
freeze ();
}
@ -404,7 +404,7 @@ void
Playlist::end_undo ()
{
thaw (true);
in_update = false;
in_undo = false;
}
void
@ -563,7 +563,7 @@ Playlist::flush_notifications (bool from_undo)
{
set<boost::shared_ptr<Region> > dependent_checks_needed;
set<boost::shared_ptr<Region> >::iterator s;
uint32_t regions_changed = false;
bool regions_changed = false;
if (in_flush) {
return;
@ -603,14 +603,17 @@ Playlist::flush_notifications (bool from_undo)
dependent_checks_needed.insert (*s);
}
if (
((regions_changed || pending_contents_change) && !in_set_state) ||
pending_layering
) {
relayer ();
}
if (regions_changed || pending_contents_change) {
if (!in_set_state) {
relayer ();
}
pending_contents_change = false;
// cerr << _name << " sends 5 contents change @ " << get_microseconds() << endl;
ContentsChanged (); /* EMIT SIGNAL */
// cerr << _name << "done contents change @ " << get_microseconds() << endl;
}
for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
@ -665,8 +668,8 @@ Playlist::flush_notifications (bool from_undo)
}
if (itimes >= 1) {
region->set_pending_layer (DBL_MAX);
add_region_internal (region, pos);
set_layer (region, DBL_MAX);
pos += region->length();
--itimes;
}
@ -678,8 +681,8 @@ Playlist::flush_notifications (bool from_undo)
for (int i = 0; i < itimes; ++i) {
boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
copy->set_pending_layer (DBL_MAX);
add_region_internal (copy, pos);
set_layer (copy, DBL_MAX);
pos += region->length();
}
@ -699,8 +702,8 @@ Playlist::flush_notifications (bool from_undo)
plist.add (Properties::layer, region->layer());
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
sub->set_pending_layer (DBL_MAX);
add_region_internal (sub, pos);
set_layer (sub, DBL_MAX);
}
}
@ -767,8 +770,8 @@ Playlist::flush_notifications (bool from_undo)
_splicing = true;
remove_region_internal (old);
newr->set_pending_layer (newr->layer ());
add_region_internal (newr, pos);
set_layer (newr, old->layer ());
_splicing = old_sp;
@ -1207,8 +1210,8 @@ Playlist::flush_notifications (bool from_undo)
the ordering they had in the original playlist.
*/
copy_of_region->set_pending_layer (copy_of_region->layer() + top);
add_region_internal (copy_of_region, (*i)->position() + pos);
set_layer (copy_of_region, copy_of_region->layer() + top);
}
pos += shift;
}
@ -1229,8 +1232,8 @@ Playlist::flush_notifications (bool from_undo)
while (itimes--) {
boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
copy->set_pending_layer (DBL_MAX);
add_region_internal (copy, pos);
set_layer (copy, DBL_MAX);
pos += region->length();
}
@ -1247,8 +1250,8 @@ Playlist::flush_notifications (bool from_undo)
plist.add (Properties::name, name);
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
sub->set_pending_layer (DBL_MAX);
add_region_internal (sub, pos);
set_layer (sub, DBL_MAX);
}
}
}
@ -2185,7 +2188,10 @@ Playlist::flush_notifications (bool from_undo)
return -1;
}
add_region (region, region->position(), 1.0);
{
RegionLock rlock (this);
add_region_internal (region, region->position());
}
region->resume_property_changes ();
@ -2210,6 +2216,7 @@ Playlist::flush_notifications (bool from_undo)
in_set_state--;
first_set_state = false;
return ret;
}
@ -2340,12 +2347,46 @@ struct RelayerSort {
}
};
/** Set a new layer for a region. This adjusts the layering indices of all
* regions in the playlist to put the specified region in the appropriate
* place. The actual layering will be fixed up when relayer() happens.
*/
void
Playlist::set_layer (boost::shared_ptr<Region> region, double new_layer)
{
/* Remove the layer we are setting from our region list, and sort it */
RegionList copy = regions.rlist();
copy.remove (region);
copy.sort (RelayerSort ());
/* Put region back in the right place */
RegionList::iterator i = copy.begin();
while (i != copy.end ()) {
if ((*i)->layer() > new_layer) {
break;
}
++i;
}
copy.insert (i, region);
/* Then re-write layering indices */
uint64_t j = 0;
for (RegionList::iterator k = copy.begin(); k != copy.end(); ++k) {
(*k)->set_layering_index (j++);
}
}
/** Take the layering indices of each of our regions, compute the layers
* that they should be on, and write the layers back to the regions.
*/
void
Playlist::relayer ()
{
/* never compute layers when changing state for undo/redo or setting from XML */
/* never compute layers when setting from XML */
if (in_update || in_set_state) {
if (in_set_state) {
return;
}
@ -2373,47 +2414,12 @@ Playlist::relayer ()
vector<vector<RegionList> > layers;
layers.push_back (vector<RegionList> (divisions));
/* Sort our regions into layering index order */
RegionList copy = regions.rlist();
RegionList pending;
/* Remove regions with pending relayers */
for (RegionList::iterator i = copy.begin(); i != copy.end(); ) {
RegionList::iterator j = i;
++j;
if ((*i)->pending_layer()) {
pending.push_back (*i);
copy.erase (i);
}
i = j;
}
/* Sort the remainder */
copy.sort (RelayerSort ());
/* Re-insert the pending layers in the right places */
for (RegionList::iterator i = pending.begin(); i != pending.end(); ++i) {
RegionList::iterator j = copy.begin();
while (j != copy.end ()) {
if ((*j)->pending_layer().get_value_or ((*j)->layer ()) > (*i)->pending_layer().get ()) {
break;
}
++j;
}
copy.insert (j, *i);
}
bool had_pending = false;
for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
/* reset the pending layer for every region now that we're relayering */
if ((*i)->reset_pending_layer ()) {
had_pending = true;
}
/* find the time divisions that this region covers; if there are no regions on the list,
division_size will equal 0 and in this case we'll just say that
start_division = end_division = 0.
@ -2482,40 +2488,33 @@ Playlist::relayer ()
if (changed) {
notify_layering_changed ();
}
if (had_pending) {
uint64_t i = 0;
for (RegionList::iterator j = copy.begin(); j != copy.end(); ++j) {
(*j)->set_layering_index (i++);
}
}
}
void
Playlist::raise_region (boost::shared_ptr<Region> region)
{
region->set_pending_layer (region->layer() + 1.5);
set_layer (region, region->layer() + 1.5);
relayer ();
}
void
Playlist::lower_region (boost::shared_ptr<Region> region)
{
region->set_pending_layer (region->layer() - 1.5);
set_layer (region, region->layer() - 1.5);
relayer ();
}
void
Playlist::raise_region_to_top (boost::shared_ptr<Region> region)
{
region->set_pending_layer (DBL_MAX);
set_layer (region, DBL_MAX);
relayer ();
}
void
Playlist::lower_region_to_bottom (boost::shared_ptr<Region> region)
{
region->set_pending_layer (-0.5);
set_layer (region, -0.5);
relayer ();
}

View File

@ -154,7 +154,6 @@ Region::register_properties ()
add_property (_length);
add_property (_position);
add_property (_sync_position);
add_property (_layer);
add_property (_ancestral_start);
add_property (_ancestral_length);
add_property (_stretch);
@ -172,7 +171,6 @@ Region::register_properties ()
, _length (Properties::length, (l)) \
, _position (Properties::position, 0) \
, _sync_position (Properties::sync_position, (s)) \
, _layer (Properties::layer, 0) \
, _muted (Properties::muted, false) \
, _opaque (Properties::opaque, true) \
, _locked (Properties::locked, false) \
@ -198,7 +196,6 @@ Region::register_properties ()
, _length(Properties::length, other->_length) \
, _position(Properties::position, other->_position) \
, _sync_position(Properties::sync_position, other->_sync_position) \
, _layer (Properties::layer, other->_layer) \
, _muted (Properties::muted, other->_muted) \
, _opaque (Properties::opaque, other->_opaque) \
, _locked (Properties::locked, other->_locked) \
@ -223,6 +220,7 @@ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& n
, _last_length (length)
, _last_position (0)
, _first_edit (EditChangesNothing)
, _layer (0)
{
register_properties ();
@ -237,6 +235,7 @@ Region::Region (const SourceList& srcs)
, _last_length (0)
, _last_position (0)
, _first_edit (EditChangesNothing)
, _layer (0)
{
register_properties ();
@ -256,6 +255,7 @@ Region::Region (boost::shared_ptr<const Region> other)
, _last_length (other->_last_length)
, _last_position(other->_last_position) \
, _first_edit (EditChangesNothing)
, _layer (other->_layer)
{
register_properties ();
@ -325,6 +325,7 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset)
, _last_length (other->_last_length)
, _last_position(other->_last_position) \
, _first_edit (EditChangesNothing)
, _layer (other->_layer)
{
register_properties ();
@ -379,6 +380,7 @@ Region::Region (boost::shared_ptr<const Region> other, const SourceList& srcs)
, _last_length (other->_last_length)
, _last_position (other->_last_position)
, _first_edit (EditChangesID)
, _layer (other->_layer)
{
register_properties ();
@ -1115,11 +1117,7 @@ Region::lower_to_bottom ()
void
Region::set_layer (layer_t l)
{
if (_layer != l) {
_layer = l;
send_change (Properties::layer);
}
_layer = l;
}
XMLNode&
@ -1650,22 +1648,3 @@ Region::post_set (const PropertyChange& pc)
}
}
void
Region::set_pending_layer (double l)
{
_pending_layer = l;
}
bool
Region::reset_pending_layer ()
{
bool const had = _pending_layer;
_pending_layer = boost::optional<double> ();
return had;
}
boost::optional<double>
Region::pending_layer () const
{
return _pending_layer;
}