From 5f7b4de02414f00c98ede60db0dc1dddbbe051ae Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 16 Feb 2009 04:46:45 +0000 Subject: [PATCH] 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 --- gtk2_ardour/audio_region_view.cc | 2 +- gtk2_ardour/automation_line.cc | 72 +++++++++++++++------------ gtk2_ardour/automation_line.h | 29 ++++++----- gtk2_ardour/automation_region_view.cc | 6 ++- gtk2_ardour/automation_time_axis.cc | 30 +++++++---- gtk2_ardour/midi_region_view.cc | 4 +- gtk2_ardour/region_gain_line.cc | 3 +- libs/ardour/ardour/midi_source.h | 4 +- libs/ardour/ardour/source.h | 6 ++- libs/ardour/import.cc | 2 +- libs/ardour/smf_source.cc | 1 + 11 files changed, 93 insertions(+), 66 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 2a6bd2e1fe..3e904aabaa 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -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(); diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index a7eada37e7..b621773682 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -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 al) - : trackview (tv), - _name (name), - alist (al), - _parent_group (parent) +AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Group& parent, + boost::shared_ptr al, + const Evoral::TimeConverter& 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(*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::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& results) + double botfrac, double topfrac, list& 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::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(*this, &before, &get_state())); + trackview.editor().current_session()->add_command ( + new MementoCommand(*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); } diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 6cf3b5ade6..c04f343bcf 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -30,12 +30,13 @@ #include "canvas.h" #include "simplerect.h" +#include + #include #include #include - 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); + AutomationLine (const string& name, TimeAxisView&, ArdourCanvas::Group&, + boost::shared_ptr, + const Evoral::TimeConverter& 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 list); boost::shared_ptr 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& _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; }; diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index 9dbc72d965..678b18c622 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include "automation_region_view.h" #include "public_editor.h" @@ -69,7 +70,8 @@ AutomationRegionView::create_line (boost::shared_ptr lis { _line = boost::shared_ptr(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(); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 48c79040a1..d46a3cdbaa 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -211,12 +211,14 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr null_converter; boost::shared_ptr 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(); diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 7a4acb560d..cc4b53f13a 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -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 diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 2528e350fc..1bc4762eed 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -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 l) - : AutomationLine (name, r.get_time_axis_view(), parent, l), + : AutomationLine (name, r.get_time_axis_view(), parent, l, + Evoral::IdentityConverter()), session (s), rv (r) { diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 3a28cde8c6..e19956ad7a 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -95,7 +95,9 @@ class MidiSource : public Source void set_model(boost::shared_ptr m) { _model = m; } void drop_model() { _model.reset(); } - BeatsFramesConverter& converter() { return _converter; } + const Evoral::TimeConverter& time_converter() const { + return _converter; + } protected: virtual void flush_midi() = 0; diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index a2ee96bf63..b585509c51 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -24,8 +24,8 @@ #include #include - #include +#include #include #include @@ -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& time_converter() const { + return Evoral::IdentityConverter(); + } protected: DataType _type; diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 0e2cfb9988..f983352d58 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -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) { diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index ab0c290191..b43b628ce2 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -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; }