summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/midi_region_view.cc104
-rw-r--r--gtk2_ardour/midi_region_view.h8
2 files changed, 73 insertions, 39 deletions
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index cf60580327..0900ecc34e 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -472,7 +472,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
beats = 1;
}
- create_note_at (event_x, event_y, beats, true);
+ create_note_at (event_x, event_y, beats, true, true);
}
break;
@@ -486,7 +486,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
beats = 1;
}
- create_note_at (event_x, event_y, beats, true);
+ create_note_at (event_x, event_y, beats, true, true);
break;
}
@@ -515,7 +515,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
const double x = _drag_rect->property_x1();
const double length = trackview.editor().pixel_to_frame (_drag_rect->property_x2() - _drag_rect->property_x1());
- create_note_at (x, _drag_rect->property_y1(), region_frames_to_region_beats(length), true);
+ create_note_at (x, _drag_rect->property_y1(), region_frames_to_region_beats(length), true, false);
}
}
@@ -541,25 +541,28 @@ MidiRegionView::motion (GdkEventMotion* ev)
event_y = ev->y;
group->w2i(event_x, event_y);
+ PublicEditor& editor = trackview.editor ();
+
// convert event_x to global frame
- event_frame = snap_pixel_to_frame (event_x);
+ framecnt_t grid_frames;
+ event_frame = snap_frame_to_grid_underneath (editor.pixel_to_frame (event_x), grid_frames);
- if (!_ghost_note && trackview.editor().current_mouse_mode() != MouseRange
+ if (!_ghost_note && editor.current_mouse_mode() != MouseRange
&& Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())
&& _mouse_state != AddDragging) {
create_ghost_note (ev->x, ev->y);
- } else if (_ghost_note && trackview.editor().current_mouse_mode() != MouseRange
+ } else if (_ghost_note && editor.current_mouse_mode() != MouseRange
&& Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
update_ghost_note (ev->x, ev->y);
- } else if (_ghost_note && trackview.editor().current_mouse_mode() != MouseRange) {
+ } else if (_ghost_note && editor.current_mouse_mode() != MouseRange) {
delete _ghost_note;
_ghost_note = 0;
- trackview.editor().verbose_cursor()->hide ();
- } else if (_ghost_note && trackview.editor().current_mouse_mode() == MouseRange) {
+ editor.verbose_cursor()->hide ();
+ } else if (_ghost_note && editor.current_mouse_mode() == MouseRange) {
update_ghost_note (ev->x, ev->y);
}
@@ -577,7 +580,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
return false;
}
- if (_pressed_button == 1 && trackview.editor().current_mouse_mode() == MouseObject
+ if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject
&& !Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) {
// Select drag start
@@ -603,7 +606,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
_mouse_state = SelectRectDragging;
return true;
- } else if (trackview.editor().internal_editing()) {
+ } else if (editor.internal_editing()) {
// Add note drag start
group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
@@ -615,11 +618,12 @@ MidiRegionView::motion (GdkEventMotion* ev)
_drag_start_y = event_y;
_drag_rect = new ArdourCanvas::SimpleRect(*group);
- _drag_rect->property_x1() = trackview.editor().frame_to_pixel(event_frame);
+ _drag_rect->property_x1() = editor.frame_to_pixel(event_frame);
_drag_rect->property_y1() = midi_stream_view()->note_to_y(
midi_stream_view()->y_to_note(event_y));
- _drag_rect->property_x2() = trackview.editor().frame_to_pixel(event_frame);
+ _drag_rect->property_x2() = editor.frame_to_pixel(event_frame);
+
_drag_rect->property_y2() = _drag_rect->property_y1()
+ floor(midi_stream_view()->note_height());
_drag_rect->property_outline_what() = 0xFF;
@@ -631,7 +635,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
delete _ghost_note;
_ghost_note = 0;
- trackview.editor().verbose_cursor()->hide ();
+ editor.verbose_cursor()->hide ();
return true;
}
@@ -651,7 +655,17 @@ MidiRegionView::motion (GdkEventMotion* ev)
}
if (_mouse_state == AddDragging) {
- event_x = trackview.editor().frame_to_pixel(event_frame);
+ event_x = editor.frame_to_pixel(event_frame);
+
+ if (editor.snap_mode() == SnapNormal) {
+ /* event_frame will have been snapped to the start of the note we are under;
+ it's more intuitive if we use the end of that note here
+ */
+ event_x = editor.frame_to_pixel (event_frame + grid_frames);
+ } else {
+ event_x = editor.frame_to_pixel (event_frame);
+ }
+
}
if (_drag_rect) {
@@ -872,9 +886,10 @@ MidiRegionView::show_list_editor ()
* \param y vertical position in pixels
* \param length duration of the note in beats, which will be snapped to the grid
* \param sh true to make the note 1 frame shorter than the snapped version of \a length.
+ * \param snap_x true to snap x to the grid, otherwise false.
*/
void
-MidiRegionView::create_note_at(double x, double y, double length, bool sh)
+MidiRegionView::create_note_at (double x, double y, double length, bool sh, bool snap_x)
{
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
MidiStreamView* const view = mtv->midi_view();
@@ -885,7 +900,11 @@ MidiRegionView::create_note_at(double x, double y, double length, bool sh)
assert(note <= 127.0);
// Start of note in frames relative to region start
- framepos_t const start_frames = snap_pixel_to_frame (x);
+ framepos_t start_frames = trackview.editor().pixel_to_frame (x);
+ if (snap_x) {
+ framecnt_t grid_frames;
+ start_frames = snap_frame_to_grid_underneath (start_frames, grid_frames);
+ }
assert(start_frames >= 0);
// Snap length
@@ -2346,7 +2365,7 @@ MidiRegionView::snap_pixel_to_frame(double x)
* @return Snapped frame offset from this region's position.
*/
frameoffset_t
-MidiRegionView::snap_frame_to_frame (frameoffset_t x)
+MidiRegionView::snap_frame_to_frame (frameoffset_t x) const
{
PublicEditor& editor = trackview.editor();
@@ -3327,24 +3346,9 @@ MidiRegionView::update_ghost_note (double x, double y)
PublicEditor& editor = trackview.editor ();
- framepos_t unsnapped_frame = editor.pixel_to_frame (x);
- bool success;
- Evoral::MusicalTime grid_beats = editor.get_grid_type_as_beats (success, unsnapped_frame);
-
- if (!success) {
- grid_beats = 1;
- }
-
- framecnt_t const grid_frames = region_beats_to_region_frames (grid_beats);
-
- /* Hack so that we always snap to the note that we are over, instead of snapping
- to the next one if we're more than halfway through the one we're over.
- */
- if (unsnapped_frame >= grid_frames / 2) {
- unsnapped_frame -= grid_frames / 2;
- }
-
- framepos_t f = snap_frame_to_frame (unsnapped_frame);
+ framepos_t const unsnapped_frame = editor.pixel_to_frame (x);
+ framecnt_t grid_frames;
+ framepos_t const f = snap_frame_to_grid_underneath (unsnapped_frame, grid_frames);
/* use region_frames... because we are converting a delta within the region
*/
@@ -3627,3 +3631,31 @@ MidiRegionView::show_verbose_cursor (string const & text, double xoffset, double
trackview.editor().verbose_cursor()->set (text, wx, wy);
trackview.editor().verbose_cursor()->show ();
}
+
+/** @param p A session framepos.
+ * @param grid_frames Filled in with the number of frames that a grid interval is at p.
+ * @return p snapped to the grid subdivision underneath it.
+ */
+framepos_t
+MidiRegionView::snap_frame_to_grid_underneath (framepos_t p, framecnt_t& grid_frames) const
+{
+ PublicEditor& editor = trackview.editor ();
+
+ bool success;
+ Evoral::MusicalTime grid_beats = editor.get_grid_type_as_beats (success, p);
+
+ if (!success) {
+ grid_beats = 1;
+ }
+
+ grid_frames = region_beats_to_region_frames (grid_beats);
+
+ /* Hack so that we always snap to the note that we are over, instead of snapping
+ to the next one if we're more than halfway through the one we're over.
+ */
+ if (editor.snap_mode() == SnapNormal && p >= grid_frames / 2) {
+ p -= grid_frames / 2;
+ }
+
+ return snap_frame_to_frame (p);
+}
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index 29a5d648da..ffce48dea0 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -169,8 +169,6 @@ public:
void end_write();
void extend_active_notes();
- void create_note_at(double x, double y, double length, bool);
-
void display_model(boost::shared_ptr<ARDOUR::MidiModel> model);
void start_note_diff_command (std::string name = "midi edit");
@@ -253,7 +251,7 @@ public:
*/
framepos_t snap_pixel_to_frame(double x);
- ARDOUR::frameoffset_t snap_frame_to_frame (ARDOUR::frameoffset_t);
+ ARDOUR::frameoffset_t snap_frame_to_frame (ARDOUR::frameoffset_t) const;
/** Convert a timestamp in beats into frames (both relative to region start) */
framepos_t region_beats_to_region_frames(double beats) const;
@@ -317,6 +315,8 @@ private:
friend class EditNoteDialog;
+ void create_note_at(double x, double y, double length, bool, bool);
+
/** Play the NoteOn event of the given note immediately
* and schedule the playback of the corresponding NoteOff event.
*/
@@ -460,6 +460,8 @@ private:
double _last_event_x;
double _last_event_y;
+ framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
+
PBD::ScopedConnection _mouse_mode_connection;
Gdk::Cursor* _pre_enter_cursor;