From 4650912ae36ef79fd342a6e183e0bc205d3326c2 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 6 Dec 2014 13:37:08 -0500 Subject: [PATCH] Adapt range when copying between automation types. For things like copying from pitch bender to a CC. Also things like fader to pan, but that seems a bit funny. The conversion probably needs to be a bit smarter here, perhaps taking the normal into consideration... --- gtk2_ardour/editor_ops.cc | 27 +++++++++++++-------------- libs/evoral/evoral/Parameter.hpp | 4 ++++ libs/evoral/src/ControlList.cpp | 11 ++++++++++- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index c84bae6ad4..69fcf67d16 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4440,26 +4440,25 @@ Editor::paste_internal (framepos_t position, float times) R1.A1, R1.A2, R2, R2.A1, ... */ } - if (internal_editing ()) { + if (ts.size() == 1 && cut_buffer->lines.size() == 1 && + dynamic_cast(ts.front())) { + /* Only one line copied, and one automation track selected. Do a + "greedy" paste from one automation type to another. */ + + begin_reversible_command (Operations::paste); + + PasteContext ctx(paste_count, times, ItemCounts(), true); + ts.front()->paste (position, *cut_buffer, ctx); + + commit_reversible_command (); + + } else if (internal_editing ()) { /* undo/redo is handled by individual tracks/regions */ RegionSelection rs; get_regions_at (rs, position, ts); - if (ts.size() == 1 && cut_buffer->lines.size() == 1) { - AutomationTimeAxisView* atv = dynamic_cast(ts.front()); - if (atv) { - /* Only one line, and one automation track selected. Do a - "greedy" paste from one automation type to another. */ - PasteContext ctx(paste_count, times, ItemCounts(), true); - begin_reversible_command (Operations::paste); - atv->paste (position, *cut_buffer, ctx); - commit_reversible_command (); - return; - } - } - PasteContext ctx(paste_count, times, ItemCounts(), false); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { MidiRegionView* mrv = dynamic_cast (*r); diff --git a/libs/evoral/evoral/Parameter.hpp b/libs/evoral/evoral/Parameter.hpp index c870fa8e99..1412699b4d 100644 --- a/libs/evoral/evoral/Parameter.hpp +++ b/libs/evoral/evoral/Parameter.hpp @@ -57,6 +57,10 @@ public: return (_type == id._type && _channel == id._channel && _id == id._id ); } + inline bool operator!=(const Parameter& id) const { + return !operator==(id); + } + /** Strict weak ordering * See: http://www.sgi.com/tech/stl/StrictWeakOrdering.html * Sort Parameters first according to type then to channel and lastly to ID. diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index 61bac6148e..70500ba8de 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -1599,7 +1599,16 @@ ControlList::paste (const ControlList& alist, double pos, float /*times*/) where = upper_bound (_events.begin(), _events.end(), &cp, time_comparator); for (const_iterator i = alist.begin();i != alist.end(); ++i) { - _events.insert (where, new ControlEvent( (*i)->when+pos,( *i)->value)); + double value = (*i)->value; + if (alist.parameter() != parameter()) { + const ParameterDescriptor& src_desc = alist.descriptor(); + + value -= src_desc.lower; // translate to 0-relative + value /= (src_desc.upper - src_desc.lower); // normalize range + value *= (_desc.upper - _desc.lower); // scale to our range + value += _desc.lower; // translate to our offset + } + _events.insert (where, new ControlEvent((*i)->when + pos, value)); end = (*i)->when + pos; } -- 2.30.2