Time unit translation for AutomationLine (correctly display MIDI controller data).
authorDavid Robillard <d@drobilla.net>
Mon, 16 Feb 2009 04:46:45 +0000 (04:46 +0000)
committerDavid Robillard <d@drobilla.net>
Mon, 16 Feb 2009 04:46:45 +0000 (04:46 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@4597 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/audio_region_view.cc
gtk2_ardour/automation_line.cc
gtk2_ardour/automation_line.h
gtk2_ardour/automation_region_view.cc
gtk2_ardour/automation_time_axis.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/region_gain_line.cc
libs/ardour/ardour/midi_source.h
libs/ardour/ardour/source.h
libs/ardour/import.cc
libs/ardour/smf_source.cc

index 2a6bd2e1fe9f259015b5ccb61c10a8c0a42233f3..3e904aabaa2d986f43b1bcd56dad08f3abcda478 100644 (file)
@@ -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();
index a7eada37e7290bcae118e16bf31ea6bdc88ceb7d..b621773682fdcf40e326746d576944e29ef268e5 100644 (file)
@@ -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);
 }
 
        
index 6cf3b5ade6977b7137c1a846340cc0aa7041d7f9..c04f343bcf308842c4c732e2af8efb59195d4953 100644 (file)
 #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;
        };
 
index 9dbc72d96528a02058118105b320545e6fd99323..678b18c622443fd54beff9ab41de7ea54b13894b 100644 (file)
@@ -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();
index 48c79040a1acafc892c59ded522c86fabf3336f7..d46a3cdbaafc21a55e3e1faf845febdcada881d3 100644 (file)
@@ -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();
index 7a4acb560d4efc914ac300eab1e8c646f921a832..cc4b53f13aa3250046609725c4998e42fc342043 100644 (file)
@@ -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
index 2528e350fc9279d3589e51c081884d5493d59b09..1bc4762eed947977e9af381c305b3ebae5647160 100644 (file)
@@ -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)
 {
index 3a28cde8c6f38df0386d033d6f506602083b11dd..e19956ad7a2b6077e1e6515148e85abc517fa48b 100644 (file)
@@ -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;
index a2ee96bf63b3f3dd2b77dc638310e82f5aeb1a90..b585509c511f83171ddb8d9ceb7424480bdd9561 100644 (file)
@@ -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;
index 0e2cfb9988499d9a4b29d8c95643f2f7aa6fc448..f983352d58d999c9c99cf84bfd19c15b9eaf3d9e 100644 (file)
@@ -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) {
index ab0c290191bbfa94f2fb20a5e3301652d777c8d6..b43b628ce2fc4f1746d33b3c6f977fb7b47a8e3f 100644 (file)
@@ -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;
        }