Create regions with property changes suspended
This fixes various issues with signal emission(s) when creating
regions from withing playlist operations.
eg. Playlist::duplicate() takes RegionWriteLock() and then calls
RegionFactory::create().
see also 6a82aa392c
This commit is contained in:
parent
61885f0284
commit
65cc9264c8
|
@ -53,6 +53,7 @@
|
|||
#include "ardour/data_type.h"
|
||||
#include "ardour/region.h"
|
||||
#include "ardour/session_object.h"
|
||||
#include "ardour/thawlist.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
@ -280,26 +281,6 @@ protected:
|
|||
friend class Session;
|
||||
|
||||
protected:
|
||||
class ThawList : public RegionList
|
||||
{
|
||||
public:
|
||||
void add (boost::shared_ptr<Region> r)
|
||||
{
|
||||
if (std::find (begin (), end (), r) != end ()) {
|
||||
return;
|
||||
}
|
||||
r->suspend_property_changes ();
|
||||
push_back (r);
|
||||
}
|
||||
|
||||
void release ()
|
||||
{
|
||||
for (RegionList::iterator i = begin (); i != end (); ++i) {
|
||||
(*i)->resume_property_changes ();
|
||||
}
|
||||
clear ();
|
||||
}
|
||||
};
|
||||
|
||||
class RegionReadLock : public Glib::Threads::RWLock::ReaderLock
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "pbd/signals.h"
|
||||
|
||||
#include "ardour/libardour_visibility.h"
|
||||
#include "ardour/thawlist.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
class XMLNode;
|
||||
|
@ -63,9 +64,11 @@ public:
|
|||
static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion;
|
||||
|
||||
/** create a "pure copy" of Region \p other */
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, bool fork = false);
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce, bool fork = false, ThawList* tl = 0);
|
||||
|
||||
/** Lua binding to create a "pure copy" of Region \p other */
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, bool announce, bool fork) {
|
||||
return create (boost::shared_ptr<const Region>(other), announce, fork);
|
||||
return create (boost::shared_ptr<const Region>(other), announce, fork, 0);
|
||||
}
|
||||
|
||||
/** create a region from a single Source */
|
||||
|
@ -77,10 +80,10 @@ public:
|
|||
const PBD::PropertyList&, bool announce = true);
|
||||
/** create a copy of \p other starting at zero within \p other's sources */
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other,
|
||||
const PBD::PropertyList&, bool announce = true);
|
||||
const PBD::PropertyList&, bool announce = true, ThawList* tl = 0);
|
||||
/** create a copy of \p other starting at \p offset within \p other */
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, ARDOUR::MusicSample offset,
|
||||
const PBD::PropertyList&, bool announce = true);
|
||||
const PBD::PropertyList&, bool announce = true, ThawList* tl = 0);
|
||||
/** create a "copy" of \p other but using a different set of sources \p srcs */
|
||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, const SourceList& srcs,
|
||||
const PBD::PropertyList&, bool announce = true);
|
||||
|
|
35
libs/ardour/ardour/thawlist.h
Normal file
35
libs/ardour/ardour/thawlist.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __ardour_thawlist_h__
|
||||
#define __ardour_thawlist_h__
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/libardour_visibility.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class LIBARDOUR_API ThawList : public RegionList
|
||||
{
|
||||
public:
|
||||
void add (boost::shared_ptr<Region> r);
|
||||
void release ();
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -284,7 +284,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, samplepos_t start,
|
|||
plist.add (Properties::layer, region->layer ());
|
||||
plist.add (Properties::layering_index, region->layering_index ());
|
||||
|
||||
new_region = RegionFactory::create (region, plist);
|
||||
new_region = RegionFactory::create (region, plist, true, &thawlist);
|
||||
|
||||
add_region_internal (new_region, position, thawlist);
|
||||
}
|
||||
|
@ -717,7 +717,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, samplepos_t position, fl
|
|||
*/
|
||||
|
||||
for (int i = 0; i < itimes; ++i) {
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true, false, &rlock.thawlist);
|
||||
add_region_internal (copy, pos, rlock.thawlist, sub_num);
|
||||
set_layer (copy, DBL_MAX);
|
||||
pos += region->length ();
|
||||
|
@ -738,7 +738,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, samplepos_t position, fl
|
|||
plist.add (Properties::name, name);
|
||||
plist.add (Properties::layer, region->layer ());
|
||||
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist, true, &rlock.thawlist);
|
||||
add_region_internal (sub, pos, rlock.thawlist, sub_num);
|
||||
set_layer (sub, DBL_MAX);
|
||||
}
|
||||
|
@ -1035,7 +1035,7 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting,
|
|||
/* see note in :_split_region()
|
||||
* for MusicSample is needed to offset region-gain
|
||||
*/
|
||||
region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist);
|
||||
region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist, true, &thawlist);
|
||||
add_region_internal (region, start, thawlist);
|
||||
new_regions.push_back (region);
|
||||
}
|
||||
|
@ -1055,7 +1055,7 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting,
|
|||
plist.add (Properties::right_of_split, true);
|
||||
maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start () + (pos3 - pos1));
|
||||
|
||||
region = RegionFactory::create (current, MusicSample (pos3 - pos1, 0), plist);
|
||||
region = RegionFactory::create (current, MusicSample (pos3 - pos1, 0), plist, true, &thawlist);
|
||||
|
||||
add_region_internal (region, end, thawlist);
|
||||
new_regions.push_back (region);
|
||||
|
@ -1093,7 +1093,7 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting,
|
|||
plist.add (Properties::left_of_split, true);
|
||||
maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start () + (pos2 - pos1));
|
||||
|
||||
region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist);
|
||||
region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist, true, &thawlist);
|
||||
|
||||
add_region_internal (region, start, thawlist);
|
||||
new_regions.push_back (region);
|
||||
|
@ -1135,7 +1135,7 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting,
|
|||
plist.add (Properties::right_of_split, true);
|
||||
maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start ());
|
||||
|
||||
region = RegionFactory::create (current, plist);
|
||||
region = RegionFactory::create (current, plist, true, &thawlist);
|
||||
|
||||
add_region_internal (region, pos1, thawlist);
|
||||
new_regions.push_back (region);
|
||||
|
@ -1279,7 +1279,7 @@ Playlist::paste (boost::shared_ptr<Playlist> other, samplepos_t position, float
|
|||
RegionWriteLock rl1 (this);
|
||||
while (itimes--) {
|
||||
for (RegionList::iterator i = other->regions.begin (); i != other->regions.end (); ++i) {
|
||||
boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i, true);
|
||||
boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i, true, false, &rl1.thawlist);
|
||||
|
||||
/* put these new regions on top of all existing ones, but preserve
|
||||
the ordering they had in the original playlist.
|
||||
|
@ -1312,7 +1312,7 @@ Playlist::duplicate (boost::shared_ptr<Region> region, samplepos_t position, sam
|
|||
int itimes = (int)floor (times);
|
||||
|
||||
while (itimes--) {
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true, false, &rl.thawlist);
|
||||
add_region_internal (copy, position, rl.thawlist);
|
||||
set_layer (copy, DBL_MAX);
|
||||
position += gap;
|
||||
|
@ -1330,7 +1330,7 @@ Playlist::duplicate (boost::shared_ptr<Region> region, samplepos_t position, sam
|
|||
plist.add (Properties::length, length);
|
||||
plist.add (Properties::name, name);
|
||||
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist, true, &rl.thawlist);
|
||||
add_region_internal (sub, position, rl.thawlist);
|
||||
set_layer (sub, DBL_MAX);
|
||||
}
|
||||
|
@ -1345,7 +1345,7 @@ Playlist::duplicate_until (boost::shared_ptr<Region> region, samplepos_t positio
|
|||
RegionWriteLock rl (this);
|
||||
|
||||
while (position + region->length () - 1 < end) {
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
|
||||
boost::shared_ptr<Region> copy = RegionFactory::create (region, true, false, &rl.thawlist);
|
||||
add_region_internal (copy, position, rl.thawlist);
|
||||
set_layer (copy, DBL_MAX);
|
||||
position += gap;
|
||||
|
@ -1363,7 +1363,7 @@ Playlist::duplicate_until (boost::shared_ptr<Region> region, samplepos_t positio
|
|||
plist.add (Properties::length, length);
|
||||
plist.add (Properties::name, name);
|
||||
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
|
||||
boost::shared_ptr<Region> sub = RegionFactory::create (region, plist, false, &rl.thawlist);
|
||||
add_region_internal (sub, position, rl.thawlist);
|
||||
set_layer (sub, DBL_MAX);
|
||||
}
|
||||
|
@ -1508,7 +1508,7 @@ Playlist::_split_region (boost::shared_ptr<Region> region, const MusicSample& pl
|
|||
* since it supplies that offset to the Region constructor, which
|
||||
* is necessary to get audio region gain envelopes right.
|
||||
*/
|
||||
left = RegionFactory::create (region, MusicSample (0, 0), plist, true);
|
||||
left = RegionFactory::create (region, MusicSample (0, 0), plist, true, &thawlist);
|
||||
}
|
||||
|
||||
RegionFactory::region_name (after_name, region->name (), false);
|
||||
|
@ -1523,7 +1523,7 @@ Playlist::_split_region (boost::shared_ptr<Region> region, const MusicSample& pl
|
|||
plist.add (Properties::layer, region->layer ());
|
||||
|
||||
/* same note as above */
|
||||
right = RegionFactory::create (region, before, plist, true);
|
||||
right = RegionFactory::create (region, before, plist, true, &thawlist);
|
||||
}
|
||||
|
||||
add_region_internal (left, region->position (), thawlist, 0);
|
||||
|
|
|
@ -51,7 +51,7 @@ std::map<std::string, PBD::ID> RegionFactory::region_name_map;
|
|||
RegionFactory::CompoundAssociations RegionFactory::_compound_associations;
|
||||
|
||||
boost::shared_ptr<Region>
|
||||
RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bool fork)
|
||||
RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bool fork, ThawList* tl)
|
||||
{
|
||||
boost::shared_ptr<Region> ret;
|
||||
boost::shared_ptr<const AudioRegion> ar;
|
||||
|
@ -86,6 +86,11 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bo
|
|||
}
|
||||
|
||||
if (ret) {
|
||||
if (tl) {
|
||||
ret->suspend_property_changes ();
|
||||
tl->add (ret);
|
||||
}
|
||||
|
||||
ret->set_name (new_region_name(ret->name()));
|
||||
|
||||
if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_lock_style() != MusicTime) {
|
||||
|
@ -104,7 +109,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, bo
|
|||
}
|
||||
|
||||
boost::shared_ptr<Region>
|
||||
RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& plist, bool announce)
|
||||
RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& plist, bool announce, ThawList* tl)
|
||||
{
|
||||
boost::shared_ptr<Region> ret;
|
||||
boost::shared_ptr<const AudioRegion> other_a;
|
||||
|
@ -126,6 +131,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
|
|||
}
|
||||
|
||||
if (ret) {
|
||||
if (tl) {
|
||||
ret->suspend_property_changes ();
|
||||
tl->add (ret);
|
||||
}
|
||||
|
||||
ret->apply_changes (plist);
|
||||
|
||||
if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_lock_style() != MusicTime) {
|
||||
|
@ -143,7 +153,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
|
|||
}
|
||||
|
||||
boost::shared_ptr<Region>
|
||||
RegionFactory::create (boost::shared_ptr<Region> region, MusicSample offset, const PropertyList& plist, bool announce)
|
||||
RegionFactory::create (boost::shared_ptr<Region> region, MusicSample offset, const PropertyList& plist, bool announce, ThawList* tl)
|
||||
{
|
||||
boost::shared_ptr<Region> ret;
|
||||
boost::shared_ptr<const AudioRegion> other_a;
|
||||
|
@ -165,6 +175,10 @@ RegionFactory::create (boost::shared_ptr<Region> region, MusicSample offset, con
|
|||
}
|
||||
|
||||
if (ret) {
|
||||
if (tl) {
|
||||
ret->suspend_property_changes ();
|
||||
tl->add (ret);
|
||||
}
|
||||
ret->apply_changes (plist);
|
||||
|
||||
if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_lock_style() != MusicTime) {
|
||||
|
|
43
libs/ardour/thawlist.cc
Normal file
43
libs/ardour/thawlist.cc
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "ardour/region.h"
|
||||
#include "ardour/thawlist.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
void
|
||||
ThawList::add (boost::shared_ptr<Region> r)
|
||||
{
|
||||
if (std::find (begin (), end (), r) != end ()) {
|
||||
return;
|
||||
}
|
||||
r->suspend_property_changes ();
|
||||
push_back (r);
|
||||
}
|
||||
|
||||
void
|
||||
ThawList::release ()
|
||||
{
|
||||
for (RegionList::iterator i = begin (); i != end (); ++i) {
|
||||
(*i)->resume_property_changes ();
|
||||
}
|
||||
clear ();
|
||||
}
|
|
@ -252,6 +252,7 @@ libardour_sources = [
|
|||
'template_utils.cc',
|
||||
'tempo.cc',
|
||||
'tempo_map_importer.cc',
|
||||
'thawlist.cc',
|
||||
'thread_buffers.cc',
|
||||
'ticker.cc',
|
||||
'track.cc',
|
||||
|
|
Loading…
Reference in New Issue
Block a user