more combine/uncombine fixes including making uncombine push the compound region gain level into the constituents and doing the right thing when we uncombine in a playlist other than the one in which the compound region was created

git-svn-id: svn://localhost/ardour2/branches/3.0@9601 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-05-26 17:22:22 +00:00
parent 92ede6153e
commit d6be900da0
9 changed files with 90 additions and 69 deletions

View File

@ -2498,6 +2498,10 @@ RouteTimeAxisView::combine_regions ()
boost::shared_ptr<Playlist> playlist = track()->playlist();
_view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions));
if (selected_regions.size() < 2) {
return 0;
}
playlist->clear_changes ();
boost::shared_ptr<Region> compound_region = playlist->combine (selected_regions);

View File

@ -56,7 +56,7 @@ class AudioPlaylistSource : public AudioSource, public PlaylistSource {
protected:
friend class SourceFactory;
AudioPlaylistSource (Session&, const std::string& name, boost::shared_ptr<AudioPlaylist>, uint32_t chn,
AudioPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist>, uint32_t chn,
frameoffset_t begin, framecnt_t len, Source::Flag flags);
AudioPlaylistSource (Session&, const XMLNode&);

View File

@ -37,13 +37,15 @@ class PlaylistSource : virtual public Source {
int set_state (const XMLNode&, int version);
boost::shared_ptr<const Playlist> playlist() const { return _playlist; }
const PBD::ID& original() const { return _original; }
protected:
boost::shared_ptr<Playlist> _playlist;
frameoffset_t _playlist_offset;
framecnt_t _playlist_length;
boost::shared_ptr<Playlist> _playlist;
PBD::ID _original;
frameoffset_t _playlist_offset;
framecnt_t _playlist_length;
PlaylistSource (Session&, const std::string& name, boost::shared_ptr<Playlist>, DataType,
PlaylistSource (Session&, const PBD::ID&, const std::string& name, boost::shared_ptr<Playlist>, DataType,
frameoffset_t begin, framecnt_t len, Source::Flag flags);
PlaylistSource (Session&, const XMLNode&);

View File

@ -56,7 +56,7 @@ class SourceFactory {
static boost::shared_ptr<Source> createFromPlaylist
(DataType type, Session& s, boost::shared_ptr<Playlist> p, const std::string& name,
(DataType type, Session& s, boost::shared_ptr<Playlist> p, const PBD::ID& orig, const std::string& name,
uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks);
static Glib::Cond* PeaksToBuild;

View File

@ -1092,7 +1092,7 @@ AudioPlaylist::pre_combine (vector<boost::shared_ptr<Region> >& copies)
ar = boost::dynamic_pointer_cast<AudioRegion> (copies.front());
/* copy the fade in of the first into the compound region */
/* disable fade in of the first region */
if (ar) {
ar->set_fade_in_active (false);
@ -1100,6 +1100,8 @@ AudioPlaylist::pre_combine (vector<boost::shared_ptr<Region> >& copies)
ar = boost::dynamic_pointer_cast<AudioRegion> (copies.back());
/* disable fade out of the last region */
if (ar) {
ar->set_fade_out_active (false);
}
@ -1124,7 +1126,6 @@ AudioPlaylist::post_combine (vector<boost::shared_ptr<Region> >& originals, boos
if (ar) {
cr->set_fade_in (ar->fade_in());
ar->set_fade_in_active (false);
}
ar = boost::dynamic_pointer_cast<AudioRegion> (originals.back());
@ -1132,13 +1133,13 @@ AudioPlaylist::post_combine (vector<boost::shared_ptr<Region> >& originals, boos
if (ar) {
/* copy the fade out of the last into the compound region */
cr->set_fade_out (ar->fade_out());
ar->set_fade_out_active (false);
}
}
void
AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boost::shared_ptr<Region> compound_region)
{
RegionSortByPosition cmp;
boost::shared_ptr<AudioRegion> ar;
boost::shared_ptr<AudioRegion> cr = boost::dynamic_pointer_cast<AudioRegion>(compound_region);
@ -1146,41 +1147,53 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
return;
}
sort (originals.begin(), originals.end(), cmp);
/* no need to call clear_changes() on the originals because that is
* done within Playlist::uncombine ()
*/
if ((ar = boost::dynamic_pointer_cast<AudioRegion> (originals.front())) != 0) {
for (vector<boost::shared_ptr<Region> >::iterator i = originals.begin(); i != originals.end(); ++i) {
/* copy the compound region's fade in back into the first
original region.
*/
if (cr->fade_in()->back()->when <= ar->length()) {
/* don't do this if the fade is longer than the
* region
*/
ar->set_fade_in (cr->fade_in());
if ((ar = boost::dynamic_pointer_cast<AudioRegion> (*i)) == 0) {
continue;
}
ar->set_fade_in_active (true);
_session.add_command (new StatefulDiffCommand (originals.front()));
}
/* scale the uncombined regions by any gain setting for the
* compound one.
*/
if ((ar = boost::dynamic_pointer_cast<AudioRegion> (originals.back())) != 0) {
ar->set_scale_amplitude (ar->scale_amplitude() * cr->scale_amplitude());
/* copy the compound region's fade out back into the last
original region.
*/
if (i == originals.begin()) {
/* copy the compound region's fade in back into the first
original region.
*/
if (cr->fade_in()->back()->when <= ar->length()) {
/* don't do this if the fade is longer than the
* region
*/
ar->set_fade_in (cr->fade_in());
}
} else if (*i == originals.back()) {
/* copy the compound region's fade out back into the last
original region.
*/
if (cr->fade_out()->back()->when <= ar->length()) {
/* don't do this if the fade is longer than the
* region
*/
ar->set_fade_out (cr->fade_out());
}
if (cr->fade_out()->back()->when <= ar->length()) {
/* don't do this if the fade is longer than the
* region
*/
ar->set_fade_out (cr->fade_out());
}
ar->set_fade_out_active (true);
_session.add_command (new StatefulDiffCommand (originals.back()));
_session.add_command (new StatefulDiffCommand (*i));
}
}

View File

@ -46,11 +46,11 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
AudioPlaylistSource::AudioPlaylistSource (Session& s, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
: Source (s, DataType::AUDIO, name)
, AudioSource (s, name)
, PlaylistSource (s, name, p, DataType::AUDIO, begin, len, flags)
, PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
, _playlist_channel (chn)
{
AudioSource::_length = len;

View File

@ -3133,9 +3133,8 @@ Playlist::combine (const RegionList& r)
pair<framepos_t,framepos_t> extent = pl->get_extent();
for (uint32_t chn = 0; chn < channels; ++chn) {
sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, parent_name, chn, 0, extent.second, false, false));
sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, id(), parent_name, chn, 0, extent.second, false, false));
}
/* now a new whole-file region using the list of sources */
@ -3191,12 +3190,12 @@ Playlist::combine (const RegionList& r)
void
Playlist::uncombine (boost::shared_ptr<Region> target)
{
// (1) check that its really a compound region
boost::shared_ptr<PlaylistSource> pls;
boost::shared_ptr<const Playlist> pl;
vector<boost::shared_ptr<Region> > originals;
// (1) check that its really a compound region
if ((pls = boost::dynamic_pointer_cast<PlaylistSource>(target->source (0))) == 0) {
return;
}
@ -3215,14 +3214,23 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
the length of the region.
*/
cerr << "Compound region: bounds within nested playlist = " << adjusted_start << " .. " << adjusted_end << endl;
// (2) get all the original regions
const RegionList& rl (pl->region_list().rlist());
RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
frameoffset_t move_offset = 0;
/* there are two possibilities here:
1) the playlist that the playlist source was based on
is us, so just add the originals (which belonged to
us anyway) back in the right place.
2) the playlist that the playlist source was based on
is NOT us, so we need to make copies of each of
the original regions that we find, and add them
instead.
*/
bool same_playlist = (pls->original() == id());
for (RegionList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
@ -3239,19 +3247,18 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
if (i == rl.begin()) {
move_offset = (target->position() - original->position()) - target->start();
cerr << "Move offset is " << target->position() << " - " << original->position()
<< " - " << target->start() << " = " << move_offset
<< endl;
adjusted_start = original->position() + target->start();
adjusted_end = adjusted_start + target->length();
}
cerr << "adjusted range = " << adjusted_start << " based on "
<< original->position() << " + " << target->start() << " .. "
<< adjusted_end << " from " << target->length()
<< endl;
if (!same_playlist) {
framepos_t pos = original->position();
/* make a copy, but don't announce it */
original = RegionFactory::create (original, false);
/* the pure copy constructor resets position() to zero,
so fix that up.
*/
original->set_position (pos, this);
}
/* check to see how the original region (in the
@ -3259,12 +3266,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
* with the new state of the compound region.
*/
cerr << "Original " << original->name()
<< " overlaptype = " << enum_2_string (original->coverage (adjusted_start, adjusted_end))
<< " target range: " << adjusted_start << " .. " << adjusted_end
<< " orig range: " << original->position() << " .. " << original->last_frame ()
<< endl;
original->clear_changes ();
modified_region = false;
@ -3273,7 +3274,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
/* original region does not cover any part
of the current state of the compound region
*/
cerr << "Not present - skip\n";
continue;
case OverlapInternal:
@ -3282,14 +3282,12 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
*/
original->trim_to (adjusted_start, adjusted_end - adjusted_start, this);
modified_region = true;
cerr << "trim to\n";
break;
case OverlapExternal:
/* overlap fully covers original, so leave it
as is
*/
cerr << "leave as is\n";
break;
case OverlapEnd:
@ -3298,7 +3296,6 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
*/
original->trim_front (adjusted_start, this);
modified_region = true;
cerr << "trim front\n";
break;
case OverlapStart:
@ -3307,14 +3304,12 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
*/
original->trim_end (adjusted_end, this);
modified_region = true;
cerr << "trim end\n";
break;
}
if (move_offset) {
/* fix the position to match any movement of the compound region.
*/
cerr << "Moving region to new position based on " << original->position() << " + " << move_offset << endl;
original->set_position (original->position() + move_offset, this);
modified_region = true;
}
@ -3339,8 +3334,7 @@ Playlist::uncombine (boost::shared_ptr<Region> target)
remove_region (target);
// (4) add the originals. This will reset their playlist reference back
// to us, which means they are no longer considered owned by the RegionFactory
// (4) add the constituent regions
for (vector<boost::shared_ptr<Region> >::iterator i = originals.begin(); i != originals.end(); ++i) {
add_region ((*i), (*i)->position());

View File

@ -43,10 +43,11 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
PlaylistSource::PlaylistSource (Session& s, const std::string& name, boost::shared_ptr<Playlist> p, DataType type,
PlaylistSource::PlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<Playlist> p, DataType type,
frameoffset_t begin, framecnt_t len, Source::Flag flags)
: Source (s, type, name)
, _playlist (p)
, _original (orig)
{
/* PlaylistSources are never writable, renameable, removable or destructive */
_flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
@ -85,6 +86,7 @@ PlaylistSource::add_state (XMLNode& node)
node.add_property ("offset", buf);
snprintf (buf, sizeof (buf), "%" PRIu64, _playlist_length);
node.add_property ("length", buf);
node.add_property ("original", _id.to_s());
node.add_child_nocopy (_playlist->get_state());
}
@ -139,6 +141,12 @@ PlaylistSource::set_state (const XMLNode& node, int version)
sscanf (prop->value().c_str(), "%" PRIu64, &_playlist_length);
if ((prop = node.property (X_("original"))) == 0) {
throw failed_constructor ();
}
_id = prop->value();
_level = _playlist->max_source_level () + 1;
return 0;

View File

@ -347,7 +347,7 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
}
boost::shared_ptr<Source>
SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const std::string& name,
SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const ID& orig, const std::string& name,
uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
{
if (type == DataType::AUDIO) {
@ -362,7 +362,7 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<
start = 0;
}
Source* src = new AudioPlaylistSource (s, name, ap, chn, start, len, Source::Flag (0));
Source* src = new AudioPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
boost::shared_ptr<Source> ret (src);
if (setup_peakfile (ret, defer_peaks)) {