13
0

wideranging changes to get automation editing working in cue editor

This commit is contained in:
Paul Davis 2024-09-20 19:44:25 -06:00
parent 4169f11ddd
commit 90c8726c6d
28 changed files with 680 additions and 486 deletions

View File

@ -102,7 +102,7 @@ AutomationLineBase::AutomationLineBase (const string& name,
, have_reset_timeout (false)
, no_draw (false)
, _is_boolean (false)
, editing_context (ec)
, _editing_context (ec)
, _parent_group (parent)
, _drag_base (drag_base)
, _offset (0)
@ -122,7 +122,7 @@ AutomationLineBase::AutomationLineBase (const string& name,
line->Event.connect (sigc::mem_fun (*this, &AutomationLineBase::event_handler));
editing_context.session()->register_with_memento_command_factory(alist->id(), this);
_editing_context.session()->register_with_memento_command_factory(alist->id(), this);
interpolation_changed (alist->interpolation ());
@ -236,7 +236,7 @@ AutomationLineBase::control_point_box_size ()
} else if (_height > (guint32) TimeAxisView::preset_height (HeightNormal)) {
return rint (6.0 * uiscale);
}
return rint (4.0 * uiscale);
return rint (12.0 * uiscale);
}
void
@ -311,9 +311,8 @@ AutomationLineBase::modify_points_y (std::vector<ControlPoint*> const& cps, doub
y = min (1.0, y);
y = _height - (y * _height);
editing_context.begin_reversible_command (_("automation event move"));
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
_editing_context.begin_reversible_command (_("automation event move"));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
alist->freeze ();
for (auto const& cp : cps) {
@ -332,11 +331,10 @@ AutomationLineBase::modify_points_y (std::vector<ControlPoint*> const& cps, doub
update_pending = false;
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()));
editing_context.commit_reversible_command ();
editing_context.session()->set_dirty ();
_editing_context.commit_reversible_command ();
_editing_context.session()->set_dirty ();
}
void
@ -435,8 +433,7 @@ AutomationLineBase::string_to_fraction (string const & s) const
void
AutomationLineBase::start_drag_single (ControlPoint* cp, double x, float fraction)
{
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
_drag_points.clear ();
_drag_points.push_back (cp);
@ -460,8 +457,7 @@ AutomationLineBase::start_drag_single (ControlPoint* cp, double x, float fractio
void
AutomationLineBase::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
{
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0));
_drag_points.clear ();
@ -479,8 +475,7 @@ AutomationLineBase::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
void
AutomationLineBase::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
{
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
_drag_points = cp;
start_drag_common (0, fraction);
@ -610,9 +605,9 @@ AutomationLineBase::dt_to_dx (timepos_t const & pos, timecnt_t const & dt)
/* convert a shift of pos by dt into an absolute timepos */
timepos_t const new_pos ((pos + dt + get_origin()).shift_earlier (offset()));
/* convert to pixels */
double px = editing_context.time_to_pixel_unrounded (new_pos);
double px = _editing_context.time_to_pixel_unrounded (new_pos);
/* convert back to pixels-relative-to-origin */
px -= editing_context.time_to_pixel_unrounded (get_origin());
px -= _editing_context.time_to_pixel_unrounded (get_origin());
return px;
}
@ -792,10 +787,9 @@ AutomationLineBase::end_drag (bool with_push, uint32_t final_index)
line->set_steps (line_points, is_stepped());
}
editing_context.session()->add_command (
new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state()));
_editing_context.add_command (new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state()));
editing_context.session()->set_dirty ();
_editing_context.session()->set_dirty ();
did_push = false;
contiguous_points.clear ();
@ -827,7 +821,7 @@ AutomationLineBase::sync_model_with_view_point (ControlPoint& cp)
const timepos_t absolute_time = model_time + origin;
/* now convert to pixels relative to start of region, which matches view_x */
const double model_x = editing_context.time_to_pixel_unrounded (absolute_time) - editing_context.time_to_pixel_unrounded (origin);
const double model_x = _editing_context.time_to_pixel_unrounded (absolute_time) - _editing_context.time_to_pixel_unrounded (origin);
if (view_x != model_x) {
@ -840,7 +834,7 @@ AutomationLineBase::sync_model_with_view_point (ControlPoint& cp)
* pixel_to_sample() islinear only depending on zoom level.
*/
const timepos_t view_samples (editing_context.pixel_to_sample (view_x));
const timepos_t view_samples (_editing_context.pixel_to_sample (view_x));
/* measure distance from RegionView origin (this preserves time domain) */
@ -880,7 +874,7 @@ AutomationLineBase::control_points_adjacent (double xval, uint32_t & before, uin
ControlPoint *acp = 0;
double unit_xval;
unit_xval = editing_context.sample_to_pixel_unrounded (xval);
unit_xval = _editing_context.sample_to_pixel_unrounded (xval);
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
@ -936,17 +930,16 @@ AutomationLineBase::is_first_point (ControlPoint& cp)
void
AutomationLineBase::remove_point (ControlPoint& cp)
{
editing_context.begin_reversible_command (_("remove control point"));
_editing_context.begin_reversible_command (_("remove control point"));
XMLNode &before = alist->get_state();
editing_context.get_selection ().clear_points ();
_editing_context.get_selection ().clear_points ();
alist->erase (cp.model());
editing_context.session()->add_command(
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
editing_context.commit_reversible_command ();
editing_context.session()->set_dirty ();
_editing_context.commit_reversible_command ();
_editing_context.session()->set_dirty ();
}
/** Get selectable points within an area.
@ -1109,7 +1102,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
* zoom and scroll into account).
*/
double px = editing_context.duration_to_pixels_unrounded (tx);
double px = _editing_context.duration_to_pixels_unrounded (tx);
add_visible_control_point (vp, pi, px, ty, ai, np);
vp++;
}
@ -1167,7 +1160,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
* from the last point to the very end
*/
double px = editing_context.duration_to_pixels_unrounded (model_to_view_coord_x (_offset + _maximum_time));
double px = _editing_context.duration_to_pixels_unrounded (model_to_view_coord_x (_offset + _maximum_time));
if (control_points[control_points.size() - 1]->get_x() != px && following != e.end()) {
double ty = model_to_view_coord_y (e.unlocked_eval (_offset + _maximum_time));
@ -1189,7 +1182,7 @@ AutomationLineBase::reset_callback (const Evoral::ControlList& events)
update_visibility ();
}
set_selected_points (editing_context.get_selection().points);
set_selected_points (_editing_context.get_selection().points);
}
void
@ -1219,7 +1212,7 @@ AutomationLineBase::queue_reset ()
{
/* this must be called from the GUI thread */
if (editing_context.session()->transport_rolling() && alist->automation_write()) {
if (_editing_context.session()->transport_rolling() && alist->automation_write()) {
/* automation write pass ... defer to a timeout */
/* redraw in 1/4 second */
if (!have_reset_timeout) {
@ -1241,8 +1234,7 @@ AutomationLineBase::clear ()
XMLNode &before = alist->get_state();
alist->clear();
editing_context.session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
_editing_context.add_command (new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
}
void

View File

@ -174,6 +174,7 @@ public:
double dt_to_dx (Temporal::timepos_t const &, Temporal::timecnt_t const &);
ARDOUR::ParameterDescriptor const & param() const { return _desc; }
EditingContext& editing_context() const { return _editing_context; }
protected:
@ -194,7 +195,7 @@ protected:
/** true if we did a push at any point during the current drag */
bool did_push;
EditingContext& editing_context;
EditingContext& _editing_context;
ArdourCanvas::Item& _parent_group;
ArdourCanvas::Rectangle* _drag_base;
ArdourCanvas::Container* group;

View File

@ -330,7 +330,6 @@ AutomationRegionView::entered ()
}
}
void
AutomationRegionView::exited ()
{
@ -338,6 +337,7 @@ AutomationRegionView::exited ()
_line->track_exited();
}
}
void
AutomationRegionView::set_selected (bool yn)
{

View File

@ -156,11 +156,9 @@ AutomationStreamView::set_automation_state (AutoState state)
if (region_views.empty()) {
_pending_automation_state = state;
} else {
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
if ((*i)->the_list()) {
(*i)->the_list()->set_automation_state (state);
for (auto & line : get_lines()) {
if (line->the_list()) {
line->the_list()->set_automation_state (state);
}
}
}
@ -222,10 +220,8 @@ AutomationStreamView::automation_state () const
bool
AutomationStreamView::has_automation () const
{
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
if ((*i)->npoints() > 0) {
for (auto const & line : get_lines()) {
if (line->npoints() > 0) {
return true;
}
}
@ -239,10 +235,8 @@ AutomationStreamView::has_automation () const
void
AutomationStreamView::set_interpolation (AutomationList::InterpolationStyle s)
{
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
(*i)->the_list()->set_interpolation (s);
for (auto & line : get_lines()) {
line->the_list()->set_interpolation (s);
}
}
@ -264,10 +258,8 @@ AutomationStreamView::interpolation () const
void
AutomationStreamView::clear ()
{
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
(*i)->clear ();
for (auto & line : get_lines()) {
line->clear ();
}
}
@ -292,20 +284,18 @@ AutomationStreamView::get_selectables (timepos_t const & start, timepos_t const
void
AutomationStreamView::set_selected_points (PointSelection& ps)
{
list<std::shared_ptr<AutomationLine> > lines = get_lines ();
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
(*i)->set_selected_points (ps);
for (auto & line : get_lines()) {
line->set_selected_points (ps);
}
}
list<std::shared_ptr<AutomationLine> >
list<std::shared_ptr<AutomationLineBase> >
AutomationStreamView::get_lines () const
{
list<std::shared_ptr<AutomationLine> > lines;
list<std::shared_ptr<AutomationLineBase> > lines;
for (list<RegionView*>::const_iterator i = region_views.begin(); i != region_views.end(); ++i) {
AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (*i);
for (auto const & rv : region_views) {
AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (rv);
if (arv) {
lines.push_back (arv->line());
}

View File

@ -66,7 +66,7 @@ public:
void get_selectables (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, std::list<Selectable*> &, bool within = false);
void set_selected_points (PointSelection &);
std::list<std::shared_ptr<AutomationLine> > get_lines () const;
std::list<std::shared_ptr<AutomationLineBase> > get_lines () const;
bool paste (Temporal::timepos_t const & pos,
unsigned paste_count,

View File

@ -1084,10 +1084,10 @@ AutomationTimeAxisView::has_automation () const
return ( (_line && _line->npoints() > 0) || (_view && _view->has_automation()) );
}
list<std::shared_ptr<AutomationLine> >
list<std::shared_ptr<AutomationLineBase> >
AutomationTimeAxisView::lines () const
{
list<std::shared_ptr<AutomationLine> > lines;
list<std::shared_ptr<AutomationLineBase> > lines;
if (_line) {
lines.push_back (_line);
@ -1167,20 +1167,19 @@ AutomationTimeAxisView::parse_state_id (
void
AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
{
list<std::shared_ptr<AutomationLine> > lines;
if (_line) {
lines.push_back (_line);
} else if (_view) {
lines = _view->get_lines ();
}
list<std::shared_ptr<AutomationLineBase> > lines;
for (list<std::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
cut_copy_clear_one (**i, selection, op);
if (_line) {
cut_copy_clear_one (*_line, selection, op);
} else if (_view) {
for (auto & line : _view->get_lines ()) {
cut_copy_clear_one (*line, selection, op);
}
}
}
void
AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
AutomationTimeAxisView::cut_copy_clear_one (AutomationLineBase& line, Selection& selection, CutCopyOp op)
{
std::shared_ptr<Evoral::ControlList> what_we_got;
std::shared_ptr<AutomationList> alist (line.the_list());

View File

@ -54,6 +54,7 @@ class PublicEditor;
class TimeSelection;
class RegionSelection;
class PointSelection;
class AutomationLineBase;
class AutomationLine;
class Selection;
class Selectable;
@ -95,7 +96,7 @@ public:
std::shared_ptr<AutomationLine> line() { return _line; }
/** @return All AutomationLines associated with this view */
std::list<std::shared_ptr<AutomationLine> > lines () const;
std::list<std::shared_ptr<AutomationLineBase> > lines () const;
AutomationStreamView* automation_view() const { return _view; }
@ -202,7 +203,7 @@ protected:
void build_display_menu ();
void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
void cut_copy_clear_one (AutomationLineBase&, Selection&, Editing::CutCopyOp);
bool paste_one (Temporal::timepos_t const &, unsigned, float times, const Selection&, ItemCounts& counts, bool greedy=false);
void route_going_away ();

View File

@ -88,7 +88,7 @@ ControlPoint::~ControlPoint ()
bool
ControlPoint::event_handler (GdkEvent* event)
{
return PublicEditor::instance().canvas_control_point_event (event, _item, this);
return _line.editing_context().canvas_control_point_event (event, _item, this);
}
void

View File

@ -34,6 +34,8 @@
#include "actions.h"
#include "ardour_ui.h"
#include "automation_line_base.h"
#include "control_point.h"
#include "edit_note_dialog.h"
#include "editing_context.h"
#include "editing_convert.h"
@ -141,6 +143,11 @@ EditingContext::EditingContext (std::string const & name)
, autoscroll_horizontal_allowed (false)
, autoscroll_vertical_allowed (false)
, autoscroll_cnt (0)
, _mouse_changed_selection (false)
, entered_marker (nullptr)
, entered_track (nullptr)
, entered_regionview (nullptr)
, clear_entered_track (false)
{
if (!button_bindings) {
button_bindings = new Bindings ("editor-mouse");
@ -2646,3 +2653,99 @@ EditingContext::get_draw_length_as_beats (bool& success, timepos_t const & posit
return Temporal::Beats();
}
void
EditingContext::select_automation_line (GdkEventButton* event, ArdourCanvas::Item* item, ARDOUR::SelectionOperation op)
{
AutomationLineBase* al = reinterpret_cast<AutomationLineBase*> (item->get_data ("line"));
std::list<Selectable*> selectables;
double mx = event->x;
double my = event->y;
bool press = (event->type == GDK_BUTTON_PRESS);
al->grab_item().canvas_to_item (mx, my);
uint32_t before, after;
samplecnt_t const where = (samplecnt_t) floor (canvas_to_timeline (mx) * samples_per_pixel);
if (!al || !al->control_points_adjacent (where, before, after)) {
return;
}
selectables.push_back (al->nth (before));
selectables.push_back (al->nth (after));
switch (op) {
case SelectionSet:
if (press) {
selection->set (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionAdd:
if (press) {
selection->add (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionToggle:
if (press) {
selection->toggle (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionExtend:
/* XXX */
break;
case SelectionRemove:
/* not relevant */
break;
}
}
/** Reset all selected points to the relevant default value */
void
EditingContext::reset_point_selection ()
{
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
ARDOUR::AutomationList::iterator j = (*i)->model ();
(*j)->value = (*i)->line().the_list()->descriptor ().normal;
}
}
EditingContext::EnterContext*
EditingContext::get_enter_context(ItemType type)
{
for (ssize_t i = _enter_stack.size() - 1; i >= 0; --i) {
if (_enter_stack[i].item_type == type) {
return &_enter_stack[i];
}
}
return NULL;
}
void
EditingContext::choose_canvas_cursor_on_entry (ItemType type)
{
if (_drags->active()) {
return;
}
Gdk::Cursor* cursor = which_canvas_cursor(type);
if (!_cursors->is_invalid (cursor)) {
// Push a new enter context
const EnterContext ctx = { type, CursorContext::create(*this, cursor) };
_enter_stack.push_back(ctx);
}
}
void
EditingContext::update_all_enter_cursors ()
{
for (auto & ec : _enter_stack) {
ec.cursor_ctx->change(which_canvas_cursor (ec.item_type));
}
}

View File

@ -59,6 +59,7 @@ namespace Temporal {
class XMLNode;
class ControlPoint;
class CursorContext;
class DragManager;
class EditorCursor;
@ -151,13 +152,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
virtual void instant_save() = 0;
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
* which may not be on the top of the stack.
*/
virtual EnterContext* get_enter_context(ItemType type) = 0;
virtual void begin_selection_op_history () = 0;
virtual void begin_reversible_selection_op (std::string cmd_name) = 0;
virtual void commit_reversible_selection_op () = 0;
@ -256,6 +250,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) = 0;
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const;
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const;
@ -315,6 +310,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
virtual Selection& get_selection() const { return *selection; }
virtual Selection& get_cut_buffer () const { return *cut_buffer; }
void reset_point_selection ();
/** Set the mouse mode (gain, object, range, timefx etc.)
* @param m Mouse mode (defined in editing_syms.h)
* @param force Perform the effects of the change even if no change is required
@ -329,9 +326,19 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
* (defined in editing_syms.h)
*/
Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
virtual Editing::MouseMode effective_mouse_mode () const { return mouse_mode; }
/** @return Whether the current mouse mode is an "internal" editing mode. */
virtual bool internal_editing() const = 0;
virtual bool get_smart_mode() const { return false; }
/** Push the appropriate enter/cursor context on item entry. */
void choose_canvas_cursor_on_entry (ItemType);
/** Update all enter cursors based on current settings. */
void update_all_enter_cursors ();
virtual Gdk::Cursor* get_canvas_cursor () const;
static MouseCursors const* cursors () {
return _cursors;
@ -388,6 +395,20 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
bool on_velocity_scroll_event (GdkEventScroll*);
void pre_render ();
void select_automation_line (GdkEventButton*, ArdourCanvas::Item*, ARDOUR::SelectionOperation);
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
* which may not be on the top of the stack.
*/
virtual EnterContext* get_enter_context(ItemType type);
virtual Gdk::Cursor* which_track_cursor () const = 0;
virtual Gdk::Cursor* which_mode_cursor () const = 0;
virtual Gdk::Cursor* which_trim_cursor (bool left_side) const = 0;
virtual Gdk::Cursor* which_canvas_cursor (ItemType type) const = 0;
/** Undo some transactions.
* @param n Number of transactions to undo.
*/
@ -652,6 +673,20 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
uint32_t autoscroll_cnt;
ArdourCanvas::Rect autoscroll_boundary;
bool _mouse_changed_selection;
ArdourMarker* entered_marker;
TimeAxisView* entered_track;
/** If the mouse is over a RegionView or one of its child canvas items, this is set up
to point to the RegionView. Otherwise it is 0.
*/
RegionView* entered_regionview;
bool clear_entered_track;
virtual void set_entered_track (TimeAxisView*) {};
std::vector<EnterContext> _enter_stack;
PBD::ScopedConnection escape_connection;
virtual void escape () {}
@ -675,4 +710,3 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
#endif /* __ardour_midi_editing_context_h__ */

View File

@ -238,7 +238,6 @@ Editor::Editor ()
, marker_click_behavior (MarkerClickSelectOnly)
, _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
, _notebook_shrunk (false)
, entered_marker (0)
, _show_marker_lines (false)
, clicked_axisview (0)
, clicked_routeview (0)
@ -246,7 +245,6 @@ Editor::Editor ()
, clicked_selection (0)
, clicked_control_point (0)
, button_release_can_deselect (true)
, _mouse_changed_selection (false)
, _popup_region_menu_item (0)
, _track_canvas (0)
, _track_canvas_viewport (0)
@ -377,9 +375,6 @@ Editor::Editor ()
, nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
, current_stepping_trackview (0)
, last_track_height_step_timestamp (0)
, entered_track (0)
, entered_regionview (0)
, clear_entered_track (false)
, _edit_point (EditAtMouse)
, meters_running (false)
, rhythm_ferret (0)

View File

@ -449,13 +449,6 @@ public:
void get_pointer_position (double &, double &) const;
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
* which may not be on the top of the stack.
*/
EnterContext* get_enter_context(ItemType type);
TimeAxisView* stepping_axis_view () {
return _stepping_axis_view;
}
@ -656,7 +649,6 @@ private:
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
TempoMarker* find_marker_for_tempo (Temporal::TempoPoint const &);
MeterMarker* find_marker_for_meter (Temporal::MeterPoint const &);
ArdourMarker* entered_marker;
bool _show_marker_lines;
typedef std::map<ARDOUR::Location*,LocationMarkers*> LocationMarkerMap;
@ -724,7 +716,6 @@ private:
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
bool button_release_can_deselect;
bool _mouse_changed_selection;
void catch_vanishing_regionview (RegionView*);
@ -778,12 +769,6 @@ private:
Gdk::Cursor* which_trim_cursor (bool left_side) const;
Gdk::Cursor* which_canvas_cursor (ItemType type) const;
/** Push the appropriate enter/cursor context on item entry. */
void choose_canvas_cursor_on_entry (ItemType);
/** Update all enter cursors based on current settings. */
void update_all_enter_cursors ();
ArdourCanvas::GtkCanvas* _track_canvas;
ArdourCanvas::GtkCanvasViewport* _track_canvas_viewport;
@ -1137,7 +1122,6 @@ private:
/* EDITING OPERATIONS */
void reset_point_selection ();
void region_lock ();
void region_unlock ();
void toggle_region_lock ();
@ -2070,15 +2054,6 @@ private:
gint track_height_step_timeout();
sigc::connection step_timeout;
TimeAxisView* entered_track;
/** If the mouse is over a RegionView or one of its child canvas items, this is set up
to point to the RegionView. Otherwise it is 0.
*/
RegionView* entered_regionview;
std::vector<EnterContext> _enter_stack;
bool clear_entered_track;
bool left_track_canvas (GdkEventCrossing*);
bool entered_track_canvas (GdkEventCrossing*);
void set_entered_track (TimeAxisView*);

View File

@ -45,6 +45,7 @@
#include "ardour_ui.h"
#include "automation_time_axis.h"
#include "control_point.h"
#include "editor.h"
#include "editing.h"
#include "rgb_macros.h"
@ -882,17 +883,6 @@ Editor::stop_canvas_autoscroll ()
autoscroll_cnt = 0;
}
EditingContext::EnterContext*
Editor::get_enter_context(ItemType type)
{
for (ssize_t i = _enter_stack.size() - 1; i >= 0; --i) {
if (_enter_stack[i].item_type == type) {
return &_enter_stack[i];
}
}
return NULL;
}
bool
Editor::left_track_canvas (GdkEventCrossing* ev)
{
@ -1217,6 +1207,16 @@ Editor::which_track_cursor () const
return cursor;
}
double
Editor::trackviews_height() const
{
if (!_trackview_group) {
return 0;
}
return _visible_canvas_height - _trackview_group->canvas_origin().y;
}
Gdk::Cursor*
Editor::which_canvas_cursor(ItemType type) const
{
@ -1387,36 +1387,242 @@ Editor::which_canvas_cursor(ItemType type) const
return cursor;
}
void
Editor::choose_canvas_cursor_on_entry (ItemType type)
bool
Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
if (_drags->active()) {
return;
ControlPoint* cp;
ArdourMarker * marker;
MeterMarker* m_marker = 0;
TempoMarker* t_marker = 0;
double fraction;
bool ret = true;
/* by the time we reach here, entered_regionview and entered trackview
* will have already been set as appropriate. Things are done this
* way because this method isn't passed a pointer to a variable type of
* thing that is entered (which may or may not be canvas item).
* (e.g. the actual entered regionview)
*/
choose_canvas_cursor_on_entry (item_type);
switch (item_type) {
case GridZoneItem:
break;
case ControlPointItem:
if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
cp->show ();
fraction = 1.0 - (cp->get_y() / cp->line().height());
_verbose_cursor->set (cp->line().get_verbose_cursor_string (fraction));
_verbose_cursor->show ();
}
break;
case GainLineItem:
if (mouse_mode == MouseDraw) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (UIConfiguration::instance().color ("entered gain line"));
}
}
break;
case AutomationLineItem:
if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
}
}
break;
case AutomationTrackItem:
AutomationTimeAxisView* atv;
if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
clear_entered_track = false;
set_entered_track (atv);
}
break;
case MarkerItem:
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = marker;
marker->set_entered (true);
break;
case MeterMarkerItem:
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = m_marker;
/* "music" currently serves as a stand-in for "entered". */
m_marker->set_color ("meter marker music");
break;
case TempoMarkerItem:
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = t_marker;
/* "music" currently serves as a stand-in for "entered". */
t_marker->set_color ("tempo marker music");
break;
case FadeInHandleItem:
case FadeInTrimHandleItem:
if (mouse_mode == MouseObject) {
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
rect->set_fill_color (rv->get_fill_color());
}
}
break;
case FadeOutHandleItem:
case FadeOutTrimHandleItem:
if (mouse_mode == MouseObject) {
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
rect->set_fill_color (rv->get_fill_color ());
}
}
break;
case FeatureLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
line->set_outline_color (0xFF0000FF);
}
break;
case SelectionItem:
break;
case WaveItem:
{
if (entered_regionview) {
entered_regionview->entered();
}
}
break;
default:
break;
}
Gdk::Cursor* cursor = which_canvas_cursor(type);
/* third pass to handle entered track status in a comprehensible way.
*/
if (!_cursors->is_invalid (cursor)) {
// Push a new enter context
const EnterContext ctx = { type, CursorContext::create(*this, cursor) };
_enter_stack.push_back(ctx);
switch (item_type) {
case GainLineItem:
case AutomationLineItem:
case ControlPointItem:
/* these do not affect the current entered track state */
clear_entered_track = false;
break;
case AutomationTrackItem:
/* handled above already */
break;
default:
break;
}
return ret;
}
void
Editor::update_all_enter_cursors ()
bool
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
{
for (auto & ec : _enter_stack) {
ec.cursor_ctx->change(which_canvas_cursor (ec.item_type));
}
}
AutomationLine* al;
ArdourMarker *marker;
TempoMarker *t_marker;
MeterMarker *m_marker;
bool ret = true;
double
Editor::trackviews_height() const
{
if (!_trackview_group) {
return 0;
if (!_enter_stack.empty()) {
_enter_stack.pop_back();
}
return _visible_canvas_height - _trackview_group->canvas_origin().y;
switch (item_type) {
case GridZoneItem:
break;
case ControlPointItem:
_verbose_cursor->hide ();
break;
case GainLineItem:
case AutomationLineItem:
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (al->get_line_color());
}
}
break;
case MarkerItem:
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = 0;
marker->set_entered (false);
break;
case MeterMarkerItem:
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
break;
}
m_marker->set_color ("meter marker");
entered_marker = 0;
break;
case TempoMarkerItem:
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
break;
}
t_marker->set_color ("tempo marker");
entered_marker = 0;
break;
case FadeInTrimHandleItem:
case FadeOutTrimHandleItem:
case FadeInHandleItem:
case FadeOutHandleItem:
{
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
rect->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
}
}
break;
case AutomationTrackItem:
break;
case FeatureLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
line->set_outline_color (UIConfiguration::instance().color ("zero line"));
}
break;
default:
_region_peak_cursor->hide ();
break;
}
return ret;
}

View File

@ -4775,8 +4775,8 @@ MarkerDrag::update_item (Location*)
/* noop */
}
ControlPointDrag::ControlPointDrag (Editor& e, ArdourCanvas::Item* i)
: EditorDrag (e, i, e.time_domain (), e.get_trackview_group(), false)
ControlPointDrag::ControlPointDrag (EditingContext& e, ArdourCanvas::Item* i)
: Drag (e, i, e.time_domain (), e.get_trackview_group(), false)
, _fixed_grab_x (0.0)
, _fixed_grab_y (0.0)
, _cumulative_y_drag (0.0)
@ -4787,7 +4787,7 @@ ControlPointDrag::ControlPointDrag (Editor& e, ArdourCanvas::Item* i)
_zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain ());
}
DEBUG_TRACE (DEBUG::Drags, "New ControlPointDrag\n");
DEBUG_TRACE (DEBUG::Drags, string_compose ("New ControlPointDrag @ %1\n", this));
_point = reinterpret_cast<ControlPoint*> (_item->get_data ("control_point"));
assert (_point);
@ -4911,7 +4911,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
if (!movement_occurred) {
/* just a click */
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
_editor.reset_point_selection ();
editing_context.reset_point_selection ();
}
} else {
@ -4935,7 +4935,7 @@ ControlPointDrag::active (Editing::MouseMode m)
}
/* otherwise active if the point is on an automation line (ie not if its on a region gain line) */
return dynamic_cast<AutomationLine*> (&(_point->line ())) != 0;
return dynamic_cast<AutomationLineBase*> (&(_point->line ())) != 0;
}
LineDrag::LineDrag (Editor& e, ArdourCanvas::Item* i)
@ -4962,7 +4962,7 @@ LineDrag::~LineDrag ()
void
LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
{
_line = reinterpret_cast<AutomationLine*> (_item->get_data ("line"));
_line = reinterpret_cast<AutomationLineBase*> (_item->get_data ("line"));
assert (_line);
_item = &_line->grab_item ();
@ -6399,7 +6399,7 @@ AutomationRangeDrag::AutomationRangeDrag (EditingContext& ec, list<RegionView*>
{
DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
list<std::shared_ptr<AutomationLine>> lines;
list<std::shared_ptr<AutomationLineBase>> lines;
for (list<RegionView*>::const_iterator i = v.begin (); i != v.end (); ++i) {
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*> (*i)) {
@ -6418,12 +6418,12 @@ AutomationRangeDrag::AutomationRangeDrag (EditingContext& ec, list<RegionView*>
* @param offset Offset from the session start to the points in the AutomationLines.
*/
void
AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLine>> const& lines)
AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLineBase>> const& lines)
{
/* find the lines that overlap the ranges being dragged */
list<std::shared_ptr<AutomationLine>>::const_iterator i = lines.begin ();
list<std::shared_ptr<AutomationLineBase>>::const_iterator i = lines.begin ();
while (i != lines.end ()) {
list<std::shared_ptr<AutomationLine>>::const_iterator j = i;
list<std::shared_ptr<AutomationLineBase>>::const_iterator j = i;
++j;
pair<timepos_t, timepos_t> r = (*i)->get_point_x_range ();

View File

@ -84,7 +84,7 @@ class TempoMarker;
class TempoCurve;
class ControlPoint;
class AudioRegionView;
class AutomationLine;
class AutomationLineBase;
class AutomationTimeAxisView;
class VelocityDisplay;
@ -1202,10 +1202,10 @@ private:
};
/** Control point drag */
class ControlPointDrag : public EditorDrag
class ControlPointDrag : public Drag
{
public:
ControlPointDrag (Editor&, ArdourCanvas::Item *);
ControlPointDrag (EditingContext&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1250,7 +1250,7 @@ public:
private:
AutomationLine* _line;
AutomationLineBase* _line;
double _fixed_grab_x;
double _fixed_grab_y;
double _cumulative_y_drag;
@ -1487,7 +1487,7 @@ public:
}
private:
void setup (std::list<std::shared_ptr<AutomationLine> > const &);
void setup (std::list<std::shared_ptr<AutomationLineBase> > const &);
double y_fraction (double global_y_position) const;
double value (std::shared_ptr<ARDOUR::AutomationList> list, Temporal::timepos_t const & x) const;
@ -1495,7 +1495,7 @@ private:
/** A line that is part of the drag */
struct Line {
std::shared_ptr<AutomationLine> line; ///< the line
std::shared_ptr<AutomationLineBase> line; ///< the line
std::list<ControlPoint*> points; ///< points to drag on the line
std::pair<Temporal::timepos_t, Temporal::timepos_t> range; ///< the range of all points on the line, in session time
XMLNode* state; ///< the XML state node before the drag

View File

@ -561,49 +561,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
case AutomationLineItem:
if (eff_mouse_mode != MouseRange && eff_mouse_mode != MouseDraw) {
AutomationLine* al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
std::list<Selectable*> selectables;
double mx = event->button.x;
double my = event->button.y;
al->grab_item().canvas_to_item (mx, my);
uint32_t before, after;
samplecnt_t const where = (samplecnt_t) floor (mx * samples_per_pixel);
if (!al || !al->control_points_adjacent (where, before, after)) {
break;
}
selectables.push_back (al->nth (before));
selectables.push_back (al->nth (after));
switch (op) {
case SelectionSet:
if (press) {
selection->set (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionAdd:
if (press) {
selection->add (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionToggle:
if (press) {
selection->toggle (selectables);
_mouse_changed_selection = true;
}
break;
case SelectionExtend:
/* XXX */
break;
case SelectionRemove:
/* not relevant */
break;
}
select_automation_line (&event->button, item, op);
}
break;
@ -1845,245 +1803,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return false;
}
bool
Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
ControlPoint* cp;
ArdourMarker * marker;
MeterMarker* m_marker = 0;
TempoMarker* t_marker = 0;
double fraction;
bool ret = true;
/* by the time we reach here, entered_regionview and entered trackview
* will have already been set as appropriate. Things are done this
* way because this method isn't passed a pointer to a variable type of
* thing that is entered (which may or may not be canvas item).
* (e.g. the actual entered regionview)
*/
choose_canvas_cursor_on_entry (item_type);
switch (item_type) {
case GridZoneItem:
break;
case ControlPointItem:
if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
cp->show ();
fraction = 1.0 - (cp->get_y() / cp->line().height());
_verbose_cursor->set (cp->line().get_verbose_cursor_string (fraction));
_verbose_cursor->show ();
}
break;
case GainLineItem:
if (mouse_mode == MouseDraw) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (UIConfiguration::instance().color ("entered gain line"));
}
}
break;
case AutomationLineItem:
if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
}
}
break;
case AutomationTrackItem:
AutomationTimeAxisView* atv;
if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
clear_entered_track = false;
set_entered_track (atv);
}
break;
case MarkerItem:
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = marker;
marker->set_entered (true);
break;
case MeterMarkerItem:
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = m_marker;
/* "music" currently serves as a stand-in for "entered". */
m_marker->set_color ("meter marker music");
break;
case TempoMarkerItem:
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = t_marker;
/* "music" currently serves as a stand-in for "entered". */
t_marker->set_color ("tempo marker music");
break;
case FadeInHandleItem:
case FadeInTrimHandleItem:
if (mouse_mode == MouseObject) {
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
rect->set_fill_color (rv->get_fill_color());
}
}
break;
case FadeOutHandleItem:
case FadeOutTrimHandleItem:
if (mouse_mode == MouseObject) {
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
rect->set_fill_color (rv->get_fill_color ());
}
}
break;
case FeatureLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
line->set_outline_color (0xFF0000FF);
}
break;
case SelectionItem:
break;
case WaveItem:
{
if (entered_regionview) {
entered_regionview->entered();
}
}
break;
default:
break;
}
/* third pass to handle entered track status in a comprehensible way.
*/
switch (item_type) {
case GainLineItem:
case AutomationLineItem:
case ControlPointItem:
/* these do not affect the current entered track state */
clear_entered_track = false;
break;
case AutomationTrackItem:
/* handled above already */
break;
default:
break;
}
return ret;
}
bool
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
{
AutomationLine* al;
ArdourMarker *marker;
TempoMarker *t_marker;
MeterMarker *m_marker;
bool ret = true;
if (!_enter_stack.empty()) {
_enter_stack.pop_back();
}
switch (item_type) {
case GridZoneItem:
break;
case ControlPointItem:
_verbose_cursor->hide ();
break;
case GainLineItem:
case AutomationLineItem:
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (al->get_line_color());
}
}
break;
case MarkerItem:
if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
break;
}
entered_marker = 0;
marker->set_entered (false);
break;
case MeterMarkerItem:
if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
break;
}
m_marker->set_color ("meter marker");
entered_marker = 0;
break;
case TempoMarkerItem:
if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
break;
}
t_marker->set_color ("tempo marker");
entered_marker = 0;
break;
case FadeInTrimHandleItem:
case FadeOutTrimHandleItem:
case FadeInHandleItem:
case FadeOutHandleItem:
{
ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
rect->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
}
}
break;
case AutomationTrackItem:
break;
case FeatureLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
line->set_outline_color (UIConfiguration::instance().color ("zero line"));
}
break;
default:
_region_peak_cursor->hide ();
break;
}
return ret;
}
GridType
Editor::determine_mapping_grid_snap(timepos_t t)

