13
0

allow dragging in MIDI automation line in cue editor

Note: once this is cleaned up and checked with respect to snap and more,
the same should be done for MidiRegionView
This commit is contained in:
Paul Davis 2024-10-07 16:28:54 -06:00
parent 4b8c51574d
commit b8fb779fa7
10 changed files with 87 additions and 66 deletions

View File

@ -63,11 +63,11 @@ class PublicEditor;
class EditorAutomationLine : public AutomationLine class EditorAutomationLine : public AutomationLine
{ {
public: public:
EditorAutomationLine (const std::string& name, EditorAutomationLine (const std::string& name,
TimeAxisView& tv, TimeAxisView& tv,
ArdourCanvas::Item& parent, ArdourCanvas::Item& parent,
std::shared_ptr<ARDOUR::AutomationList> al, std::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc); const ARDOUR::ParameterDescriptor& desc);
virtual ~EditorAutomationLine (); virtual ~EditorAutomationLine ();

View File

@ -101,7 +101,7 @@ MergeableLine::merge_drawn_line (EditingContext& e, Session& s, Evoral::ControlL
XMLNode& after = list->get_state(); XMLNode& after = list->get_state();
e.begin_reversible_command (_("draw automation")); e.begin_reversible_command (_("draw automation"));
s.add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after)); e.add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
_line->end_draw_merge (); _line->end_draw_merge ();

View File

@ -26,7 +26,7 @@
#include "ardour/types.h" #include "ardour/types.h"
class EditorAutomationLine; class AutomationLine;
class RouteTimeAxisView; class RouteTimeAxisView;
class EditingContext; class EditingContext;
@ -38,7 +38,7 @@ class AutomationControl;
class MergeableLine class MergeableLine
{ {
public: public:
MergeableLine (std::shared_ptr<EditorAutomationLine> l, std::shared_ptr<ARDOUR::AutomationControl> c, MergeableLine (std::shared_ptr<AutomationLine> l, std::shared_ptr<ARDOUR::AutomationControl> c,
std::function<Temporal::timepos_t(Temporal::timepos_t const &)> tf, std::function<Temporal::timepos_t(Temporal::timepos_t const &)> tf,
std::function<void(ARDOUR::AutoState)> asc, std::function<void(ARDOUR::AutoState)> asc,
std::function<void()> ctc) std::function<void()> ctc)
@ -53,7 +53,7 @@ class MergeableLine
void merge_drawn_line (EditingContext& e, ARDOUR::Session& s, Evoral::ControlList::OrderedPoints& points, bool thin); void merge_drawn_line (EditingContext& e, ARDOUR::Session& s, Evoral::ControlList::OrderedPoints& points, bool thin);
private: private:
std::shared_ptr<EditorAutomationLine> _line; std::shared_ptr<AutomationLine> _line;
std::shared_ptr<ARDOUR::AutomationControl> _control; std::shared_ptr<ARDOUR::AutomationControl> _control;
std::function<Temporal::timepos_t(Temporal::timepos_t const &)> time_filter; std::function<Temporal::timepos_t(Temporal::timepos_t const &)> time_filter;
std::function<void(ARDOUR::AutoState)> automation_state_callback; std::function<void(ARDOUR::AutoState)> automation_state_callback;

View File

@ -29,7 +29,7 @@ MidiCueAutomationLine::MidiCueAutomationLine (const std::string&
ArdourCanvas::Rectangle* drag_base, ArdourCanvas::Rectangle* drag_base,
std::shared_ptr<ARDOUR::AutomationList> al, std::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc) const ARDOUR::ParameterDescriptor& desc)
: AutomationLine (name, ec, parent, drag_base, al, desc) : AutomationLine (name, ec, parent, drag_base, al, desc)
{ {
_drag_base->set_data ("line", this); _drag_base->set_data ("line", this);
_drag_base->Event.connect (sigc::mem_fun (*this, &MidiCueAutomationLine::base_event_handler)); _drag_base->Event.connect (sigc::mem_fun (*this, &MidiCueAutomationLine::base_event_handler));

View File

@ -510,9 +510,9 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
{ {
NoteBase* note = nullptr; NoteBase* note = nullptr;
if (mouse_mode == Editing::MouseContent) { switch (item_type) {
switch (item_type) { case NoteItem:
case NoteItem: if (mouse_mode == Editing::MouseContent) {
/* Existing note: allow trimming/motion */ /* Existing note: allow trimming/motion */
if ((note = reinterpret_cast<NoteBase*> (item->get_data ("notebase")))) { if ((note = reinterpret_cast<NoteBase*> (item->get_data ("notebase")))) {
if (note->big_enough_to_trim() && note->mouse_near_ends()) { if (note->big_enough_to_trim() && note->mouse_near_ends()) {
@ -523,47 +523,51 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
_drags->set (nd, event); _drags->set (nd, 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;
break;
case VelocityBaseItem:
_drags->set (new VelocityLineDrag (*this, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
return true;
break;
case AutomationTrackItem:
switch (mouse_mode) {
case Editing::MouseContent:
/* rubberband drag to select automation points */
// _drags->set (new EditorRubberbandSelectDrag (*this, item), event);
break;
case Editing::MouseDraw:
_drags->set (new AutomationDrawDrag (*this, nullptr, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
break;
default:
break;
}
return true;
break;
case EditorAutomationLineItem: {
ARDOUR::SelectionOperation op = ArdourKeyboard::selection_type (event->button.state);
select_automation_line (&event->button, item, op);
return true;
} }
return true;
case ControlPointItem:
if (mouse_mode == Editing::MouseContent) {
_drags->set (new ControlPointDrag (*this, item), event);
}
return true;
break;
case VelocityItem:
if (mouse_mode == Editing::MouseContent) {
_drags->set (new LollipopDrag (*this, item), event);
}
return true;
break;
case VelocityBaseItem:
_drags->set (new VelocityLineDrag (*this, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
return true;
break;
case AutomationTrackItem:
switch (mouse_mode) {
case Editing::MouseContent:
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
break;
case Editing::MouseDraw:
_drags->set (new AutomationDrawDrag (*this, nullptr, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
break;
default: default:
break; break;
} }
return true;
break;
case EditorAutomationLineItem: {
ARDOUR::SelectionOperation op = ArdourKeyboard::selection_type (event->button.state);
select_automation_line (&event->button, item, op);
return true;
}
default:
break;
} }
return false; return false;

View File

@ -29,6 +29,7 @@
#include "editor_drag.h" #include "editor_drag.h"
#include "hit.h" #include "hit.h"
#include "keyboard.h" #include "keyboard.h"
#include "mergeable_line.h"
#include "midi_cue_automation_line.h" #include "midi_cue_automation_line.h"
#include "midi_cue_view.h" #include "midi_cue_view.h"
#include "midi_cue_velocity.h" #include "midi_cue_velocity.h"
@ -48,7 +49,6 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
MidiViewBackground& bg, MidiViewBackground& bg,
uint32_t basic_color) uint32_t basic_color)
: MidiView (mt, parent, ec, bg, basic_color) : MidiView (mt, parent, ec, bg, basic_color)
, automation_line (nullptr)
, velocity_base (nullptr) , velocity_base (nullptr)
, velocity_display (nullptr) , velocity_display (nullptr)
, _slot_index (slot_index) , _slot_index (slot_index)
@ -72,6 +72,7 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
automation_group = new ArdourCanvas::Rectangle (&parent); automation_group = new ArdourCanvas::Rectangle (&parent);
CANVAS_DEBUG_NAME (automation_group, "cue automation group"); CANVAS_DEBUG_NAME (automation_group, "cue automation group");
automation_group->set_fill_color (UIConfiguration::instance().color ("midi automation track fill")); automation_group->set_fill_color (UIConfiguration::instance().color ("midi automation track fill"));
automation_group->set_data ("linemerger", this);
velocity_base = new ArdourCanvas::Rectangle (&parent); velocity_base = new ArdourCanvas::Rectangle (&parent);
CANVAS_DEBUG_NAME (velocity_base, "cue velocity base"); CANVAS_DEBUG_NAME (velocity_base, "cue velocity base");
@ -249,10 +250,8 @@ MidiCueView::show_automation (Evoral::Parameter const & param)
// return; // return;
// } // }
if (automation_line) { automation_line.reset ();
delete automation_line; automation_control.reset ();
automation_line = nullptr;
}
std::shared_ptr<AutomationControl> control; std::shared_ptr<AutomationControl> control;
@ -274,18 +273,17 @@ MidiCueView::show_automation (Evoral::Parameter const & param)
*/ */
std::shared_ptr<Evoral::Control> control = _midi_region->model()->control (param, true); std::shared_ptr<Evoral::Control> control = _midi_region->model()->control (param, true);
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (control); automation_control = std::dynamic_pointer_cast<AutomationControl> (control);
if (ac) { if (automation_control) {
automation_line = new MidiCueAutomationLine ("whatevs", automation_line.reset (new MidiCueAutomationLine ("whatevs",
_editing_context, _editing_context,
*automation_group, *automation_group,
automation_group, automation_group,
ac->alist(), automation_control->alist(),
ac->desc()); automation_control->desc()));
automation_line->set_height (automation_group->get().height()); automation_line->set_height (automation_group->get().height());
} }
break; break;
} }
@ -299,7 +297,15 @@ MidiCueView::selectable_owners()
{ {
std::list<SelectableOwner*> sl; std::list<SelectableOwner*> sl;
if (automation_line) { if (automation_line) {
sl.push_back (automation_line); sl.push_back (automation_line.get());
} }
return sl; return sl;
} }
MergeableLine*
MidiCueView::make_merger ()
{
return new MergeableLine (automation_line, automation_control,
[this](Temporal::timepos_t const& t) { return t; },
nullptr, nullptr);
}

View File

@ -57,12 +57,14 @@ class MidiCueView : public MidiView
ArdourCanvas::Item* drag_group() const; ArdourCanvas::Item* drag_group() const;
std::list<SelectableOwner*> selectable_owners(); std::list<SelectableOwner*> selectable_owners();
MergeableLine* make_merger ();
protected: protected:
bool scroll (GdkEventScroll* ev); bool scroll (GdkEventScroll* ev);
ArdourCanvas::Rectangle* automation_group; ArdourCanvas::Rectangle* automation_group;
MidiCueAutomationLine* automation_line; std::shared_ptr<MidiCueAutomationLine> automation_line;
std::shared_ptr<ARDOUR::AutomationControl> automation_control;
ArdourCanvas::Rectangle* velocity_base; ArdourCanvas::Rectangle* velocity_base;
VelocityDisplay* velocity_display; VelocityDisplay* velocity_display;

View File

@ -756,3 +756,9 @@ MidiRegionView::set_visibility_note_range (MidiViewBackground::VisibleNoteRange
{ {
dynamic_cast<MidiTimeAxisView*>(&trackview)->set_visibility_note_range (vnr, from_selection); dynamic_cast<MidiTimeAxisView*>(&trackview)->set_visibility_note_range (vnr, from_selection);
} }
MergeableLine*
MidiRegionView::make_merger ()
{
return nullptr;
}

View File

@ -132,6 +132,8 @@ public:
void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool); void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool);
MergeableLine* make_merger ();
protected: protected:
void reset_width_dependent_items (double pixel_width); void reset_width_dependent_items (double pixel_width);
void parameter_changed (std::string const & p); void parameter_changed (std::string const & p);

View File

@ -43,6 +43,7 @@
#include "time_axis_view_item.h" #include "time_axis_view_item.h"
#include "editor_automation_line.h" #include "editor_automation_line.h"
#include "enums.h" #include "enums.h"
#include "line_merger.h"
namespace ARDOUR { namespace ARDOUR {
class MidiRegion; class MidiRegion;
@ -75,7 +76,7 @@ class VelocityGhostRegion;
class EditingContext; class EditingContext;
class PasteContext; class PasteContext;
class MidiView : public virtual sigc::trackable class MidiView : public virtual sigc::trackable, public LineMerger
{ {
public: public:
typedef Evoral::Note<Temporal::Beats> NoteType; typedef Evoral::Note<Temporal::Beats> NoteType;