diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 08696178cf..f7b0066bd5 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -79,8 +79,7 @@ using namespace PBD; using namespace Editing; using namespace Temporal; -#define TIME_TO_SAMPLES(x) (_distance_measure (x, Temporal::AudioTime)) -#define SAMPLES_TO_TIME(x) (_distance_measure (x, alist->time_domain())) +#define SAMPLES_TO_TIME(x) (get_origin().distance (x)) /** @param converter A TimeConverter whose origin_b is the start time of the AutomationList in session samples. * This will not be deleted by AutomationLine. @@ -89,8 +88,7 @@ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Item& parent, boost::shared_ptr al, - const ParameterDescriptor& desc, - Temporal::DistanceMeasure const & m) + const ParameterDescriptor& desc) : trackview (tv) , _name (name) , alist (al) @@ -99,7 +97,6 @@ AutomationLine::AutomationLine (const string& name, , _maximum_time (timepos_t::max (al->time_domain())) , _fill (false) , _desc (desc) - , _distance_measure (m) { _visible = Line; @@ -139,6 +136,15 @@ AutomationLine::~AutomationLine () control_points.clear (); } +timepos_t +AutomationLine::get_origin() const +{ + /* this is the default for all non-derived AutomationLine classes: the + origin is zero, in whatever time domain the list we represent uses. + */ + return timepos_t (the_list()->time_domain()); +} + bool AutomationLine::event_handler (GdkEvent* event) { @@ -762,6 +768,14 @@ AutomationLine::end_drag (bool with_push, uint32_t final_index) contiguous_points.clear (); } +/** + * + * get model coordinates synced with (possibly changed) view coordinates. + * + * For example, we call this in ::end_drag(), when we have probably moved a + * point in the view, and now want to "push" that change back into the + * corresponding model point. + */ bool AutomationLine::sync_model_with_view_point (ControlPoint& cp) { @@ -773,22 +787,49 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp) double view_x = cp.get_x(); double view_y = 1.0 - cp.get_y() / (double)_height; - /* if xval has not changed, set it directly from the model to avoid rounding errors */ + timepos_t model_time = (*cp.model())->when; - timepos_t model_x = (*cp.model())->when; + /* convert to absolute time by taking the origin of the line into + * account. + */ - if (view_x != trackview.editor().time_to_pixel_unrounded (model_x.earlier (_offset))) { - /* convert from view coordinates, via pixels->samples->timepos_t + const timepos_t absolute_time = model_time + get_origin(); + + /* convert the absolute time of the model event into unrounded pixels, + * taking _offset into account. + */ + + const double model_x = trackview.editor().time_to_pixel_unrounded (absolute_time.earlier (_offset)); + + if (view_x != model_x) { + + /* convert the current position in the view (units: pixels) + * into samples, then use that to create a timecnt_t that + * measures the distance from the origin for this line. */ - const timecnt_t p = timecnt_t (trackview.editor().pixel_to_sample (view_x), timepos_t()); /* samples */ - model_x = SAMPLES_TO_TIME (p + _offset); /* correct time domain for list */ + + const timecnt_t view_samples (trackview.editor().pixel_to_sample (view_x)); /* implicit zero origin */ + + /* adjust to measure distance from origin (this preserves time domain) */ + const timecnt_t distance_from_origin = get_origin().distance (timepos_t (view_samples)); + + /* now convert to relevant time domain, and use _offset. + */ + + if (model_time.time_domain() == Temporal::AudioTime) { + model_time = timepos_t (distance_from_origin.samples()) + _offset; + } else { + model_time = timepos_t (distance_from_origin.beats()) + _offset; + } + } else { + model_time = model_time.earlier (_offset); } update_pending = true; view_to_model_coord_y (view_y); - alist->modify (cp.model(), model_x, view_y); + alist->modify (cp.model(), model_time, view_y); /* convert back from model to view y for clamping position (for integer/boolean/etc) */ model_to_view_coord_y (view_y); @@ -1346,13 +1387,13 @@ AutomationLine::get_point_x_range () const samplepos_t AutomationLine::session_sample_position (AutomationList::const_iterator p) const { - return (*p)->when.samples() + _offset.samples() + _distance_measure.origin().samples(); + return (*p)->when.samples() + _offset.samples() + get_origin().samples(); } timepos_t AutomationLine::session_position (AutomationList::const_iterator p) const { - return (*p)->when + _offset + _distance_measure.origin(); + return (*p)->when + _offset + get_origin(); } void @@ -1365,9 +1406,3 @@ AutomationLine::set_offset (timecnt_t const & off) _offset = off; reset (); } - -void -AutomationLine::set_distance_measure_origin (timepos_t const & pos) -{ - _distance_measure.set_origin (pos); -} diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 4c51cd0500..cf69861077 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -37,8 +37,6 @@ #include "pbd/statefuldestructible.h" #include "pbd/memento_command.h" -#include "temporal/time_converter.h" - #include "ardour/automation_list.h" #include "ardour/parameter_descriptor.h" #include "ardour/types.h" @@ -71,11 +69,13 @@ public: TimeAxisView& tv, ArdourCanvas::Item& parent, boost::shared_ptr al, - const ARDOUR::ParameterDescriptor& desc, - Temporal::DistanceMeasure const &); + const ARDOUR::ParameterDescriptor& desc); + virtual ~AutomationLine (); + virtual Temporal::timepos_t get_origin () const; + void queue_reset (); void reset (); void clear (); @@ -164,9 +164,6 @@ public: samplepos_t session_sample_position (ARDOUR::AutomationList::const_iterator) const; Temporal::timepos_t session_position (ARDOUR::AutomationList::const_iterator) const; - Temporal::DistanceMeasure const & distance_measure () const { return _distance_measure; } - void set_distance_measure_origin (Temporal::timepos_t const &); - protected: std::string _name; @@ -245,7 +242,6 @@ private: bool _fill; const ARDOUR::ParameterDescriptor _desc; - Temporal::DistanceMeasure _distance_measure; friend class AudioRegionGainLine; }; diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index a37008e447..0213e901d5 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -305,8 +305,7 @@ AutomationTimeAxisView::AutomationTimeAxisView ( *this, *_canvas_display, _control->alist(), - _control->desc(), - Temporal::DistanceMeasure (timepos_t()) /* default distance measure, origin at absolute zero */ + _control->desc() ) ); @@ -868,8 +867,7 @@ AutomationTimeAxisView::paste_one (timepos_t const & pos, unsigned paste_count, } /* convert position to model's unit and position */ - Temporal::DistanceMeasure const & dm (_line->distance_measure()); - Temporal::timepos_t model_pos = dm (_line->distance_measure().origin().distance (tpos), line()->the_list()->time_domain()); + Temporal::timepos_t model_pos (_line->get_origin().distance (tpos)); XMLNode &before = alist->get_state(); alist->paste (**p, model_pos); @@ -1143,9 +1141,8 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel XMLNode &before = alist->get_state(); /* convert time selection to automation list model coordinates */ - /* convert time selection to automation list model coordinates */ - timepos_t start = selection.time.front().start().earlier (line.distance_measure().origin()); - timepos_t end = selection.time.front().end().earlier (line.distance_measure().origin()); + timepos_t start = selection.time.front().start().earlier (line.get_origin()); + timepos_t end = selection.time.front().end().earlier (line.get_origin()); switch (op) { case Delete: diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 9c87570ced..54ab4628e9 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -6537,7 +6537,7 @@ AutomationRangeDrag::setup (list > const & lin //TODO: if we implement automation regions, this check can probably be removed AudioRegionGainLine *argl = dynamic_cast ((*i).get()); if (!argl) { - //in automation lanes, the EFFECTIVE range should be considered 0->max_samplepos (even if there is no line) + //in automation lanes, the EFFECTIVE range should be considered 0->max_position (even if there is no line) r.first = Temporal::timepos_t ((*i)->the_list()->time_domain()); r.second = Temporal::timepos_t::max ((*i)->the_list()->time_domain()); } @@ -6702,6 +6702,23 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move) /* here's a control point on this line */ ControlPoint* p = i->line->nth (j); #warning NUTEMPO figure out what this code is/was doing and replace it + /* + convert is ... double meant beats + so origin_b is the origin in samplepos_t (since a=double b=samplepos_t) + + so ->to() returns samples + + so to (p->model->when) is the beat time (as dobule) + we convert to samples + then add the originin samples + + BUT ... mostly used IdentityConverter, except MIDI + + where the time_converter() is a source-relative converter + source-relative uses the the source_position() as the origin + + */ + //double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b (); double const w = 0;; diff --git a/gtk2_ardour/midi_automation_line.cc b/gtk2_ardour/midi_automation_line.cc index f466aa2bf2..5b0d3b2ef0 100644 --- a/gtk2_ardour/midi_automation_line.cc +++ b/gtk2_ardour/midi_automation_line.cc @@ -38,7 +38,7 @@ MidiAutomationLine::MidiAutomationLine ( boost::shared_ptr list, boost::shared_ptr region, Evoral::Parameter parameter) - : AutomationLine (name, tav, parent, list, parameter, Temporal::DistanceMeasure (Temporal::timepos_t())) + : AutomationLine (name, tav, parent, list, parameter) , _region (region) , _parameter (parameter) { @@ -51,6 +51,17 @@ MidiAutomationLine::memento_command_binder () return new ARDOUR::MidiAutomationListBinder (_region->midi_source(), _parameter); } +Temporal::timepos_t +MidiAutomationLine::get_origin() const +{ + /* Events in the automation list are relative to the start of the + source, not the start of the region, so we need to use the + position-of-the-start-of-the-source, rather than just the + position-of-the-region. + */ + return _region->source_position(); +} + string MidiAutomationLine::get_verbose_cursor_string (double fraction) const { diff --git a/gtk2_ardour/midi_automation_line.h b/gtk2_ardour/midi_automation_line.h index 72f9108baa..ebf5d44be4 100644 --- a/gtk2_ardour/midi_automation_line.h +++ b/gtk2_ardour/midi_automation_line.h @@ -38,6 +38,7 @@ public: MementoCommandBinder* memento_command_binder (); virtual std::string get_verbose_cursor_string (double) const; + Temporal::timepos_t get_origin() const; private: boost::shared_ptr _region; diff --git a/gtk2_ardour/midi_list_editor.cc b/gtk2_ardour/midi_list_editor.cc index fcb13f3049..5a7758989e 100644 --- a/gtk2_ardour/midi_list_editor.cc +++ b/gtk2_ardour/midi_list_editor.cc @@ -26,7 +26,6 @@ #include "evoral/midi_util.h" #include "evoral/Note.h" -#include "ardour/beats_samples_converter.h" #include "ardour/midi_model.h" #include "ardour/midi_region.h" #include "ardour/midi_source.h" diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 4376896e77..a7589bacaf 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -44,7 +44,7 @@ using namespace ARDOUR; using namespace PBD; AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, boost::shared_ptr l) - : AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter(), Temporal::DistanceMeasure (r.region()->position())) + : AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter()) , rv (r) { // If this isn't true something is horribly wrong, and we'll get catastrophic gain values @@ -57,6 +57,13 @@ AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& terminal_points_can_slide = false; } +timepos_t +AudioRegionGainLine::get_origin() const +{ + return rv.region()->position(); +} + + void AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction) { @@ -110,10 +117,6 @@ AudioRegionGainLine::region_changed (const PropertyChange& what_changed) interesting_stuff.add (ARDOUR::Properties::start); interesting_stuff.add (ARDOUR::Properties::position); - if (what_changed.contains (ARDOUR::Properties::position)) { - set_distance_measure_origin (rv.region()->position()); - } - if (what_changed.contains (interesting_stuff)) { reset (); } diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 1bbc2be28f..82ea387590 100644 --- a/gtk2_ardour/region_gain_line.h +++ b/gtk2_ardour/region_gain_line.h @@ -42,6 +42,8 @@ class AudioRegionGainLine : public AutomationLine public: AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, boost::shared_ptr); + Temporal::timepos_t get_origin() const; + void start_drag_single (ControlPoint*, double, float); void end_drag (bool with_push, uint32_t final_index); diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 6256ce45ff..5578dabdf1 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -32,7 +32,6 @@ #include #include "ardour/region.h" -#include "ardour/beats_samples_converter.h" #include "canvas/fwd.h" diff --git a/gtk2_ardour/tempo_lines.h b/gtk2_ardour/tempo_lines.h index 980b6195e2..a8d4ea2e62 100644 --- a/gtk2_ardour/tempo_lines.h +++ b/gtk2_ardour/tempo_lines.h @@ -21,7 +21,6 @@ #ifndef __ardour_tempo_lines_h__ #define __ardour_tempo_lines_h__ -#include "ardour/beats_samples_converter.h" #include "ardour/tempo.h" #include "canvas/line_set.h"