View File

@ -5708,16 +5708,6 @@ Editor::duplicate_selection (float times)
}
}
/** Reset all selected points to the relevant default value */
void
Editor::reset_point_selection ()
{
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
ARDOUR::AutomationList::iterator j = (*i)->model ();
(*j)->value = (*i)->line().the_list()->descriptor ().normal;
}
}
void
Editor::center_playhead ()
{

View File

@ -16,6 +16,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "canvas/rectangle.h"
#include "editing_context.h"
#include "editor_drag.h"
#include "keyboard.h"
#include "midi_cue_automation_line.h"
MidiCueAutomationLine::MidiCueAutomationLine (const std::string& name,
@ -26,10 +31,18 @@ MidiCueAutomationLine::MidiCueAutomationLine (const std::string&
const ARDOUR::ParameterDescriptor& desc)
: AutomationLineBase (name, ec, parent, drag_base, al, desc)
{
_drag_base->set_data ("line", this);
_drag_base->Event.connect (sigc::mem_fun (*this, &MidiCueAutomationLine::base_event_handler));
}
bool
MidiCueAutomationLine::event_handler (GdkEvent*)
MidiCueAutomationLine::base_event_handler (GdkEvent* ev)
{
return true;
return _editing_context.typed_event (_drag_base, ev, AutomationTrackItem);
}
bool
MidiCueAutomationLine::event_handler (GdkEvent* ev)
{
return _editing_context.typed_event (line, ev, AutomationLineItem);
}

View File

@ -31,6 +31,7 @@ class MidiCueAutomationLine : public AutomationLineBase
std::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc);
bool base_event_handler (GdkEvent*);
bool event_handler (GdkEvent*);
};

