X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmidi_region_view.cc;h=00bdb94dce74911508c11846a94b7a0811c3cd2c;hb=90619f4b9869ceccb29965e916ec07fe197b86da;hp=6fe9768febd2d1531cc541c60768579cf84e675e;hpb=5f2ef08666d7dccf5f3e6c626821d8e54c146e62;p=ardour.git diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 6fe9768feb..00bdb94dce 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -51,6 +51,7 @@ #include "canvas_patch_change.h" #include "debug.h" #include "editor.h" +#include "editor_drag.h" #include "ghostregion.h" #include "gui_thread.h" #include "keyboard.h" @@ -294,12 +295,18 @@ MidiRegionView::init (Gdk::Color const & basic_color, bool wfd) SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), ui_bind (&MidiRegionView::selection_cleared, this, _1), gui_context ()); } +const boost::shared_ptr +MidiRegionView::midi_region() const +{ + return boost::dynamic_pointer_cast(_region); +} + void MidiRegionView::connect_to_diskstream () { midi_view()->midi_track()->DataRecorded.connect( *this, invalidator(*this), - ui_bind(&MidiRegionView::data_recorded, this, _1, _2), + ui_bind(&MidiRegionView::data_recorded, this, _1), gui_context()); } @@ -388,7 +395,7 @@ MidiRegionView::enter_notify (GdkEventCrossing* ev) } bool -MidiRegionView::leave_notify (GdkEventCrossing* ev) +MidiRegionView::leave_notify (GdkEventCrossing*) { _mouse_mode_connection.disconnect (); @@ -456,10 +463,12 @@ MidiRegionView::button_release (GdkEventButton* ev) group->w2i(event_x, event_y); group->ungrab(ev->time); + PublicEditor& editor = trackview.editor (); + switch (_mouse_state) { case Pressed: // Clicked - switch (trackview.editor().current_mouse_mode()) { + switch (editor.current_mouse_mode()) { case MouseObject: case MouseTimeFX: { @@ -474,7 +483,7 @@ MidiRegionView::button_release (GdkEventButton* ev) group->w2i(event_x, event_y); bool success; - Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x)); + Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x)); if (!success) { beats = 1; @@ -488,7 +497,7 @@ MidiRegionView::button_release (GdkEventButton* ev) case MouseRange: { bool success; - Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x)); + Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x)); if (!success) { beats = 1; @@ -506,10 +515,8 @@ MidiRegionView::button_release (GdkEventButton* ev) break; case SelectRectDragging: // Select drag done - + editor.drags()->end_grab ((GdkEvent *) ev); _mouse_state = None; - delete _drag_rect; - _drag_rect = 0; break; case AddDragging: // Add drag done @@ -590,27 +597,8 @@ MidiRegionView::motion (GdkEventMotion* ev) if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject && !Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) { - // Select drag start - - group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - Gdk::Cursor(Gdk::FLEUR), ev->time); - - _last_x = event_x; - _last_y = event_y; - _drag_start_x = event_x; - _drag_start_y = event_y; - - _drag_rect = new ArdourCanvas::SimpleRect(*group); - _drag_rect->property_x1() = event_x; - _drag_rect->property_y1() = event_y; - _drag_rect->property_x2() = event_x; - _drag_rect->property_y2() = event_y; - _drag_rect->property_outline_what() = 0xFF; - _drag_rect->property_outline_color_rgba() - = ARDOUR_UI::config()->canvasvar_MidiSelectRectOutline.get(); - _drag_rect->property_fill_color_rgba() - = ARDOUR_UI::config()->canvasvar_MidiSelectRectFill.get(); + editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast (&editor), this), (GdkEvent *) ev); _mouse_state = SelectRectDragging; return true; @@ -650,7 +638,10 @@ MidiRegionView::motion (GdkEventMotion* ev) return false; - case SelectRectDragging: // Select drag motion + case SelectRectDragging: + editor.drags()->motion_handler ((GdkEvent *) ev, false); + break; + case AddDragging: // Add note drag motion if (ev->is_hint) { @@ -686,18 +677,6 @@ MidiRegionView::motion (GdkEventMotion* ev) } } - if (_drag_rect && _mouse_state == SelectRectDragging) { - - if (event_y > _drag_start_y) { - _drag_rect->property_y2() = event_y; - } - else { - _drag_rect->property_y1() = event_y; - } - - update_drag_selection(_drag_start_x, event_x, _drag_start_y, event_y, Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)); - } - _last_x = event_x; _last_y = event_y; @@ -719,6 +698,13 @@ MidiRegionView::scroll (GdkEventScroll* ev) return false; } + if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + /* XXX: bit of a hack; allow PrimaryModifier scroll through so that + it still works for zoom. + */ + return false; + } + trackview.editor().verbose_cursor()->hide (); bool fine = !Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier); @@ -843,7 +829,7 @@ void MidiRegionView::channel_edit () { bool first = true; - uint8_t current_channel; + uint8_t current_channel = 0; if (_selection.empty()) { return; @@ -1170,8 +1156,17 @@ MidiRegionView::redisplay_model() for (Events::iterator i = _events.begin(); i != _events.end(); ) { if (!(*i)->valid ()) { + + for (vector::iterator j = ghosts.begin(); j != ghosts.end(); ++j) { + MidiGhostRegion* gr = dynamic_cast (*j); + if (gr) { + gr->remove_note (*i); + } + } + delete *i; i = _events.erase (i); + } else { ++i; } @@ -2020,6 +2015,31 @@ MidiRegionView::select_all_notes () } } +void +MidiRegionView::select_range (framepos_t start, framepos_t end) +{ + clear_selection (); + + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { + framepos_t t = source_beats_to_absolute_frames((*i)->note()->time()); + if (t >= start && t <= end) { + add_to_selection (*i); + } + } +} + +void +MidiRegionView::invert_selection () +{ + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { + if ((*i)->selected()) { + remove_from_selection(*i); + } else { + add_to_selection (*i); + } + } +} + void MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend) { @@ -2359,6 +2379,9 @@ MidiRegionView::note_dropped(CanvasNoteEvent *, frameoffset_t dt, int8_t dnote) } } +/** @param x Pixel relative to the region position. + * @return Snapped frame relative to the region position. + */ framepos_t MidiRegionView::snap_pixel_to_frame(double x) { @@ -2366,6 +2389,9 @@ MidiRegionView::snap_pixel_to_frame(double x) return snap_frame_to_frame (editor.pixel_to_frame (x)); } +/** @param x Pixel relative to the region position. + * @return Snapped pixel relative to the region position. + */ double MidiRegionView::snap_to_pixel(double x) { @@ -2505,9 +2531,6 @@ MidiRegionView::update_resizing (ArdourCanvas::CanvasNoteEvent* primary, bool at double beats; beats = snap_pixel_to_frame (current_x); - /* XXX not sure this is correct - snap_pixel_to_frame() - returns an absolute frame. - */ beats = region_frames_to_region_beats (beats); double len; @@ -2570,13 +2593,10 @@ MidiRegionView::commit_resizing (ArdourCanvas::CanvasNoteEvent* primary, bool at } } - /* Convert that to a frame within the region */ + /* Convert that to a frame within the source */ current_x = snap_pixel_to_frame (current_x) + _region->start (); /* and then to beats */ - /* XXX not sure this is correct - snap_pixel_to_frame() - returns an absolute frame. - */ current_x = region_frames_to_region_beats (current_x); if (at_front && current_x < canvas_note->note()->end_time()) { @@ -3243,24 +3263,30 @@ MidiRegionView::goto_next_note (bool add_to_selection) time_sort_events (); + MidiTimeAxisView* const mtv = dynamic_cast(&trackview); + uint16_t const channel_mask = mtv->channel_selector().get_selected_channels (); + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { if ((*i)->selected()) { use_next = true; continue; } else if (use_next) { - if (!add_to_selection) { - unique_select (*i); - } else { - note_selected (*i, true, false); + if (channel_mask & (1 << (*i)->note()->channel())) { + if (!add_to_selection) { + unique_select (*i); + } else { + note_selected (*i, true, false); + } + return; } - return; } } /* use the first one */ - unique_select (_events.front()); - + if (!_events.empty() && (channel_mask & (1 << _events.front()->note()->channel ()))) { + unique_select (_events.front()); + } } void @@ -3274,23 +3300,30 @@ MidiRegionView::goto_previous_note (bool add_to_selection) time_sort_events (); + MidiTimeAxisView* const mtv = dynamic_cast(&trackview); + uint16_t const channel_mask = mtv->channel_selector().get_selected_channels (); + for (Events::reverse_iterator i = _events.rbegin(); i != _events.rend(); ++i) { if ((*i)->selected()) { use_next = true; continue; } else if (use_next) { - if (!add_to_selection) { - unique_select (*i); - } else { - note_selected (*i, true, false); + if (channel_mask & (1 << (*i)->note()->channel())) { + if (!add_to_selection) { + unique_select (*i); + } else { + note_selected (*i, true, false); + } + return; } - return; } } /* use the last one */ - unique_select (*(_events.rbegin())); + if (!_events.empty() && (channel_mask & (1 << (*_events.rbegin())->note()->channel ()))) { + unique_select (*(_events.rbegin())); + } } void @@ -3487,11 +3520,10 @@ MidiRegionView::set_step_edit_cursor_width (Evoral::MusicalTime beats) } /** Called when a diskstream on our track has received some data. Update the view, if applicable. - * @param buf Data that has been recorded. - * @param w Source that this data will end up in. + * @param w Source that the data will end up in. */ void -MidiRegionView::data_recorded (boost::shared_ptr buf, boost::weak_ptr w) +MidiRegionView::data_recorded (boost::weak_ptr w) { if (!_active_notes) { /* we aren't actively being recorded to */ @@ -3505,6 +3537,9 @@ MidiRegionView::data_recorded (boost::shared_ptr buf, boost::weak_pt } MidiTimeAxisView* mtv = dynamic_cast (&trackview); + + boost::shared_ptr buf = mtv->midi_track()->get_gui_feed_buffer (); + BeatsFramesConverter converter (trackview.session()->tempo_map(), mtv->midi_track()->get_capture_start_frame (0)); framepos_t back = max_framepos;