From 9f9087030651c388cf5f3a2975b901138ae8c9db Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 9 Dec 2021 10:19:23 -0700 Subject: [PATCH] reduce (but not eliminate) AutomationLine (+ derivatives) dependence on TimeAxisView AutomationLines now use a TimeThing for time conversions, and has their own Session ref handle --- gtk2_ardour/audio_region_view.cc | 2 +- gtk2_ardour/automation_line.cc | 83 +++++++++++++-------------- gtk2_ardour/automation_line.h | 24 +++++--- gtk2_ardour/automation_region_view.cc | 5 +- gtk2_ardour/automation_time_axis.cc | 2 + gtk2_ardour/editor_canvas_events.cc | 4 +- gtk2_ardour/editor_ops.cc | 2 +- gtk2_ardour/midi_automation_line.cc | 18 +++--- gtk2_ardour/midi_automation_line.h | 6 +- gtk2_ardour/region_gain_line.cc | 21 +++---- gtk2_ardour/region_gain_line.h | 2 +- gtk2_ardour/selection.cc | 2 +- 12 files changed, 94 insertions(+), 77 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 46ffc25a34..81e94e3602 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -236,7 +236,7 @@ AudioRegionView::init (bool wfd) const string line_name = _region->name() + ":gain"; - gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope())); + gain_line.reset (new AudioRegionGainLine (line_name, *this, PublicEditor::instance(), get_time_axis_view(), *group, audio_region()->envelope())); update_envelope_visibility (); gain_line->reset (); diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 29021f517f..a568659cd6 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -81,15 +81,16 @@ using namespace Temporal; #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. - */ -AutomationLine::AutomationLine (const string& name, - TimeAxisView& tv, - ArdourCanvas::Item& parent, - boost::shared_ptr al, - const ParameterDescriptor& desc) - : trackview (tv) +AutomationLine::AutomationLine (const string& name, + TimeThing const & tt, + Session& s, + TimeAxisView& tv, + ArdourCanvas::Item& parent, + boost::shared_ptr al, + const ParameterDescriptor& desc) + : SessionHandleRef (s) + , _trackview (tv) + , time_thing (tt) , _name (name) , alist (al) , _parent_group (parent) @@ -118,7 +119,7 @@ AutomationLine::AutomationLine (const string& name, line->Event.connect (sigc::mem_fun (*this, &AutomationLine::event_handler)); - trackview.session()->register_with_memento_command_factory(alist->id(), this); + _session.register_with_memento_command_factory(alist->id(), this); interpolation_changed (alist->interpolation ()); @@ -300,8 +301,8 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y) y = min (1.0, y); y = _height - (y * _height); - trackview.editor().begin_reversible_command (_("automation event move")); - trackview.editor().session()->add_command ( + PublicEditor::instance().begin_reversible_command (_("automation event move")); + _session.add_command ( new MementoCommand (memento_command_binder(), &get_state(), 0)); cp.move_to (cp.get_x(), y, ControlPoint::Full); @@ -318,11 +319,11 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y) update_pending = false; - trackview.editor().session()->add_command ( + _session.add_command ( new MementoCommand (memento_command_binder(), 0, &alist->get_state())); - trackview.editor().commit_reversible_command (); - trackview.editor().session()->set_dirty (); + PublicEditor::instance().commit_reversible_command (); + _session.set_dirty (); } void @@ -420,7 +421,7 @@ AutomationLine::string_to_fraction (string const & s) const void AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) { - trackview.editor().session()->add_command ( + _session.add_command ( new MementoCommand (memento_command_binder(), &get_state(), 0)); _drag_points.clear (); @@ -445,7 +446,7 @@ AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) void AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) { - trackview.editor().session()->add_command ( + _session.add_command ( new MementoCommand (memento_command_binder (), &get_state(), 0)); _drag_points.clear (); @@ -464,7 +465,7 @@ AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) void AutomationLine::start_drag_multiple (list cp, float fraction, XMLNode* state) { - trackview.editor().session()->add_command ( + _session.add_command ( new MementoCommand (memento_command_binder(), state, 0)); _drag_points = cp; @@ -487,7 +488,7 @@ AutomationLine::ContiguousControlPoints::ContiguousControlPoints (AutomationLine } void -AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) +AutomationLine::ContiguousControlPoints::compute_x_bounds (TimeThing const & tt) { uint32_t sz = size(); @@ -501,10 +502,10 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) if (front()->view_index() > 0) { before_x = line.nth (front()->view_index() - 1)->get_x(); - const samplepos_t pos = e.pixel_to_sample(before_x); + const samplepos_t pos = tt.pixel_to_sample(before_x); const TempoMetric& metric = map->metric_at (pos); const samplecnt_t len = ceil (metric.samples_per_bar (pos) / (Temporal::ticks_per_beat * metric.meter().divisions_per_bar())); - const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); + const double one_tick_in_pixels = tt.sample_to_pixel_unrounded (len); before_x += one_tick_in_pixels; } @@ -516,10 +517,10 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) if (back()->view_index() < (line.npoints() - 1)) { after_x = line.nth (back()->view_index() + 1)->get_x(); - const samplepos_t pos = e.pixel_to_sample(after_x); + const samplepos_t pos = tt.pixel_to_sample(after_x); const TempoMetric& metric = map->metric_at (pos); const samplecnt_t len = ceil (metric.samples_per_bar (pos) / (Temporal::ticks_per_beat * metric.meter().divisions_per_bar())); - const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); + const double one_tick_in_pixels = tt.sample_to_pixel_unrounded (len); after_x -= one_tick_in_pixels; } @@ -632,7 +633,7 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool } for (vector::iterator ccp = contiguous_points.begin(); ccp != contiguous_points.end(); ++ccp) { - (*ccp)->compute_x_bounds (trackview.editor()); + (*ccp)->compute_x_bounds (PublicEditor::instance()); } _drag_had_movement = true; } @@ -759,10 +760,10 @@ AutomationLine::end_drag (bool with_push, uint32_t final_index) line->set_steps (line_points, is_stepped()); } - trackview.editor().session()->add_command ( + _session.add_command ( new MementoCommand(memento_command_binder (), 0, &alist->get_state())); - trackview.editor().session()->set_dirty (); + _session.set_dirty (); did_push = false; contiguous_points.clear (); @@ -799,7 +800,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp) * taking _offset into account. */ - const double model_x = trackview.editor().time_to_pixel_unrounded (absolute_time.earlier (_offset)); + const double model_x = PublicEditor::instance().time_to_pixel_unrounded (absolute_time.earlier (_offset)); if (view_x != model_x) { @@ -808,7 +809,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp) * measures the distance from the origin for this line. */ - const timecnt_t view_samples (trackview.editor().pixel_to_sample (view_x)); /* implicit zero origin */ + const timecnt_t view_samples (PublicEditor::instance().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)); @@ -850,7 +851,7 @@ AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_ ControlPoint *acp = 0; double unit_xval; - unit_xval = trackview.editor().sample_to_pixel_unrounded (xval); + unit_xval = PublicEditor::instance().sample_to_pixel_unrounded (xval); for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { @@ -906,17 +907,16 @@ AutomationLine::is_first_point (ControlPoint& cp) void AutomationLine::remove_point (ControlPoint& cp) { - trackview.editor().begin_reversible_command (_("remove control point")); + PublicEditor::instance().begin_reversible_command (_("remove control point")); XMLNode &before = alist->get_state(); - trackview.editor ().get_selection ().clear_points (); + PublicEditor::instance().get_selection ().clear_points (); alist->erase (cp.model()); - trackview.editor().session()->add_command( - new MementoCommand (memento_command_binder (), &before, &alist->get_state())); + _session.add_command (new MementoCommand (memento_command_binder (), &before, &alist->get_state())); - trackview.editor().commit_reversible_command (); - trackview.editor().session()->set_dirty (); + PublicEditor::instance().commit_reversible_command (); + _session.set_dirty (); } /** Get selectable points within an area. @@ -930,8 +930,8 @@ void AutomationLine::get_selectables (timepos_t const & start, timepos_t const & end, double botfrac, double topfrac, list& results) { /* convert fractions to display coordinates with 0 at the top of the track */ - double const bot_track = (1 - topfrac) * trackview.current_height (); - double const top_track = (1 - botfrac) * trackview.current_height (); + double const bot_track = (1 - topfrac) * _height; + double const top_track = (1 - botfrac) * _height; for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { @@ -1038,7 +1038,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) * zoom and scroll into account). */ - double px = trackview.editor().time_to_pixel_unrounded (tx); + double px = PublicEditor::instance().time_to_pixel_unrounded (tx); /* convert from canonical view height (0..1.0) to actual * height coordinates (using X11's top-left rooted system) @@ -1084,7 +1084,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) update_visibility (); } - set_selected_points (trackview.editor().get_selection().points); + set_selected_points (PublicEditor::instance().get_selection().points); } void @@ -1114,7 +1114,7 @@ AutomationLine::queue_reset () { /* this must be called from the GUI thread */ - if (trackview.editor().session()->transport_rolling() && alist->automation_write()) { + if (_session.transport_rolling() && alist->automation_write()) { /* automation write pass ... defer to a timeout */ /* redraw in 1/4 second */ if (!have_timeout) { @@ -1136,8 +1136,7 @@ AutomationLine::clear () XMLNode &before = alist->get_state(); alist->clear(); - trackview.editor().session()->add_command ( - new MementoCommand (memento_command_binder (), &before, &alist->get_state())); + _session.add_command (new MementoCommand (memento_command_binder (), &before, &alist->get_state())); } void diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index ced055aee9..7b8fb4fbb2 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -39,12 +39,15 @@ #include "ardour/automation_list.h" #include "ardour/parameter_descriptor.h" +#include "ardour/session_handle.h" #include "ardour/types.h" #include "canvas/types.h" #include "canvas/container.h" #include "canvas/poly_line.h" +#include "time_thing.h" + class AutomationLine; class ControlPoint; class PointSelection; @@ -54,9 +57,8 @@ class Selectable; class Selection; class PublicEditor; - /** A GUI representation of an ARDOUR::AutomationList */ -class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible +class AutomationLine : public ARDOUR::SessionHandleRef, public sigc::trackable, public PBD::StatefulDestructible { public: enum VisibleAspects { @@ -66,6 +68,8 @@ public: }; AutomationLine (const std::string& name, + TimeThing const & tt, + ARDOUR::Session& s, TimeAxisView& tv, ArdourCanvas::Item& parent, boost::shared_ptr al, @@ -115,8 +119,6 @@ public: bool get_uses_gain_mapping () const; - TimeAxisView& trackview; - ArdourCanvas::Container& canvas_group() const { return *group; } ArdourCanvas::Item& parent_group() const { return _parent_group; } ArdourCanvas::Item& grab_item() const { return *line; } @@ -164,11 +166,15 @@ public: samplepos_t session_sample_position (ARDOUR::AutomationList::const_iterator) const; Temporal::timepos_t session_position (ARDOUR::AutomationList::const_iterator) const; -protected: - std::string _name; - guint32 _height; - uint32_t _line_color; + TimeAxisView& trackview() { return _trackview; } + + protected: + TimeAxisView& _trackview; + TimeThing const & time_thing; + std::string _name; + guint32 _height; + uint32_t _line_color; boost::shared_ptr alist; @@ -193,7 +199,7 @@ public: ContiguousControlPoints (AutomationLine& al); double clamp_dx (double dx); void move (double dx, double dvalue); - void compute_x_bounds (PublicEditor& e); + void compute_x_bounds (TimeThing const & e); private: AutomationLine& line; double before_x; diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index dbe125e770..cb609f4628 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -97,7 +97,10 @@ AutomationRegionView::create_line (boost::shared_ptr lis { _line = boost::shared_ptr (new MidiAutomationLine( ARDOUR::EventTypeMap::instance().to_symbol(list->parameter()), - trackview, *get_canvas_group(), list, + PublicEditor::instance(), + *trackview.session(), + trackview, + *get_canvas_group(), list, boost::dynamic_pointer_cast (_region), _parameter)); _line->set_colors(); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 0213e901d5..dfecdb6469 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -302,6 +302,8 @@ AutomationTimeAxisView::AutomationTimeAxisView ( boost::shared_ptr line ( new AutomationLine ( ARDOUR::EventTypeMap::instance().to_symbol(_parameter), + PublicEditor::instance(), + *session(), *this, *_canvas_display, _control->alist(), diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 82d8c8719d..6dee0fe100 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -660,7 +660,7 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: clicked_control_point = cp; - clicked_axisview = &cp->line().trackview; + clicked_axisview = &cp->line().trackview(); clicked_routeview = dynamic_cast(clicked_axisview); clicked_regionview = 0; break; @@ -689,7 +689,7 @@ Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, Automation } clicked_control_point = 0; - clicked_axisview = &al->trackview; + clicked_axisview = &al->trackview(); clicked_routeview = dynamic_cast(clicked_axisview); return typed_event (item, event, type); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 3c10edeb54..6338c25545 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4427,7 +4427,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time) timepos_t earliest (earliest_time); /* XXX: not ideal, as there may be more than one track involved in the point selection */ - _last_cut_copy_source_track = &selection->points.front()->line().trackview; + _last_cut_copy_source_track = &selection->points.front()->line().trackview(); /* Keep a record of the AutomationLists that we end up using in this operation */ typedef std::map, AutomationRecord> Lists; diff --git a/gtk2_ardour/midi_automation_line.cc b/gtk2_ardour/midi_automation_line.cc index 67b1df6531..8216b3f083 100644 --- a/gtk2_ardour/midi_automation_line.cc +++ b/gtk2_ardour/midi_automation_line.cc @@ -32,13 +32,15 @@ using namespace std; MidiAutomationLine::MidiAutomationLine ( - const std::string& name, - TimeAxisView& tav, - ArdourCanvas::Item& parent, - boost::shared_ptr list, - boost::shared_ptr region, - Evoral::Parameter parameter) - : AutomationLine (name, tav, parent, list, parameter) + const std::string& name, + TimeThing const & tt, + ARDOUR::Session& s, + TimeAxisView& tv, + ArdourCanvas::Item& parent, + boost::shared_ptr list, + boost::shared_ptr region, + Evoral::Parameter parameter) + : AutomationLine (name, tt, s, tv, parent, list, parameter) , _region (region) , _parameter (parameter) { @@ -71,7 +73,7 @@ MidiAutomationLine::get_verbose_cursor_string (double fraction) const return AutomationLine::get_verbose_cursor_string(fraction); } - MidiTimeAxisView* const mtv = dynamic_cast(trackview.get_parent()); + MidiTimeAxisView* const mtv = dynamic_cast (_trackview.get_parent()); if (!mtv) { return AutomationLine::get_verbose_cursor_string(fraction); } diff --git a/gtk2_ardour/midi_automation_line.h b/gtk2_ardour/midi_automation_line.h index ebf5d44be4..f0326a382f 100644 --- a/gtk2_ardour/midi_automation_line.h +++ b/gtk2_ardour/midi_automation_line.h @@ -24,13 +24,17 @@ namespace ARDOUR { class MidiRegion; } +class MidiTimeAxisView; + /** Stub class so that lines for MIDI AutomationRegionViews can use the correct * MementoCommandBinder. */ class MidiAutomationLine : public AutomationLine { public: - MidiAutomationLine (const std::string&, TimeAxisView&, ArdourCanvas::Item&, + MidiAutomationLine (const std::string&, TimeThing const &, ARDOUR::Session&, + TimeAxisView& tv, + ArdourCanvas::Item&, boost::shared_ptr, boost::shared_ptr, Evoral::Parameter); diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 66385dffc4..a677594dda 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -43,8 +43,8 @@ using namespace std; 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()) +AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, TimeThing const & tt, TimeAxisView& tv, ArdourCanvas::Container& parent, boost::shared_ptr l) + : AutomationLine (name, tt, r.region()->session(), tv, parent, l, l->parameter()) , rv (r) { // If this isn't true something is horribly wrong, and we'll get catastrophic gain values @@ -72,7 +72,7 @@ AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fracti // XXX Stateful need to capture automation curve data if (!rv.audio_region()->envelope_active()) { - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); + _session.add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); rv.audio_region()->set_envelope_active(false); } } @@ -81,21 +81,22 @@ AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fracti void AudioRegionGainLine::remove_point (ControlPoint& cp) { - trackview.editor().begin_reversible_command (_("remove control point")); + PublicEditor& e (PublicEditor::instance()); + e.begin_reversible_command (_("remove control point")); XMLNode &before = alist->get_state(); if (!rv.audio_region()->envelope_active()) { rv.audio_region()->clear_changes (); rv.audio_region()->set_envelope_active(true); - trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region())); + _session.add_command(new StatefulDiffCommand (rv.audio_region())); } - trackview.editor ().get_selection ().clear_points (); + e.get_selection ().clear_points (); alist->erase (cp.model()); - trackview.editor().session()->add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); - trackview.editor().commit_reversible_command (); - trackview.editor().session()->set_dirty (); + _session.add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); + e.commit_reversible_command (); + _session.set_dirty (); } void @@ -103,7 +104,7 @@ AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index) { if (!rv.audio_region()->envelope_active()) { rv.audio_region()->set_envelope_active(true); - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state())); + _session.add_command (new MementoCommand(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state())); } AutomationLine::end_drag (with_push, final_index); diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 82ea387590..71136d3e0d 100644 --- a/gtk2_ardour/region_gain_line.h +++ b/gtk2_ardour/region_gain_line.h @@ -40,7 +40,7 @@ class AudioRegionView; class AudioRegionGainLine : public AutomationLine { public: - AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, boost::shared_ptr); + AudioRegionGainLine (const std::string & name, AudioRegionView&, TimeThing const &, TimeAxisView& tv, ArdourCanvas::Container& parent, boost::shared_ptr); Temporal::timepos_t get_origin() const; diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 6408cae9ce..3fd9648448 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -1116,7 +1116,7 @@ Selection::get_state () const } for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) { - AutomationTimeAxisView* atv = dynamic_cast (&(*i)->line().trackview); + AutomationTimeAxisView* atv = dynamic_cast (&(*i)->line().trackview()); if (atv) { XMLNode* r = node->add_child (X_("ControlPoint"));