libardour: remove ripple callback API, and fix deadlock issues with ripple/ripple_locked/ripple_unlocked/remove_gaps

This commit is contained in:
Paul Davis 2021-06-02 16:33:27 -06:00
parent 8e2c5239c4
commit a2b3e31e10
2 changed files with 64 additions and 57 deletions

View file

@ -191,16 +191,14 @@ public:
void shuffle (boost::shared_ptr<Region>, int dir);
typedef boost::function<void (Playlist&, samplepos_t, samplecnt_t)> RippleCallback;
void ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback ripple_callback);
void ripple (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude, RippleCallback ripple_callback)
void ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude);
void ripple (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude)
{
RegionList el;
if (exclude) {
el.push_back (exclude);
}
ripple (at, distance, &el, ripple_callback);
ripple (at, distance, &el);
}
void update_after_tempo_map_change ();
@ -305,24 +303,24 @@ protected:
friend class Session;
protected:
class RegionReadLock : public Glib::Threads::RWLock::ReaderLock
{
public:
RegionReadLock (Playlist* pl)
: Glib::Threads::RWLock::ReaderLock (pl->region_lock)
: Glib::Threads::RWLock::ReaderLock (pl->region_lock)
{
}
~RegionReadLock () {}
};
class RegionWriteLock : public Glib::Threads::RWLock::WriterLock
{
public:
RegionWriteLock (Playlist* pl, bool do_block_notify = true)
: Glib::Threads::RWLock::WriterLock (pl->region_lock)
, playlist (pl)
, block_notify (do_block_notify)
: Glib::Threads::RWLock::WriterLock (pl->region_lock)
, playlist (pl)
, block_notify (do_block_notify)
{
if (block_notify) {
playlist->delay_notifications ();
@ -429,8 +427,8 @@ protected:
void splice_locked (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude);
void splice_unlocked (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude, ThawList& thawlist);
void ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback);
void ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback, ThawList& thawlist, bool notify = true);
void ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude);
bool ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, ThawList& thawlist);
virtual void remove_dependents (boost::shared_ptr<Region> /*region*/) {}
virtual void region_going_away (boost::weak_ptr<Region> /*region*/) {}

View file

@ -874,44 +874,46 @@ Playlist::remove_region_internal (boost::shared_ptr<Region> region, ThawList& th
void
Playlist::remove_gaps (samplepos_t gap_threshold, samplepos_t leave_gap, boost::function<void (samplepos_t, samplecnt_t)> gap_callback)
{
RegionWriteLock rlock (this);
RegionList::iterator i;
RegionList::iterator nxt (regions.end());
bool closed = false;
RippleCallback null_ripple_callback;
if (regions.size() < 2) {
return;
}
{
RegionWriteLock rlock (this);
RegionList::iterator i;
RegionList::iterator nxt (regions.end());
for (i = regions.begin(); i != regions.end(); ++i) {
nxt = i;
++nxt;
if (nxt == regions.end()) {
break;
if (regions.size() < 2) {
return;
}
samplepos_t end_of_this_region = (*i)->position() + (*i)->length();
for (i = regions.begin(); i != regions.end(); ++i) {
if (end_of_this_region >= (*nxt)->position()) {
continue;
nxt = i;
++nxt;
if (nxt == regions.end()) {
break;
}
samplepos_t end_of_this_region = (*i)->position() + (*i)->length();
if (end_of_this_region >= (*nxt)->position()) {
continue;
}
const samplepos_t gap = (*nxt)->position() - end_of_this_region;
if (gap < gap_threshold) {
continue;
}
const samplepos_t shift = gap - leave_gap;
(void) ripple_unlocked ((*nxt)->position(), -shift, 0, rlock.thawlist);
gap_callback ((*nxt)->position(), shift);
closed = true;
}
const samplepos_t gap = (*nxt)->position() - end_of_this_region;
if (gap < gap_threshold) {
continue;
}
const samplepos_t shift = gap - leave_gap;
ripple_unlocked ((*nxt)->position(), -shift, 0, null_ripple_callback, rlock.thawlist, false);
gap_callback ((*nxt)->position(), shift);
closed = true;
}
if (closed) {
@ -1654,23 +1656,33 @@ Playlist::splice_unlocked (samplepos_t at, samplecnt_t distance, boost::shared_p
}
void
Playlist::ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback ripple_callback)
Playlist::ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude)
{
ripple_locked (at, distance, exclude, ripple_callback);
ripple_locked (at, distance, exclude);
}
void
Playlist::ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback ripple_callback)
Playlist::ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude)
{
RegionWriteLock rl (this);
ripple_unlocked (at, distance, exclude, ripple_callback, rl.thawlist);
bool changed = false;
{
RegionWriteLock rl (this);
changed = ripple_unlocked (at, distance, exclude, rl.thawlist);
}
if (changed) {
notify_contents_changed ();
}
}
void
Playlist::ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, RippleCallback ripple_callback, ThawList& thawlist, bool notify)
bool
Playlist::ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, ThawList& thawlist)
{
if (distance == 0) {
return;
bool changed = false;
if (distance == 0 || regions.empty()) {
return false;
}
_rippling = true;
@ -1695,16 +1707,13 @@ Playlist::ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exc
thawlist.add (*i);
(*i)->set_position (new_pos);
changed = true;
}
}
_rippling = false;
ripple_callback (*this, at, distance);
if (notify) {
notify_contents_changed ();
}
return changed;
}
void