13
0

the basics of lollipop dragging

This commit is contained in:
Paul Davis 2023-06-20 11:28:59 -06:00
parent 2977205f3a
commit cf7ba80fc1
12 changed files with 140 additions and 26 deletions

View File

@ -674,7 +674,7 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C
bool bool
Editor::canvas_velocity_event (GdkEvent *event, ArdourCanvas::Item* item) Editor::canvas_velocity_event (GdkEvent *event, ArdourCanvas::Item* item)
{ {
std::cerr << "Velocity event: " << Gtkmm2ext::event_type_string (event->type) << std::endl; // std::cerr << "Velocity event: " << Gtkmm2ext::event_type_string (event->type) << std::endl;
return typed_event (item, event, VelocityItem); return typed_event (item, event, VelocityItem);
} }

View File

@ -52,6 +52,7 @@
#include "ardour/session_playlists.h" #include "ardour/session_playlists.h"
#include "canvas/canvas.h" #include "canvas/canvas.h"
#include "canvas/lollipop.h"
#include "canvas/scroll_group.h" #include "canvas/scroll_group.h"
#include "ardour_ui.h" #include "ardour_ui.h"
@ -77,6 +78,7 @@
#include "region_gain_line.h" #include "region_gain_line.h"
#include "selection.h" #include "selection.h"
#include "ui_config.h" #include "ui_config.h"
#include "velocity_ghost_region.h"
#include "verbose_cursor.h" #include "verbose_cursor.h"
#include "video_timeline.h" #include "video_timeline.h"
@ -7178,9 +7180,11 @@ RegionMarkerDrag::setup_pointer_sample_offset ()
_pointer_offset = model_abs_pos.distance (raw_grab_time ()); _pointer_offset = model_abs_pos.distance (raw_grab_time ());
} }
LollipopDrag::LollipopDrag (Editor* ed, MidiRegionView* r, ArdourCanvas::Item* i) LollipopDrag::LollipopDrag (Editor* ed, ArdourCanvas::Item* l)
: Drag (ed, i, r->region ()->position ().time_domain ()) : Drag (ed, l, Temporal::BeatTime)
, _primary (dynamic_cast<ArdourCanvas::Lollipop*> (l))
{ {
_region = reinterpret_cast<VelocityGhostRegion*> (_item->get_data ("ghostregionview"));
} }
LollipopDrag::~LollipopDrag () LollipopDrag::~LollipopDrag ()
@ -7191,25 +7195,48 @@ void
LollipopDrag::start_grab (GdkEvent *ev, Gdk::Cursor* c) LollipopDrag::start_grab (GdkEvent *ev, Gdk::Cursor* c)
{ {
Drag::start_grab (ev, c); Drag::start_grab (ev, c);
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&_region->parent_rv);
assert (mrv);
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
mrv->note_selected (note, add, extend);
} }
void void
LollipopDrag::motion (GdkEvent *ev, bool first_move) LollipopDrag::motion (GdkEvent *ev, bool first_move)
{ {
_region->drag_lolli (_primary, &ev->motion);
} }
void void
LollipopDrag::finished (GdkEvent *ev, bool did_move) LollipopDrag::finished (GdkEvent *ev, bool did_move)
{ {
if (!did_move) {
return;
}
int velocity = _region->y_position_to_velocity (_primary->y0());
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&_region->parent_rv);
assert (mrv);
mrv->set_velocity (note, velocity);
} }
void void
LollipopDrag::aborted (bool) LollipopDrag::aborted (bool)
{ {
/* XXX get ghost velocity view etc. to redraw with original values */
} }
void void
LollipopDrag::setup_pointer_sample_offset () LollipopDrag::setup_pointer_sample_offset ()
{ {
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
_pointer_offset = _region->parent_rv.region()->source_beats_to_absolute_time (note->note()->time ()).distance (raw_grab_time ());
} }

View File

