reduce (but not eliminate) AutomationLine (+ derivatives) dependence on TimeAxisView

AutomationLines now use a TimeThing for time conversions, and has their own Session ref handle
This commit is contained in:
Paul Davis 2021-12-09 10:19:23 -07:00
parent 0dda441598
commit 9f90870306
12 changed files with 94 additions and 77 deletions

View File

@ -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 ();

View File

@ -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<AutomationList> al,
const ParameterDescriptor& desc)
: trackview (tv)
AutomationLine::AutomationLine (const string& name,
TimeThing const & tt,
Session& s,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
boost::shared_ptr<AutomationList> 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<AutomationList> (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<AutomationList> (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<AutomationList> (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<AutomationList> (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<ControlPoint*> cp, float fraction, XMLNode* state)
{
trackview.editor().session()->add_command (
_session.add_command (
new MementoCommand<AutomationList> (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<CCP>::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<AutomationList>(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<ControlPoint*>::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<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
_session.add_command (new MementoCommand<AutomationList> (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<Selectable*>& 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<ControlPoint*>::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<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
_session.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
}
void

View File

@ -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<ARDOUR::AutomationList> 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<ARDOUR::AutomationList> 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;

View File

@ -97,7 +97,10 @@ AutomationRegionView::create_line (boost::shared_ptr<ARDOUR::AutomationList> lis
{
_line = boost::shared_ptr<AutomationLine> (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<ARDOUR::MidiRegion> (_region),
_parameter));
_line->set_colors();

View File

@ -302,6 +302,8 @@ AutomationTimeAxisView::AutomationTimeAxisView (
boost::shared_ptr<AutomationLine> line (
new AutomationLine (
ARDOUR::EventTypeMap::instance().to_symbol(_parameter),
PublicEditor::instance(),
*session(),
*this,
*_canvas_display,
_control->alist(),

View File

@ -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<RouteTimeAxisView*>(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<RouteTimeAxisView*>(clicked_axisview);
return typed_event (item, event, type);

View File

@ -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<boost::shared_ptr<AutomationList>, AutomationRecord> Lists;

View File

@ -32,13 +32,15 @@
using namespace std;
MidiAutomationLine::MidiAutomationLine (
const std::string& name,
TimeAxisView& tav,
ArdourCanvas::Item& parent,
boost::shared_ptr<ARDOUR::AutomationList> list,
boost::shared_ptr<ARDOUR::MidiRegion> 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<ARDOUR::AutomationList> list,
boost::shared_ptr<ARDOUR::MidiRegion> 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<MidiTimeAxisView*>(trackview.get_parent());
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*> (_trackview.get_parent());
if (!mtv) {
return AutomationLine::get_verbose_cursor_string(fraction);
}

View File

@ -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<ARDOUR::AutomationList>,
boost::shared_ptr<ARDOUR::MidiRegion>,
Evoral::Parameter);

View File

@ -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<AutomationList> 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<AutomationList> 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<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
_session.add_command(new MementoCommand<AudioRegion>(*(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<AutomationList>(*alist.get(), &before, &alist->get_state()));
trackview.editor().commit_reversible_command ();
trackview.editor().session()->set_dirty ();
_session.add_command (new MementoCommand<AutomationList>(*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<AudioRegion>(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state()));
_session.add_command (new MementoCommand<AudioRegion>(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state()));
}
AutomationLine::end_drag (with_push, final_index);

View File

@ -40,7 +40,7 @@ class AudioRegionView;
class AudioRegionGainLine : public AutomationLine
{
public:
AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, boost::shared_ptr<ARDOUR::AutomationList>);
AudioRegionGainLine (const std::string & name, AudioRegionView&, TimeThing const &, TimeAxisView& tv, ArdourCanvas::Container& parent, boost::shared_ptr<ARDOUR::AutomationList>);
Temporal::timepos_t get_origin() const;

View File

@ -1116,7 +1116,7 @@ Selection::get_state () const
}
for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview());
if (atv) {
XMLNode* r = node->add_child (X_("ControlPoint"));