move most of AutomationLine into AutomatonLineBase, a class not strongly tied to the editor

This commit is contained in:
Paul Davis
2024-08-24 08:03:21 -06:00
parent 0b05ec93c8
commit fa79645c19
11 changed files with 57 additions and 1688 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,8 @@
#include "canvas/container.h"
#include "canvas/poly_line.h"
#include "automation_line_base.h"
class AutomationLine;
class ControlPoint;
class PointSelection;
@@ -55,16 +57,13 @@ class Selection;
class PublicEditor;
/** A GUI representation of an ARDOUR::AutomationList */
class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
/** A GUI representation of an ARDOUR::AutomationList within the main editor
* (i.e. in a TimeAxisView
*/
class AutomationLine : public AutomationLineBase
{
public:
enum VisibleAspects {
Line = 0x1,
ControlPoints = 0x2,
SelectedControlPoints = 0x4
};
AutomationLine (const std::string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
@@ -74,182 +73,10 @@ public:
virtual ~AutomationLine ();
virtual Temporal::timepos_t get_origin () const;
void queue_reset ();
void reset ();
void clear ();
void set_fill (bool f) { _fill = f; } // owner needs to call set_height
void set_selected_points (PointSelection const &);
void get_selectables (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, std::list<Selectable*>&);
void get_inverted_selectables (Selection&, std::list<Selectable*>& results);
virtual void remove_point (ControlPoint&);
bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after);
/* dragging API */
virtual void start_drag_single (ControlPoint*, double, float);
virtual void start_drag_line (uint32_t, uint32_t, float);
virtual void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode *);
virtual std::pair<float, float> drag_motion (Temporal::timecnt_t const &, float, bool, bool with_push, uint32_t& final_index);
virtual void end_drag (bool with_push, uint32_t final_index);
virtual void end_draw_merge () {}
ControlPoint* nth (uint32_t);
ControlPoint const * nth (uint32_t) const;
uint32_t npoints() const { return control_points.size(); }
std::string name() const { return _name; }
bool visible() const { return _visible != VisibleAspects(0); }
guint32 height() const { return _height; }
void set_line_color (std::string color, std::string mod = "");
uint32_t get_line_color() const;
void set_visibility (VisibleAspects);
void add_visibility (VisibleAspects);
void remove_visibility (VisibleAspects);
void hide ();
void set_height (guint32);
bool get_uses_gain_mapping () const;
void tempo_map_changed ();
TimeAxisView& trackview;
ArdourCanvas::Container& canvas_group() const { return *group; }
ArdourCanvas::Item& parent_group() const { return _parent_group; }
ArdourCanvas::Item& grab_item() const { return *line; }
virtual std::string get_verbose_cursor_string (double) const;
std::string get_verbose_cursor_relative_string (double, double) const;
std::string fraction_to_string (double) const;
std::string delta_to_string (double) const;
double string_to_fraction (std::string const &) const;
void view_to_model_coord_y (double &) const;
double model_to_view_coord_y (double) const;
Temporal::timecnt_t model_to_view_coord_x (Temporal::timepos_t const &) const;
double compute_delta (double from, double to) const;
void apply_delta (double& val, double delta) const;
void set_list(std::shared_ptr<ARDOUR::AutomationList> list);
std::shared_ptr<ARDOUR::AutomationList> the_list() const { return alist; }
void track_entered();
void track_exited();
bool is_last_point (ControlPoint &);
bool is_first_point (ControlPoint &);
XMLNode& get_state () const;
int set_state (const XMLNode&, int version);
void set_colors();
void modify_points_y (std::vector<ControlPoint*> const&, double);
virtual MementoCommandBinder<ARDOUR::AutomationList>* memento_command_binder ();
std::pair<Temporal::timepos_t, Temporal::timepos_t> get_point_x_range () const;
void set_maximum_time (Temporal::timepos_t const &);
Temporal::timepos_t maximum_time () const {
return _maximum_time;
}
void set_offset (Temporal::timepos_t const &);
Temporal::timepos_t offset () { return _offset; }
void set_width (Temporal::timecnt_t const &);
Temporal::timepos_t session_position (Temporal::timepos_t const &) const;
void dump (std::ostream&) const;
double dt_to_dx (Temporal::timepos_t const &, Temporal::timecnt_t const &);
protected:
std::string _name;
guint32 _height;
std::string _line_color;
std::string _line_color_mod;
uint32_t _view_index_offset;
std::shared_ptr<ARDOUR::AutomationList> alist;
VisibleAspects _visible;
bool terminal_points_can_slide;
bool update_pending;
bool have_reset_timeout;
bool no_draw;
bool _is_boolean;
/** true if we did a push at any point during the current drag */
bool did_push;
ArdourCanvas::Item& _parent_group;
ArdourCanvas::Container* group;
ArdourCanvas::PolyLine* line; /* line */
ArdourCanvas::Points line_points; /* coordinates for canvas line */
std::vector<ControlPoint*> control_points; /* visible control points */
class ContiguousControlPoints : public std::list<ControlPoint*> {
public:
ContiguousControlPoints (AutomationLine& al);
Temporal::timecnt_t clamp_dt (Temporal::timecnt_t const & dx, Temporal::timepos_t const & region_limit);
void move (Temporal::timecnt_t const &, double dvalue);
void compute_x_bounds (PublicEditor& e);
private:
AutomationLine& line;
Temporal::timepos_t before_x;
Temporal::timepos_t after_x;
};
friend class ContiguousControlPoints;
typedef std::shared_ptr<ContiguousControlPoints> CCP;
std::vector<CCP> contiguous_points;
bool sync_model_with_view_point (ControlPoint&);
bool sync_model_with_view_points (std::list<ControlPoint*>);
void start_drag_common (double, float);
void reset_callback (const Evoral::ControlList&);
void list_changed ();
protected:
virtual bool event_handler (GdkEvent*);
private:
std::list<ControlPoint*> _drag_points; ///< points we are dragging
std::list<ControlPoint*> _push_points; ///< additional points we are dragging if "push" is enabled
bool _drag_had_movement; ///< true if the drag has seen movement, otherwise false
double _last_drag_fraction; ///< last y position of the drag, as a fraction
/** offset from the start of the automation list to the start of the line, so that
* a +ve offset means that the 0 on the line is at _offset in the list
*/
Temporal::timepos_t _offset;
bool is_stepped() const;
void update_visibility ();
void reset_line_coords (ControlPoint&);
void add_visible_control_point (uint32_t, uint32_t, double, double, ARDOUR::AutomationList::iterator, uint32_t);
double control_point_box_size ();
void connect_to_list ();
void interpolation_changed (ARDOUR::AutomationList::InterpolationStyle);
PBD::ScopedConnectionList _list_connections;
/** maximum time that a point on this line can be at, relative to the position of its region or start of its track */
Temporal::timepos_t _maximum_time;
bool _fill;
const ARDOUR::ParameterDescriptor _desc;
friend class AudioRegionGainLine;
friend class RegionFxLine;
};
#endif /* __ardour_automation_line_h__ */