@ -56,6 +56,7 @@ namespace ArdourCanvas {
class Item; class Item;
class Line; class Line;
class Rectangle; class Rectangle;
class Lollipop;
} }
namespace PBD { namespace PBD {
@ -81,6 +82,7 @@ class ControlPoint;
class AudioRegionView; class AudioRegionView;
class AutomationLine; class AutomationLine;
class AutomationTimeAxisView; class AutomationTimeAxisView;
class VelocityGhostRegion;
/** Class to manage current drags */ /** Class to manage current drags */
class DragManager class DragManager
@ -1550,7 +1552,7 @@ class RegionMarkerDrag : public Drag
class LollipopDrag : public Drag class LollipopDrag : public Drag
{ {
public: public:
LollipopDrag (Editor*, MidiRegionView*, ArdourCanvas::Item*); LollipopDrag (Editor*, ArdourCanvas::Item*);
~LollipopDrag (); ~LollipopDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1573,8 +1575,8 @@ class LollipopDrag : public Drag
void setup_pointer_sample_offset (); void setup_pointer_sample_offset ();
private: private:
MidiRegionView* _region; VelocityGhostRegion* _region;
NoteBase* _primary; ArdourCanvas::Lollipop* _primary;
}; };
#endif /* __gtk2_ardour_editor_drag_h_ */ #endif /* __gtk2_ardour_editor_drag_h_ */

View File

@ -897,6 +897,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true; return true;
break; break;
case VelocityItem:
_drags->set (new LollipopDrag (this, item), event);
return true;
break;
default: default:
break; break;
} }

View File

