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:
parent
8bb26628e3
commit
0b5db91ee9
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user