View File

@@ -19,7 +19,7 @@
*/
#include "control_point.h"
#include "automation_line.h"
#include "automation_line_base.h"
#include "public_editor.h"
#include "ui_config.h"
@@ -33,7 +33,7 @@ using namespace PBD;
PBD::Signal1<void, ControlPoint *> ControlPoint::CatchDeletion;
ControlPoint::ControlPoint (AutomationLine& al)
ControlPoint::ControlPoint (AutomationLineBase& al)
: _line (al)
{
_model = al.the_list()->end();

View File

@@ -29,7 +29,7 @@
#include "selectable.h"
class AutomationLine;
class AutomationLineBase;
class ControlPoint;
class PointSelection;
class TimeAxisView;
@@ -46,7 +46,7 @@ namespace ArdourCanvas {
class ControlPoint : public Selectable
{
public:
ControlPoint (AutomationLine& al);
ControlPoint (AutomationLineBase& al);
ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor);
virtual ~ControlPoint ();
@@ -84,13 +84,13 @@ public:
void unset_item () { _item = 0 ; }
ARDOUR::AutomationList::iterator model() const { return _model; }
AutomationLine& line() const { return _line; }
AutomationLineBase& line() const { return _line; }
static PBD::Signal1<void, ControlPoint *> CatchDeletion;
private:
ArdourCanvas::Rectangle* _item;
AutomationLine& _line;
ArdourCanvas::Rectangle * _item;
AutomationLineBase& _line;
ARDOUR::AutomationList::iterator _model;
uint32_t _view_index;
bool _can_slide;

View File

@@ -21,7 +21,7 @@
#include "gtkmm2ext/gtk_ui.h"
#include "automation_line.h"
#include "automation_line_base.h"
#include "control_point.h"
#include "control_point_dialog.h"

View File

@@ -331,6 +331,8 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Rou
bool
Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
{
std::cerr << "AT event\n";
if (atv->parameter().type() == MidiVelocityAutomation) {
/* no event handling for velocity tracks until we can make the
automation control affect note velocity.
@@ -636,7 +638,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 = &dynamic_cast<AutomationLine*> (&cp->line())->trackview;
clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
clicked_regionview = 0;
break;

View File

@@ -53,6 +53,7 @@
#include "canvas/canvas.h"
#include "canvas/lollipop.h"
#include "canvas/rectangle.h"
#include "canvas/scroll_group.h"
#include "ardour_ui.h"

View File

@@ -2198,7 +2198,7 @@ Editor::can_remove_control_point (ArdourCanvas::Item* item)
abort(); /*NOTREACHED*/
}
AutomationLine& line = control_point->line ();
AutomationLineBase& line (control_point->line());
if (dynamic_cast<RegionFxLine*> (&line)) {
/* we shouldn't remove the first or last gain point in region gain lines */
if (line.is_last_point(*control_point) || line.is_first_point(*control_point)) {

View File

@@ -89,6 +89,7 @@
#include "audio_region_view.h"
#include "audio_streamview.h"
#include "audio_time_axis.h"
#include "automation_line_base.h"
#include "automation_time_axis.h"
#include "control_point.h"
#include "debug.h"
@@ -4815,11 +4816,11 @@ Editor::cut_copy (CutCopyOp op)
struct AutomationRecord {
AutomationRecord () : state (0) , line(NULL) {}
AutomationRecord (XMLNode* s, const AutomationLine* l) : state (s) , line (l) {}
AutomationRecord () : state (0) , line (nullptr) {}
AutomationRecord (XMLNode* s, const AutomationLineBase* l) : state (s) , line (l) {}
XMLNode* state; ///< state before any operation
const AutomationLine* line; ///< line this came from
const AutomationLineBase* line; ///< line this came from
std::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
};
@@ -4842,7 +4843,9 @@ 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;
AutomationLine* line = dynamic_cast<AutomationLine*> (&selection->points.front()->line());
assert (line);
_last_cut_copy_source_track = &line->trackview;
/* Keep a record of the AutomationLists that we end up using in this operation */
typedef std::map<std::shared_ptr<AutomationList>, AutomationRecord> Lists;
@@ -4852,8 +4855,8 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time)
selection->points.sort(PointsSelectionPositionSorter ());
/* Go through all selected points, making an AutomationRecord for each distinct AutomationList */
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
const AutomationLine& line = (*sel_point)->line();
for (auto & selected_point : selection->points) {
const AutomationLineBase& line (selected_point->line());
const std::shared_ptr<AutomationList> al = line.the_list();
if (lists.find (al) == lists.end ()) {
/* We haven't seen this list yet, so make a record for it. This includes
@@ -4873,9 +4876,9 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time)
/* Add all selected points to the relevant copy ControlLists */
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
std::shared_ptr<AutomationList> al = (*sel_point)->line().the_list();
AutomationList::const_iterator ctrl_evt = (*sel_point)->model ();
for (auto & selected_point : selection->points) {
std::shared_ptr<AutomationList> al = selected_point->line().the_list();
AutomationList::const_iterator ctrl_evt = selected_point->model ();
lists[al].copy->fast_simple_add ((*ctrl_evt)->when, (*ctrl_evt)->value);
earliest = std::min (earliest, (*ctrl_evt)->when);
@@ -4905,21 +4908,21 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time)
}
/* Remove each selected point from its AutomationList */
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
AutomationLine& line = (*sel_point)->line ();
for (auto & selected_point : selection->points) {
AutomationLineBase& line (selected_point->line ());
std::shared_ptr<AutomationList> al = line.the_list();
bool erase = true;
if (dynamic_cast<RegionFxLine*> (&line)) {
/* removing of first and last gain point in region gain lines is prohibited*/
if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
if (line.is_last_point (*selected_point) || line.is_first_point (*selected_point)) {
erase = false;
}
}
if(erase) {
al->erase ((*sel_point)->model ());
al->erase (selected_point->model ());
}
}

View File

@@ -37,6 +37,7 @@
#include "control_protocol/control_protocol.h"
#include "audio_region_view.h"
#include "automation_line_base.h"
#include "debug.h"
#include "gui_thread.h"
#include "midi_cut_buffer.h"
@@ -1163,25 +1164,27 @@ Selection::get_state () const
}
}
for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
for (auto & cp : points) {
AutomationLine* al = dynamic_cast<AutomationLine*> (&cp->line());
assert (al);
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&al->trackview);
if (atv) {
XMLNode* r = node->add_child (X_("ControlPoint"));
r->set_property (X_("type"), "track");
r->set_property (X_("route-id"), atv->parent_stripable()->id ());
r->set_property (X_("automation-list-id"), (*i)->line().the_list()->id ());
r->set_property (X_("parameter"), EventTypeMap::instance().to_symbol ((*i)->line().the_list()->parameter ()));
r->set_property (X_("view-index"), (*i)->view_index());
continue;
}
r->set_property (X_("automation-list-id"), al->the_list()->id ());
r->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (al->the_list()->parameter ()));
r->set_property (X_("view-index"), cp->view_index());
} else {
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> (&(*i)->line());
if (fxl) {
XMLNode* r = node->add_child (X_("ControlPoint"));
r->set_property (X_("type"), "region");
r->set_property (X_("region-id"), fxl->region_view ().region ()->id ());
r->set_property (X_("view-index"), (*i)->view_index());
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> (al);
if (fxl) {
XMLNode* r = node->add_child (X_("ControlPoint"));
r->set_property (X_("type"), "region");
r->set_property (X_("region-id"), fxl->region_view ().region ()->id ());
r->set_property (X_("view-index"), cp->view_index());
}
}
}

View File

@@ -49,6 +49,7 @@ gtk2_ardour_sources = [
'audio_time_axis.cc',
'automation_controller.cc',
'automation_line.cc',
'automation_line_base.cc',
'automation_region_view.cc',
'automation_streamview.cc',
'automation_time_axis.cc',