@ -221,8 +221,7 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Container* g
: event (e) : event (e)
{ {
if (dynamic_cast<Note*>(e)) { if (dynamic_cast<Note*>(e)) {
item = new ArdourCanvas::Rectangle( item = new ArdourCanvas::Rectangle (g, ArdourCanvas::Rect(e->x0(), e->y0(), e->x1(), e->y1()));
g, ArdourCanvas::Rect(e->x0(), e->y0(), e->x1(), e->y1()));
is_hit = false; is_hit = false;
} else { } else {
Hit* hit = dynamic_cast<Hit*>(e); Hit* hit = dynamic_cast<Hit*>(e);

View File

@ -28,7 +28,7 @@ using namespace ARDOUR;
using ArdourCanvas::Coord; using ArdourCanvas::Coord;
using ArdourCanvas::Duple; using ArdourCanvas::Duple;
Lollipop::Lollipop ( NoteVelocityLollipop (
MidiRegionView& region, ArdourCanvas::Item* parent, const std::shared_ptr<NoteType> note, bool with_events) MidiRegionView& region, ArdourCanvas::Item* parent, const std::shared_ptr<NoteType> note, bool with_events)
: NoteBase (region, with_events, note) : NoteBase (region, with_events, note)
, _lollipop (new ArdourCanvas::Lollipop (parent)) , _lollipop (new ArdourCanvas::Lollipop (parent))
@ -37,73 +37,74 @@ Lollipop::Lollipop (
set_item (_lollipop); set_item (_lollipop);
} }
Lollipop::~Lollipop () NoteVelocity~Lollipop ()
{ {
delete _lollipop; delete _lollipop;
} }
void void
Lollipop::move_event (double dx, double dy) NoteVelocitymove_event (double dx, double dy)
{ {
std::cerr << "move lolli to: " << (Duple (_lollipop->x(), _lollipop->y0()).translate (Duple (dx, dy)), _lollipop->length(), _lollipop->radius()) << std::endl;
_lollipop->set (Duple (_lollipop->x(), _lollipop->y0()).translate (Duple (dx, dy)), _lollipop->length(), _lollipop->radius()); _lollipop->set (Duple (_lollipop->x(), _lollipop->y0()).translate (Duple (dx, dy)), _lollipop->length(), _lollipop->radius());
} }
void void
Lollipop::set_outline_color (uint32_t color) NoteVelocityset_outline_color (uint32_t color)
{ {
_lollipop->set_outline_color (color); _lollipop->set_outline_color (color);
} }
void void
Lollipop::set_fill_color (uint32_t color) NoteVelocityset_fill_color (uint32_t color)
{ {
_lollipop->set_fill_color (color); _lollipop->set_fill_color (color);
} }
void void
Lollipop::show () NoteVelocityshow ()
{ {
_lollipop->show (); _lollipop->show ();
} }
void void
Lollipop::hide () NoteVelocityhide ()
{ {
_lollipop->hide (); _lollipop->hide ();
} }
void void
Lollipop::set (ArdourCanvas::Duple const & d, ArdourCanvas::Coord len, ArdourCanvas::Coord radius) NoteVelocityset (ArdourCanvas::Duple const & d, ArdourCanvas::Coord len, ArdourCanvas::Coord radius)
{ {
_lollipop->set (d, len, radius); _lollipop->set (d, len, radius);
} }
void void
Lollipop::set_x (Coord x) NoteVelocityset_x (Coord x)
{ {
_lollipop->set_x (x); _lollipop->set_x (x);
} }
void void
Lollipop::set_len (Coord l) NoteVelocityset_len (Coord l)
{ {
_lollipop->set_length (l); _lollipop->set_length (l);
} }
void void
Lollipop::set_outline_what (ArdourCanvas::Rectangle::What what) NoteVelocityset_outline_what (ArdourCanvas::Rectangle::What what)
{ {
// _lollipop->set_outline_what (what); // _lollipop->set_outline_what (what);
} }
void void
Lollipop::set_outline_all () NoteVelocityset_outline_all ()
{ {
// _lollipop->set_outline_all (); // _lollipop->set_outline_all ();
} }
void void
Lollipop::set_ignore_events (bool ignore) NoteVelocityset_ignore_events (bool ignore)
{ {
_lollipop->set_ignore_events (ignore); _lollipop->set_ignore_events (ignore);
} }

View File

@ -31,17 +31,17 @@ namespace ArdourCanvas {
class Lollipop; class Lollipop;
} }
class Lollipop : public NoteBase class NoteVelocity : public NoteBase
{ {
public: public:
typedef Evoral::Note<Temporal::Beats> NoteType; typedef Evoral::Note<Temporal::Beats> NoteType;
Lollipop (MidiRegionView& region, NoteVelocity (MidiRegionView& region,
ArdourCanvas::Item* parent, ArdourCanvas::Item* parent,
const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>(), const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>(),
bool with_events = true); bool with_events = true);
~Lollipop (); ~NoteVelocity ();
void set (ArdourCanvas::Duple const &, ArdourCanvas::Coord, ArdourCanvas::Coord); void set (ArdourCanvas::Duple const &, ArdourCanvas::Coord, ArdourCanvas::Coord);
void set_x (ArdourCanvas::Coord); void set_x (ArdourCanvas::Coord);
@ -58,6 +58,8 @@ public:
void set_ignore_events (bool); void set_ignore_events (bool);
ArdourCanvas::Lollipop& lolli() { return *_lollipop; }
void move_event (double dx, double dy); void move_event (double dx, double dy);
private: private:

View File

@ -3369,6 +3369,31 @@ MidiRegionView::change_note_length (NoteBase* event, Temporal::Beats t)
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t); note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t);
} }
void
MidiRegionView::set_velocity (NoteBase* note, int velocity)
{
if (_selection.empty()) {
return;
}
int delta = velocity - note->note()->velocity();
std::cerr << "vel delta = " << delta << std::endl;
start_note_diff_command (_("set velocities"));
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {
Selection::iterator next = i;
++next;
change_note_velocity (*i, delta, true);
i = next;
}
apply_note_diff();
}
void void
MidiRegionView::change_velocities (bool up, bool fine, bool allow_smush, bool all_together) MidiRegionView::change_velocities (bool up, bool fine, bool allow_smush, bool all_together)
{ {

View File

@ -54,10 +54,10 @@ namespace MIDI {
}; };
class SysEx; class SysEx;
class NoteBase;
class Note; class Note;
class Hit; class Hit;
class MidiTimeAxisView; class MidiTimeAxisView;
class NoteBase;
class GhostRegion; class GhostRegion;
class AutomationTimeAxisView; class AutomationTimeAxisView;
class AutomationRegionView; class AutomationRegionView;
@ -67,6 +67,7 @@ class EditNoteDialog;
class PatchChange; class PatchChange;
class ItemCounts; class ItemCounts;
class CursorContext; class CursorContext;
class VelocityGhostRegion;
class MidiRegionView : public RegionView class MidiRegionView : public RegionView
{ {
@ -286,6 +287,7 @@ public:
void goto_next_note (bool add_to_selection); void goto_next_note (bool add_to_selection);
void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end); void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end);
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together); void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity);
void transpose (bool up, bool fine, bool allow_smush); void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine); void nudge_notes (bool forward, bool fine);
void channel_edit (); void channel_edit ();
@ -502,6 +504,7 @@ public:
std::shared_ptr<PatchChange> find_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr p); std::shared_ptr<PatchChange> find_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr p);
std::shared_ptr<SysEx> find_canvas_sys_ex (ARDOUR::MidiModel::SysExPtr s); std::shared_ptr<SysEx> find_canvas_sys_ex (ARDOUR::MidiModel::SysExPtr s);
friend class VelocityGhostRegion;
void update_note (NoteBase*, bool update_ghost_regions = true); void update_note (NoteBase*, bool update_ghost_regions = true);
void update_sustained (Note *, bool update_ghost_regions = true); void update_sustained (Note *, bool update_ghost_regions = true);
void update_hit (Hit *, bool update_ghost_regions = true); void update_hit (Hit *, bool update_ghost_regions = true);

