Time unit translation for AutomationLine (correctly display MIDI controller data).
git-svn-id: svn://localhost/ardour2/branches/3.0@4597 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
0ef53a2d34
commit
5f7b4de024
@ -1008,7 +1008,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
|
||||
|
||||
/* map using gain line */
|
||||
|
||||
gain_line->view_to_model_y (y);
|
||||
gain_line->view_to_model_coord (x, y);
|
||||
|
||||
trackview.session().begin_reversible_command (_("add gain control point"));
|
||||
XMLNode &before = audio_region()->envelope()->get_state();
|
||||
|
@ -56,11 +56,14 @@ using namespace PBD;
|
||||
using namespace Editing;
|
||||
using namespace Gnome; // for Canvas
|
||||
|
||||
AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr<AutomationList> al)
|
||||
: trackview (tv),
|
||||
_name (name),
|
||||
alist (al),
|
||||
_parent_group (parent)
|
||||
AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Group& parent,
|
||||
boost::shared_ptr<AutomationList> al,
|
||||
const Evoral::TimeConverter<double, nframes_t>& converter)
|
||||
: trackview (tv)
|
||||
, _name (name)
|
||||
, alist (al)
|
||||
, _parent_group (parent)
|
||||
, _time_converter (converter)
|
||||
{
|
||||
_interpolation = al->interpolation();
|
||||
points_visible = false;
|
||||
@ -209,7 +212,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y)
|
||||
y = min (1.0, y);
|
||||
y = _height - (y * _height);
|
||||
|
||||
double const x = trackview.editor().frame_to_unit ((*cp.model())->when);
|
||||
double const x = trackview.editor().frame_to_unit (_time_converter.to((*cp.model())->when));
|
||||
|
||||
trackview.editor().current_session()->begin_reversible_command (_("automation event move"));
|
||||
trackview.editor().current_session()->add_command (new MementoCommand<AutomationList>(*alist.get(), &get_state(), 0));
|
||||
@ -311,7 +314,7 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
|
||||
|
||||
/* leave the x-coordinate alone */
|
||||
|
||||
x = trackview.editor().frame_to_unit ((*cp.model())->when);
|
||||
x = trackview.editor().frame_to_unit (_time_converter.to((*cp.model())->when));
|
||||
|
||||
}
|
||||
|
||||
@ -359,7 +362,6 @@ AutomationLine::reset_line_coords (ControlPoint& cp)
|
||||
void
|
||||
AutomationLine::sync_model_with_view_line (uint32_t start, uint32_t end)
|
||||
{
|
||||
|
||||
ControlPoint *p;
|
||||
|
||||
update_pending = true;
|
||||
@ -378,27 +380,26 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
|
||||
line to convert them to something relevant.
|
||||
*/
|
||||
|
||||
mr.xval = (nframes_t) floor (cp.get_x());
|
||||
mr.xval = cp.get_x();
|
||||
mr.yval = 1.0 - (cp.get_y() / _height);
|
||||
|
||||
/* if xval has not changed, set it directly from the model to avoid rounding errors */
|
||||
|
||||
if (mr.xval == trackview.editor().frame_to_unit((*cp.model())->when)) {
|
||||
mr.xval = (nframes_t) (*cp.model())->when;
|
||||
if (mr.xval == trackview.editor().frame_to_unit(_time_converter.to((*cp.model())->when))) {
|
||||
mr.xval = (*cp.model())->when;
|
||||
} else {
|
||||
mr.xval = trackview.editor().unit_to_frame (mr.xval);
|
||||
}
|
||||
|
||||
/* virtual call: this will do the right thing
|
||||
for whatever particular type of line we are.
|
||||
/* convert to model units
|
||||
*/
|
||||
|
||||
view_to_model_y (mr.yval);
|
||||
view_to_model_coord (mr.xval, mr.yval);
|
||||
|
||||
/* part 2: find out where the model point is now
|
||||
*/
|
||||
|
||||
mr.xpos = (nframes_t) (*cp.model())->when;
|
||||
mr.xpos = (*cp.model())->when;
|
||||
mr.ypos = (*cp.model())->value;
|
||||
|
||||
/* part 3: get the position of the visual control
|
||||
@ -417,7 +418,7 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
|
||||
after = nth (cp.view_index() + 1);
|
||||
|
||||
if (before) {
|
||||
mr.xmin = (nframes_t) (*before->model())->when;
|
||||
mr.xmin = (*before->model())->when;
|
||||
mr.ymin = (*before->model())->value;
|
||||
mr.start = before->model();
|
||||
++mr.start;
|
||||
@ -656,7 +657,6 @@ AutomationLine::get_verbose_cursor_string (double fraction) const
|
||||
* @param fraction y fraction
|
||||
* @return string representation of this value, using dB if appropriate.
|
||||
*/
|
||||
|
||||
string
|
||||
AutomationLine::fraction_to_string (double fraction) const
|
||||
{
|
||||
@ -669,7 +669,8 @@ AutomationLine::fraction_to_string (double fraction) const
|
||||
snprintf (buf, sizeof (buf), "%.1f", coefficient_to_dB (slider_position_to_gain (fraction)));
|
||||
}
|
||||
} else {
|
||||
view_to_model_y (fraction);
|
||||
double dummy = 0.0;
|
||||
view_to_model_coord (dummy, fraction);
|
||||
if (EventTypeMap::instance().is_integer (alist->parameter())) {
|
||||
snprintf (buf, sizeof (buf), "%d", (int)fraction);
|
||||
} else {
|
||||
@ -685,7 +686,6 @@ AutomationLine::fraction_to_string (double fraction) const
|
||||
* @param s Value string in the form as returned by fraction_to_string.
|
||||
* @return Corresponding y fraction.
|
||||
*/
|
||||
|
||||
double
|
||||
AutomationLine::string_to_fraction (string const & s) const
|
||||
{
|
||||
@ -699,7 +699,8 @@ AutomationLine::string_to_fraction (string const & s) const
|
||||
if (_uses_gain_mapping) {
|
||||
v = gain_to_slider_position (dB_to_coefficient (v));
|
||||
} else {
|
||||
model_to_view_y (v);
|
||||
double dummy = 0.0;
|
||||
model_to_view_coord (dummy, v);
|
||||
}
|
||||
|
||||
return v;
|
||||
@ -781,7 +782,9 @@ AutomationLine::line_drag (uint32_t i1, uint32_t i2, float fraction, bool with_p
|
||||
|
||||
for (uint32_t i = i1 ; i <= i2; i++) {
|
||||
cp = nth (i);
|
||||
modify_view_point (*cp, trackview.editor().unit_to_frame (cp->get_x()), ((_height - cp->get_y()) /_height) + ydelta, with_push);
|
||||
modify_view_point (*cp,
|
||||
trackview.editor().unit_to_frame (_time_converter.to(cp->get_x())),
|
||||
((_height - cp->get_y()) /_height) + ydelta, with_push);
|
||||
}
|
||||
|
||||
if (line_points.size() > 1) {
|
||||
@ -892,8 +895,6 @@ AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_
|
||||
ControlPoint *acp = 0;
|
||||
double unit_xval;
|
||||
|
||||
/* xval is in frames */
|
||||
|
||||
unit_xval = trackview.editor().frame_to_unit (xval);
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
@ -968,13 +969,13 @@ AutomationLine::remove_point (ControlPoint& cp)
|
||||
|
||||
void
|
||||
AutomationLine::get_selectables (nframes_t& start, nframes_t& end,
|
||||
double botfrac, double topfrac, list<Selectable*>& results)
|
||||
double botfrac, double topfrac, list<Selectable*>& results)
|
||||
{
|
||||
|
||||
double top;
|
||||
double bot;
|
||||
nframes_t nstart;
|
||||
nframes_t nend;
|
||||
double nstart;
|
||||
double nend;
|
||||
bool collecting = false;
|
||||
|
||||
/* Curse X11 and its inverted coordinate system! */
|
||||
@ -986,8 +987,7 @@ AutomationLine::get_selectables (nframes_t& start, nframes_t& end,
|
||||
nend = 0;
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
|
||||
nframes_t when = (nframes_t) (*(*i)->model())->when;
|
||||
double when = (*(*i)->model())->when;
|
||||
|
||||
if (when >= start && when <= end) {
|
||||
|
||||
@ -1137,8 +1137,9 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
|
||||
|
||||
for (ai = events.begin(); ai != events.end(); ++ai) {
|
||||
|
||||
double translated_x = (*ai)->when;
|
||||
double translated_y = (*ai)->value;
|
||||
model_to_view_y (translated_y);
|
||||
model_to_view_coord (translated_x, translated_y);
|
||||
|
||||
add_model_point (tmp_points, (*ai)->when, translated_y);
|
||||
}
|
||||
@ -1150,7 +1151,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
|
||||
void
|
||||
AutomationLine::add_model_point (ALPoints& tmp_points, double frame, double yfract)
|
||||
{
|
||||
tmp_points.push_back (ALPoint (trackview.editor().frame_to_unit (frame),
|
||||
tmp_points.push_back (ALPoint (trackview.editor().frame_to_unit (_time_converter.to(frame)),
|
||||
_height - (yfract * _height)));
|
||||
}
|
||||
|
||||
@ -1172,7 +1173,8 @@ AutomationLine::clear ()
|
||||
/* parent must create command */
|
||||
XMLNode &before = get_state();
|
||||
alist->clear();
|
||||
trackview.editor().current_session()->add_command (new MementoCommand<AutomationLine>(*this, &before, &get_state()));
|
||||
trackview.editor().current_session()->add_command (
|
||||
new MementoCommand<AutomationLine>(*this, &before, &get_state()));
|
||||
trackview.editor().current_session()->commit_reversible_command ();
|
||||
trackview.editor().current_session()->set_dirty ();
|
||||
}
|
||||
@ -1248,7 +1250,7 @@ AutomationLine::set_state (const XMLNode &node)
|
||||
}
|
||||
|
||||
void
|
||||
AutomationLine::view_to_model_y (double& y) const
|
||||
AutomationLine::view_to_model_coord (double& x, double& y) const
|
||||
{
|
||||
/* TODO: This should be more generic ... */
|
||||
if (alist->parameter().type() == GainAutomation ||
|
||||
@ -1264,10 +1266,12 @@ AutomationLine::view_to_model_y (double& y) const
|
||||
} else {
|
||||
y = (int)(y * alist->parameter().max());
|
||||
}
|
||||
|
||||
x = _time_converter.from(x);
|
||||
}
|
||||
|
||||
void
|
||||
AutomationLine::model_to_view_y (double& y) const
|
||||
AutomationLine::model_to_view_coord (double& x, double& y) const
|
||||
{
|
||||
/* TODO: This should be more generic ... */
|
||||
if (alist->parameter().type() == GainAutomation ||
|
||||
@ -1281,6 +1285,8 @@ AutomationLine::model_to_view_y (double& y) const
|
||||
} else {
|
||||
y = y / (double)alist->parameter().max(); /* ... like this */
|
||||
}
|
||||
|
||||
x = _time_converter.to(x);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,12 +30,13 @@
|
||||
#include "canvas.h"
|
||||
#include "simplerect.h"
|
||||
|
||||
#include <evoral/TimeConverter.hpp>
|
||||
|
||||
#include <pbd/undo.h>
|
||||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
#include <ardour/automation_list.h>
|
||||
|
||||
|
||||
class AutomationLine;
|
||||
class ControlPoint;
|
||||
class PointSelection;
|
||||
@ -53,7 +54,9 @@ namespace Gnome {
|
||||
class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoingAway
|
||||
{
|
||||
public:
|
||||
AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, boost::shared_ptr<ARDOUR::AutomationList>);
|
||||
AutomationLine (const string& name, TimeAxisView&, ArdourCanvas::Group&,
|
||||
boost::shared_ptr<ARDOUR::AutomationList>,
|
||||
const Evoral::TimeConverter<double, nframes_t>& converter);
|
||||
virtual ~AutomationLine ();
|
||||
|
||||
void queue_reset ();
|
||||
@ -70,7 +73,6 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||
bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after);
|
||||
|
||||
/* dragging API */
|
||||
|
||||
virtual void start_drag (ControlPoint*, nframes_t x, float fraction);
|
||||
virtual void point_drag(ControlPoint&, nframes_t x, float, bool with_push);
|
||||
virtual void end_drag (ControlPoint*);
|
||||
@ -79,9 +81,9 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||
ControlPoint* nth (uint32_t);
|
||||
uint32_t npoints() const { return control_points.size(); }
|
||||
|
||||
string name() const { return _name; }
|
||||
string name() const { return _name; }
|
||||
bool visible() const { return _visible; }
|
||||
guint32 height() const { return _height; }
|
||||
guint32 height() const { return _height; }
|
||||
|
||||
void set_line_color (uint32_t);
|
||||
uint32_t get_line_color() const { return _line_color; }
|
||||
@ -106,8 +108,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||
string get_verbose_cursor_string (double) const;
|
||||
string fraction_to_string (double) const;
|
||||
double string_to_fraction (string const &) const;
|
||||
void view_to_model_y (double&) const;
|
||||
void model_to_view_y (double&) const;
|
||||
void view_to_model_coord (double& x, double& y) const;
|
||||
void model_to_view_coord (double& x, double& y) const;
|
||||
|
||||
void set_list(boost::shared_ptr<ARDOUR::AutomationList> list);
|
||||
boost::shared_ptr<ARDOUR::AutomationList> the_list() const { return alist; }
|
||||
@ -180,8 +182,9 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||
uint32_t line_drag_cp2;
|
||||
int64_t drag_x;
|
||||
int64_t drag_distance;
|
||||
|
||||
ARDOUR::AutomationList::InterpolationStyle _interpolation;
|
||||
|
||||
const Evoral::TimeConverter<double, nframes_t>& _time_converter;
|
||||
ARDOUR::AutomationList::InterpolationStyle _interpolation;
|
||||
|
||||
void modify_view_point (ControlPoint&, double, double, bool with_push);
|
||||
void reset_line_coords (ControlPoint&);
|
||||
@ -191,13 +194,13 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
|
||||
struct ModelRepresentation {
|
||||
ARDOUR::AutomationList::iterator start;
|
||||
ARDOUR::AutomationList::iterator end;
|
||||
nframes_t xpos;
|
||||
double xpos;
|
||||
double ypos;
|
||||
nframes_t xmin;
|
||||
double xmin;
|
||||
double ymin;
|
||||
nframes_t xmax;
|
||||
double xmax;
|
||||
double ymax;
|
||||
nframes_t xval;
|
||||
double xval;
|
||||
double yval;
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <ardour/automation_control.h>
|
||||
#include <ardour/event_type_map.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/source.h>
|
||||
#include "automation_region_view.h"
|
||||
#include "public_editor.h"
|
||||
|
||||
@ -69,7 +70,8 @@ AutomationRegionView::create_line (boost::shared_ptr<ARDOUR::AutomationList> lis
|
||||
{
|
||||
_line = boost::shared_ptr<AutomationLine>(new AutomationLine(
|
||||
ARDOUR::EventTypeMap::instance().to_symbol(list->parameter()),
|
||||
trackview, *get_canvas_group(), list));
|
||||
trackview, *get_canvas_group(), list,
|
||||
_region->source(0)->time_converter()));
|
||||
_line->set_colors();
|
||||
_line->set_interpolation(list->interpolation());
|
||||
_line->show();
|
||||
@ -114,7 +116,7 @@ AutomationRegionView::add_automation_event (GdkEvent* event, nframes_t when, dou
|
||||
|
||||
/* map using line */
|
||||
|
||||
_line->view_to_model_y (y);
|
||||
_line->view_to_model_coord (x, y);
|
||||
|
||||
view->session().begin_reversible_command (_("add automation event"));
|
||||
XMLNode& before = _line->the_list()->get_state();
|
||||
|
@ -211,12 +211,14 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
|
||||
|
||||
/* no regions, just a single line for the entire track (e.g. bus gain) */
|
||||
} else {
|
||||
static const Evoral::IdentityConverter<double,nframes_t> null_converter;
|
||||
|
||||
boost::shared_ptr<AutomationLine> line(new AutomationLine (
|
||||
ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
|
||||
*this,
|
||||
*_canvas_display,
|
||||
_control->alist()));
|
||||
_control->alist(),
|
||||
null_converter));
|
||||
|
||||
line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
|
||||
line->queue_reset ();
|
||||
@ -581,7 +583,7 @@ AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent
|
||||
|
||||
/* map using line */
|
||||
|
||||
_line->view_to_model_y (y);
|
||||
_line->view_to_model_coord (x, y);
|
||||
|
||||
_session.begin_reversible_command (_("add automation event"));
|
||||
XMLNode& before = _control->alist()->get_state();
|
||||
@ -634,9 +636,11 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
|
||||
|
||||
if (what_we_got) {
|
||||
for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
|
||||
double foo = (*x)->value;
|
||||
line.model_to_view_y (foo);
|
||||
(*x)->value = foo;
|
||||
double when = (*x)->when;
|
||||
double val = (*x)->value;
|
||||
line.model_to_view_coord (when, val);
|
||||
(*x)->when = when;
|
||||
(*x)->value = val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,9 +718,11 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
|
||||
|
||||
if (what_we_got) {
|
||||
for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
|
||||
double foo = (*x)->value;
|
||||
line.model_to_view_y (foo);
|
||||
(*x)->value = foo;
|
||||
double when = (*x)->when;
|
||||
double val = (*x)->value;
|
||||
line.model_to_view_coord (when, val);
|
||||
(*x)->when = when;
|
||||
(*x)->value = val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,9 +755,11 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float ti
|
||||
AutomationList copy (**p);
|
||||
|
||||
for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
|
||||
double foo = (*x)->value;
|
||||
line.view_to_model_y (foo);
|
||||
(*x)->value = foo;
|
||||
double when = (*x)->when;
|
||||
double val = (*x)->value;
|
||||
line.view_to_model_coord (when, val);
|
||||
(*x)->when = when;
|
||||
(*x)->value = val;
|
||||
}
|
||||
|
||||
XMLNode &before = alist->get_state();
|
||||
|
@ -1388,13 +1388,13 @@ MidiRegionView::get_position_pixels()
|
||||
nframes64_t
|
||||
MidiRegionView::beats_to_frames(double beats) const
|
||||
{
|
||||
return midi_region()->midi_source()->converter().to(beats);
|
||||
return midi_region()->midi_source()->time_converter().to(beats);
|
||||
}
|
||||
|
||||
double
|
||||
MidiRegionView::frames_to_beats(nframes64_t frames) const
|
||||
{
|
||||
return midi_region()->midi_source()->converter().from(frames);
|
||||
return midi_region()->midi_source()->time_converter().from(frames);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -39,7 +39,8 @@ using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, AudioRegionView& r, ArdourCanvas::Group& parent, boost::shared_ptr<AutomationList> l)
|
||||
: AutomationLine (name, r.get_time_axis_view(), parent, l),
|
||||
: AutomationLine (name, r.get_time_axis_view(), parent, l,
|
||||
Evoral::IdentityConverter<double, nframes_t>()),
|
||||
session (s),
|
||||
rv (r)
|
||||
{
|
||||
|
@ -95,7 +95,9 @@ class MidiSource : public Source
|
||||
void set_model(boost::shared_ptr<MidiModel> m) { _model = m; }
|
||||
void drop_model() { _model.reset(); }
|
||||
|
||||
BeatsFramesConverter& converter() { return _converter; }
|
||||
const Evoral::TimeConverter<double, nframes_t>& time_converter() const {
|
||||
return _converter;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void flush_midi() = 0;
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include <set>
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
|
||||
#include <pbd/statefuldestructible.h>
|
||||
#include <evoral/TimeConverter.hpp>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/session_object.h>
|
||||
@ -91,6 +91,10 @@ class Source : public SessionObject, public ARDOUR::Readable
|
||||
int load_transients (const std::string&);
|
||||
|
||||
void update_length (nframes_t pos, nframes_t cnt);
|
||||
|
||||
virtual const Evoral::TimeConverter<double, nframes_t>& time_converter() const {
|
||||
return Evoral::IdentityConverter<double, nframes_t>();
|
||||
}
|
||||
|
||||
protected:
|
||||
DataType _type;
|
||||
|
@ -356,7 +356,7 @@ write_midi_data_to_new_files (Evoral::SMF* source, Session::ImportStatus& status
|
||||
}
|
||||
|
||||
const double length_beats = ceil(t / (double)source->ppqn());
|
||||
smfs->update_length(0, smfs->converter().to(length_beats));
|
||||
smfs->update_length(0, smfs->time_converter().to(length_beats));
|
||||
smfs->end_write();
|
||||
|
||||
if (status.cancel) {
|
||||
|
@ -612,6 +612,7 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||
}
|
||||
|
||||
if (_model && !force_reload) {
|
||||
cerr << _name << " not reloading model " << _model.get() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user