View File

@ -393,6 +393,12 @@ MidiCueEditor::current_page_samples() const
return (samplecnt_t) _visible_canvas_width* samples_per_pixel;
}
bool
MidiCueEditor::canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item* item, ControlPoint* cp)
{
return typed_event (item, event, ControlPointItem);
}
bool
MidiCueEditor::canvas_note_event (GdkEvent* event, ArdourCanvas::Item* item)
{
@ -518,6 +524,11 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
}
return true;
case ControlPointItem:
_drags->set (new ControlPointDrag (*this, item), event);
return true;
break;
case VelocityItem:
_drags->set (new LollipopDrag (*this, item), event);
return true;
@ -528,6 +539,17 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
return true;
break;
case AutomationTrackItem:
_drags->set (new AutomationDrawDrag (*this, nullptr, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
return true;
break;
case AutomationLineItem: {
ARDOUR::SelectionOperation op = ArdourKeyboard::selection_type (event->button.state);
select_automation_line (&event->button, item, op);
return true;
}
default:
break;
}
@ -604,18 +626,6 @@ MidiCueEditor::motion_handler (ArdourCanvas::Item*, GdkEvent* event, bool from_a
return true;
}
bool
MidiCueEditor::enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
{
return true;
}
bool
MidiCueEditor::leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
{
return true;
}
bool
MidiCueEditor::key_press_handler (ArdourCanvas::Item*, GdkEvent* ev, ItemType)
{
@ -1455,3 +1465,165 @@ MidiCueEditor::escape ()
view->clear_note_selection ();
}
Gdk::Cursor*
MidiCueEditor::which_track_cursor () const
{
return _cursors->grabber;
}
Gdk::Cursor*
MidiCueEditor::which_mode_cursor () const
{
Gdk::Cursor* mode_cursor = MouseCursors::invalid_cursor ();
switch (mouse_mode) {
case Editing::MouseContent:
/* don't use mode cursor, pick a grabber cursor based on the item */
break;
case Editing::MouseDraw:
mode_cursor = _cursors->midi_pencil;
break;
default:
break;
}
return mode_cursor;
}
Gdk::Cursor*
MidiCueEditor::which_trim_cursor (bool left_side) const
{
abort ();
/*NOTREACHED*/
return nullptr;
}
Gdk::Cursor*
MidiCueEditor::which_canvas_cursor (ItemType type) const
{
Gdk::Cursor* cursor = which_mode_cursor ();
if (mouse_mode == Editing::MouseContent) {
/* find correct cursor to use in object/smart mode */
switch (type) {
case AutomationTrackItem:
cursor = which_track_cursor ();
break;
case PlayheadCursorItem:
cursor = _cursors->grabber;
break;
case SelectionItem:
cursor = _cursors->selector;
break;
case ControlPointItem:
cursor = _cursors->fader;
break;
case GainLineItem:
cursor = _cursors->cross_hair;
break;
case AutomationLineItem:
cursor = _cursors->cross_hair;
break;
case StartSelectionTrimItem:
cursor = _cursors->left_side_trim;
break;
case EndSelectionTrimItem:
cursor = _cursors->right_side_trim;
break;
case NoteItem:
cursor = _cursors->grabber_note;
default:
break;
}
} else if (mouse_mode == Editing::MouseDraw) {
/* ControlPointItem is not really specific to region gain mode
but it is the same cursor so don't worry about this for now.
The result is that we'll see the fader cursor if we enter
non-region-gain-line control points while in MouseDraw
mode, even though we can't edit them in this mode.
*/
switch (type) {
case ControlPointItem:
cursor = _cursors->fader;
break;
case NoteItem:
cursor = _cursors->grabber_note;
default:
break;
}
}
return cursor;
}
bool
MidiCueEditor::enter_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type)
{
AutomationLine* al;
choose_canvas_cursor_on_entry (item_type);
switch (item_type) {
case AutomationTrackItem:
/* item is the base rectangle */
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
al->track_entered ();
break;
case AutomationLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (UIConfiguration::instance().color ("entered automation line"));
}
}
break;
default:
break;
}
return true;
}
bool
MidiCueEditor::leave_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type)
{
AutomationLine* al;
if (!_enter_stack.empty()) {
_enter_stack.pop_back();
}
switch (item_type) {
case ControlPointItem:
_verbose_cursor->hide ();
break;
case AutomationLineItem:
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
line->set_outline_color (al->get_line_color());
}
}
if (ev->crossing.detail != GDK_NOTIFY_INFERIOR) {
al->track_exited ();
}
break;
default:
break;
}
return true;
}