View File

@ -79,6 +79,8 @@ VelocityGhostRegion::add_note (NoteBase* nb)
events.insert (std::make_pair (nb->note(), event)); events.insert (std::make_pair (nb->note(), event));
l->Event.connect (sigc::bind (sigc::mem_fun (*this, &VelocityGhostRegion::lollevent), event)); l->Event.connect (sigc::bind (sigc::mem_fun (*this, &VelocityGhostRegion::lollevent), event));
l->raise_to_top (); l->raise_to_top ();
l->set_data (X_("ghostregionview"), this);
l->set_data (X_("note"), nb);
event->item->set_fill_color (UIConfiguration::instance().color_mod(nb->base_color(), "ghost track midi fill")); event->item->set_fill_color (UIConfiguration::instance().color_mod(nb->base_color(), "ghost track midi fill"));
event->item->set_outline_color (_outline); event->item->set_outline_color (_outline);
@ -125,3 +127,45 @@ VelocityGhostRegion::set_colors ()
{ {
base_rect->set_fill_color (Gtkmm2ext::Color (0xff000085)); base_rect->set_fill_color (Gtkmm2ext::Color (0xff000085));
} }
void
VelocityGhostRegion::drag_lolli (ArdourCanvas::Lollipop* l, GdkEventMotion* ev)
{
ArdourCanvas::Rect r (base_rect->item_to_window (base_rect->get()));
/* translate event y-coord so that zero matches the top of base_rect */
ev->y -= r.y0;
/* clamp y to be within the range defined by the base_rect height minus
* the lollipop radius at top and bottom
*/
const double effective_y = std::max (lollipop_radius, std::min (r.height() - (2.0 * lollipop_radius), ev->y));
std::cerr << "new y " << effective_y << std::endl;
l->set (ArdourCanvas::Duple (l->x(), effective_y), r.height() - effective_y - lollipop_radius, lollipop_radius);
}
int
VelocityGhostRegion::y_position_to_velocity (double y) const
{
const ArdourCanvas::Rect r (base_rect->get());
int velocity;
std::cerr << "y = " << y << " h = " << r.height() << std::endl;
if (y >= r.height() - (2.0 * lollipop_radius)) {
velocity = 0;
} else if (y <= lollipop_radius) {
velocity = 127;
} else {
velocity = floor (127. * ((r.height() - y) / r.height()));
}
std::cerr << " y = " << y << " vel = " << velocity << std::endl;
return velocity;
}

View File

@ -23,6 +23,10 @@
#include "ghostregion.h" #include "ghostregion.h"
namespace ArdourCanvas {
class Lollipop;
}
class VelocityGhostRegion : public MidiGhostRegion class VelocityGhostRegion : public MidiGhostRegion
{ {
public: public:
@ -36,6 +40,9 @@ public:
void remove_note (NoteBase*); void remove_note (NoteBase*);
void set_colors (); void set_colors ();
void drag_lolli (ArdourCanvas::Lollipop* l, GdkEventMotion* ev);
int y_position_to_velocity (double y) const;
private: private:
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*); bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);

View File

@ -152,7 +152,6 @@ gtk2_ardour_sources = [
'level_meter.cc', 'level_meter.cc',
'library_download_dialog.cc', 'library_download_dialog.cc',
'location_ui.cc', 'location_ui.cc',
'lollipop.cc',
'loudness_dialog.cc', 'loudness_dialog.cc',
'loudness_settings.cc', 'loudness_settings.cc',
'lua_script_manager.cc', 'lua_script_manager.cc',