13
0

AutomationLine time-unit conversion and paste API update

This fixes copy/paste of MIDI automation (time-unit: beat) from/to
Parameter automation (time-unit: samples).

It also fixes repeatedly pasting with tempo-ramps: pre-multiply length
before converting to samples.
This commit is contained in:
Robin Gareus 2017-04-26 16:21:39 +02:00
parent 8bb26628e3
commit 0b5db91ee9
6 changed files with 61 additions and 9 deletions

View File

@ -210,6 +210,8 @@ AutomationRegionView::paste (framepos_t pos
float times,
boost::shared_ptr<const ARDOUR::AutomationList> slist)
{
using namespace ARDOUR;
AutomationTimeAxisView* const view = automation_view();
boost::shared_ptr<ARDOUR::AutomationList> my_list = _line->the_list();
@ -218,15 +220,24 @@ AutomationRegionView::paste (framepos_t pos
return false;
}
/* add multi-paste offset if applicable */
pos += view->editor().get_paste_offset(
pos, paste_count, _source_relative_time_converter.to(slist->length()));
AutomationType src_type = (AutomationType)slist->parameter().type ();
double len = slist->length();
const double model_pos = _source_relative_time_converter.from(
/* add multi-paste offset if applicable */
if (parameter_is_midi (src_type)) {
// convert length to samples (incl tempo-ramps)
len = DoubleBeatsFramesConverter (view->session()->tempo_map(), pos).to (len * paste_count);
pos += view->editor ().get_paste_offset (pos, paste_count > 0 ? 1 : 0, len);
} else {
pos += view->editor ().get_paste_offset (pos, paste_count, len);
}
/* convert sample-position to model's unit and position */
const double model_pos = _source_relative_time_converter.from (
pos - _source_relative_time_converter.origin_b());
XMLNode& before = my_list->get_state();
my_list->paste(*slist, model_pos, times);
my_list->paste(*slist, model_pos, DoubleBeatsFramesConverter (view->session()->tempo_map(), pos));
view->session()->add_command(
new MementoCommand<ARDOUR::AutomationList>(_line->memento_command_binder(), &before, &my_list->get_state()));

View File

@ -29,6 +29,7 @@
#include "pbd/types_convert.h"
#include "ardour/automation_control.h"
#include "ardour/beats_frames_converter.h"
#include "ardour/event_type_map.h"
#include "ardour/parameter_types.h"
#include "ardour/profile.h"
@ -695,12 +696,23 @@ AutomationTimeAxisView::paste_one (framepos_t pos, unsigned paste_count, float t
counts.increase_n_lines(_parameter);
/* add multi-paste offset if applicable */
pos += _editor.get_paste_offset(pos, paste_count, (*p)->length());
AutomationType src_type = (AutomationType)(*p)->parameter().type ();
double len = (*p)->length();
if (parameter_is_midi (src_type)) {
// convert length to samples (incl tempo-ramps)
len = DoubleBeatsFramesConverter (_session->tempo_map(), pos).to (len * paste_count);
pos += _editor.get_paste_offset (pos, paste_count > 0 ? 1 : 0, len);
} else {
pos += _editor.get_paste_offset (pos, paste_count, len);
}
/* convert sample-position to model's unit and position */
double const model_pos = _line->time_converter().from (pos - _line->time_converter().origin_b ());
XMLNode &before = alist->get_state();
alist->paste (**p, model_pos, times);
alist->paste (**p, model_pos, DoubleBeatsFramesConverter (_session->tempo_map(), pos));
_session->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
return true;

View File

@ -40,6 +40,7 @@
namespace ARDOUR {
class AutomationList;
class DoubleBeatsFramesConverter;
/** A SharedStatefulProperty for AutomationLists */
class LIBARDOUR_API AutomationListProperty : public PBD::SharedStatefulProperty<AutomationList>
@ -81,6 +82,7 @@ class LIBARDOUR_API AutomationList : public Evoral::ControlList, public PBD::Sta
AutomationList& operator= (const AutomationList&);
void thaw ();
bool paste (const ControlList&, double, DoubleBeatsFramesConverter const&);
void set_automation_state (AutoState);
AutoState automation_state() const { return _state; }

View File

@ -24,8 +24,10 @@
#include <sstream>
#include <algorithm>
#include "ardour/automation_list.h"
#include "ardour/beats_frames_converter.h"
#include "ardour/event_type_map.h"
#include "ardour/parameter_descriptor.h"
#include "ardour/parameter_types.h"
#include "ardour/evoral_types_convert.h"
#include "ardour/types_convert.h"
#include "evoral/Curve.hpp"
@ -289,6 +291,31 @@ AutomationList::thaw ()
}
}
bool
AutomationList::paste (const ControlList& alist, double pos, DoubleBeatsFramesConverter const& bfc)
{
AutomationType src_type = (AutomationType)alist.parameter().type();
AutomationType dst_type = (AutomationType)_parameter.type();
if (parameter_is_midi (src_type) == parameter_is_midi (dst_type)) {
return ControlList::paste (alist, pos);
}
bool to_frame = parameter_is_midi (src_type);
ControlList cl (alist);
cl.clear ();
for (const_iterator i = alist.begin ();i != alist.end (); ++i) {
double when = (*i)->when;
if (to_frame) {
when = bfc.to ((*i)->when);
} else {
when = bfc.from ((*i)->when);
}
cl.fast_simple_add (when, (*i)->value);
}
return ControlList::paste (cl, pos);
}
Command*
AutomationList::memento_command (XMLNode* before, XMLNode* after)
{

View File

@ -172,7 +172,7 @@ public:
*/
void clear (double start, double end);
bool paste (const ControlList&, double position, float times);
bool paste (const ControlList&, double position);
void set_yrange (double min, double max) {
_min_yval = min;

View File

@ -1652,7 +1652,7 @@ ControlList::clear (double start, double end)
/** @param pos Position in model coordinates */
bool
ControlList::paste (const ControlList& alist, double pos, float /*times*/)
ControlList::paste (const ControlList& alist, double pos)
{
if (alist._events.empty()) {
return false;