From f7bff95fbce75cb0d4c717b1400677edd814f7be Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 25 May 2010 23:14:41 +0000 Subject: [PATCH] Rudimentary ghost note when adding MIDI notes to a region, as per #3180. git-svn-id: svn://localhost/ardour2/branches/3.0@7162 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-note.h | 16 +++++++ gtk2_ardour/editor.cc | 4 +- gtk2_ardour/midi_region_view.cc | 78 ++++++++++++++++++++++++++++++++- gtk2_ardour/midi_region_view.h | 8 ++++ gtk2_ardour/public_editor.h | 2 + 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/gtk2_ardour/canvas-note.h b/gtk2_ardour/canvas-note.h index b65eae53d6..6147941ad2 100644 --- a/gtk2_ardour/canvas-note.h +++ b/gtk2_ardour/canvas-note.h @@ -55,6 +55,22 @@ public: } }; +class NoEventCanvasNote : public CanvasNote +{ +public: + NoEventCanvasNote ( + MidiRegionView& region, + Group& group, + const boost::shared_ptr note = boost::shared_ptr() + ) + : CanvasNote (region, group, note) {} + + double point_vfunc(double, double, int, int, GnomeCanvasItem**) { + /* return a huge value to tell the canvas that we're never the item for an event */ + return 9999999999999.0; + } +}; + } // namespace Gnome } // namespace Canvas diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 78dcdcd091..353f4099f4 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -2128,7 +2128,9 @@ Editor::set_snap_to (SnapType st) default: /* relax */ break; - } + } + + SnapChanged (); /* EMIT SIGNAL */ } void diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index c78386ab02..c1c7f650e7 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -85,6 +85,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & , _note_group(new ArdourCanvas::Group(*parent)) , _delta_command(0) , _diff_command(0) + , _ghost_note(0) , _mouse_state(None) , _pressed_button(0) , _sort_needed (true) @@ -107,6 +108,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & , _note_group(new ArdourCanvas::Group(*parent)) , _delta_command(0) , _diff_command(0) + , _ghost_note(0) , _mouse_state(None) , _pressed_button(0) , _sort_needed (true) @@ -130,6 +132,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other) , _note_group(new ArdourCanvas::Group(*get_canvas_group())) , _delta_command(0) , _diff_command(0) + , _ghost_note(0) , _mouse_state(None) , _pressed_button(0) , _sort_needed (true) @@ -156,6 +159,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptrsignal_midi_patch_settings_changed().connect( sigc::mem_fun(this, &MidiRegionView::midi_patch_settings_changed)); + + trackview.editor().SnapChanged.connect (snap_changed_connection, invalidator (*this), ui_bind (&MidiRegionView::snap_changed, this), gui_context ()); } bool @@ -363,12 +369,26 @@ MidiRegionView::canvas_event(GdkEvent* ev) return true; case GDK_ENTER_NOTIFY: + { /* FIXME: do this on switch to note tool, too, if the pointer is already in */ Keyboard::magic_widget_grab_focus(); group->grab_focus(); + + if (editor.current_mouse_mode() == MouseRange) { + create_ghost_note (ev->crossing.x, ev->crossing.y); + } break; + } + + case GDK_LEAVE_NOTIFY: + { + delete _ghost_note; + _ghost_note = 0; + break; + } case GDK_MOTION_NOTIFY: + { event_x = ev->motion.x; event_y = ev->motion.y; group->w2i(event_x, event_y); @@ -379,6 +399,10 @@ MidiRegionView::canvas_event(GdkEvent* ev) // convert event_frame back to local coordinates relative to position event_frame -= _region->position(); + if (_ghost_note) { + update_ghost_note (ev->motion.x, ev->motion.y); + } + switch (_mouse_state) { case Pressed: // Maybe start a drag, if we've moved a bit @@ -477,6 +501,7 @@ MidiRegionView::canvas_event(GdkEvent* ev) break; } break; + } case GDK_BUTTON_RELEASE: event_x = ev->motion.x; @@ -533,7 +558,7 @@ MidiRegionView::canvas_event(GdkEvent* ev) drag_rect = 0; default: break; } - + default: break; } @@ -2689,3 +2714,54 @@ MidiRegionView::selection_as_notelist (Notes& selected, bool allow_all_if_none_s } } } + +void +MidiRegionView::update_ghost_note (double x, double y) +{ + _last_ghost_x = x; + _last_ghost_y = y; + + group->w2i (x, y); + nframes64_t f = trackview.editor().pixel_to_frame (x) + _region->position (); + trackview.editor().snap_to (f); + f -= _region->position (); + + bool success; + Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, f); + if (!success) { + beats = 1; + } + + double length = frames_to_beats (snap_frame_to_frame (f + beats_to_frames (beats)) - f); + + _ghost_note->note()->set_time (frames_to_beats (f + _region->start())); + _ghost_note->note()->set_length (length); + _ghost_note->note()->set_note (midi_stream_view()->y_to_note (y)); + + update_note (_ghost_note); +} + +void +MidiRegionView::create_ghost_note (double x, double y) +{ + delete _ghost_note; + _ghost_note = 0; + + boost::shared_ptr g (new NoteType); + _ghost_note = new NoEventCanvasNote (*this, *group, g); + update_ghost_note (x, y); + _ghost_note->show (); + + _last_ghost_x = x; + _last_ghost_y = y; +} + +void +MidiRegionView::snap_changed () +{ + if (!_ghost_note) { + return; + } + + create_ghost_note (_last_ghost_x, _last_ghost_y); +} diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 77215e9b90..3fb3cfd1e3 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -369,6 +369,9 @@ class MidiRegionView : public RegionView ArdourCanvas::Group* _note_group; ARDOUR::MidiModel::DeltaCommand* _delta_command; ARDOUR::MidiModel::DiffCommand* _diff_command; + ArdourCanvas::CanvasNote* _ghost_note; + double _last_ghost_x; + double _last_ghost_y; MouseState _mouse_state; int _pressed_button; @@ -400,12 +403,17 @@ class MidiRegionView : public RegionView void update_note (ArdourCanvas::CanvasNote*); void update_hit (ArdourCanvas::CanvasHit*); + void create_ghost_note (double, double); + void update_ghost_note (double, double); MidiListEditor* _list_editor; bool no_sound_notes; PBD::ScopedConnection note_delete_connection; void maybe_remove_deleted_note_from_selection (ArdourCanvas::CanvasNoteEvent*); + + void snap_changed (); + PBD::ScopedConnection snap_changed_connection; }; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 6fc7004cc3..2ff5d53326 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -364,6 +364,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible { friend bool relay_key_press (GdkEventKey*, Gtk::Window*); friend bool forward_key_press (GdkEventKey*); + + PBD::Signal0 SnapChanged; }; #endif // __gtk_ardour_public_editor_h__