View File

@ -68,6 +68,7 @@ class MidiCueEditor : public CueEditor
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*);
bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*);
bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*);
bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*);
int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; }
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }
@ -98,6 +99,11 @@ class MidiCueEditor : public CueEditor
void midi_action (void (MidiView::*method)());
Gdk::Cursor* which_track_cursor () const;
Gdk::Cursor* which_mode_cursor () const;
Gdk::Cursor* which_trim_cursor (bool left_side) const;
Gdk::Cursor* which_canvas_cursor (ItemType type) const;
protected:
void register_actions ();

View File

@ -33,6 +33,7 @@
#include "midi_cue_view.h"
#include "midi_cue_velocity.h"
#include "note.h"
#include "ui_config.h"
#include "velocity_display.h"
#include "pbd/i18n.h"
@ -70,6 +71,7 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
automation_group = new ArdourCanvas::Rectangle (&parent);
CANVAS_DEBUG_NAME (automation_group, "cue automation group");
automation_group->set_fill_color (UIConfiguration::instance().color ("midi automation track fill"));
velocity_base = new ArdourCanvas::Rectangle (&parent);
CANVAS_DEBUG_NAME (velocity_base, "cue velocity base");
@ -275,7 +277,6 @@ MidiCueView::show_automation (Evoral::Parameter const & param)
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (control);
if (ac) {
std::cerr << "found control, list contains " << ac->alist()->size() << std::endl;
automation_line = new MidiCueAutomationLine ("whatevs",
_editing_context,
*automation_group,

View File

@ -1753,8 +1753,6 @@ MidiView::add_note(const std::shared_ptr<NoteType> note, bool visible)
event = 0;
}
std::cerr << "add note, event " << event << std::endl;
if (event) {
ghost_add_note (event);

View File

@ -2606,7 +2606,7 @@ RouteTimeAxisView::automation_child(Evoral::Parameter param, PBD::ID ctrl_id)
return std::shared_ptr<AutomationTimeAxisView>();
}
std::shared_ptr<AutomationLine>
std::shared_ptr<AutomationLineBase>
RouteTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
{
for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
@ -2615,10 +2615,9 @@ RouteTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
if (!atv) {
continue;
}
list<std::shared_ptr<AutomationLine> > lines = atv->lines();
for (list<std::shared_ptr<AutomationLine> >::const_iterator li = lines.begin(); li != lines.end(); ++li) {
if ((*li)->the_list()->id() == alist_id) {
return *li;
for (auto & line : atv->lines()) {
if (line->the_list()->id() == alist_id) {
return line;
}
}
}

View File

@ -207,7 +207,7 @@ protected:
void add_processor_automation_curve (std::shared_ptr<ARDOUR::Processor> r, Evoral::Parameter);
void add_existing_processor_automation_curves (std::weak_ptr<ARDOUR::Processor>);
std::shared_ptr<AutomationLine> automation_child_by_alist_id (PBD::ID);
std::shared_ptr<AutomationLineBase> automation_child_by_alist_id (PBD::ID);
void reset_processor_automation_curves ();

View File

@ -1315,7 +1315,7 @@ Selection::set_state (XMLNode const & node, int)
vector <ControlPoint *> cps;
if (stv) {
std::shared_ptr<AutomationLine> li = stv->automation_child_by_alist_id (alist_id);
std::shared_ptr<AutomationLineBase> li = stv->automation_child_by_alist_id (alist_id);
if (li) {
ControlPoint* cp = li->nth(view_index);
if (cp) {

View File

@ -192,15 +192,14 @@ StripableTimeAxisView::automation_child(Evoral::Parameter param, PBD::ID)
}
}
std::shared_ptr<AutomationLine>
std::shared_ptr<AutomationLineBase>
StripableTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
{
for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
std::shared_ptr<AutomationTimeAxisView> atv (i->second);
std::list<std::shared_ptr<AutomationLine> > lines = atv->lines();
for (std::list<std::shared_ptr<AutomationLine> >::const_iterator li = lines.begin(); li != lines.end(); ++li) {
if ((*li)->the_list()->id() == alist_id) {
return *li;
for (auto & line : atv->lines()) {
if (line->the_list()->id() == alist_id) {
return line;;
}
}
}

View File

@ -38,7 +38,7 @@ public:
virtual void create_automation_child (const Evoral::Parameter& param, bool show) = 0;
virtual std::shared_ptr<AutomationTimeAxisView> automation_child (Evoral::Parameter param, PBD::ID ctrl_id = PBD::ID(0));
virtual std::shared_ptr<AutomationLine> automation_child_by_alist_id (PBD::ID);
virtual std::shared_ptr<AutomationLineBase> automation_child_by_alist_id (PBD::ID);
void request_redraw ();