diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-18 02:37:57 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-18 02:37:57 +0000 |
commit | b116282bbb91404f5772643473485e23946a9b40 (patch) | |
tree | f7e7239e4a10a9a9df1a1274dedb0bae781e513c | |
parent | 3162ffb4f418d85088d53d5e0a4a5d6ce7235e04 (diff) |
make shift-click for extend-selection sort-of work for MIDI
git-svn-id: svn://localhost/ardour2/branches/3.0@5541 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/canvas-note-event.cc | 21 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 153 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/public_editor.h | 2 |
5 files changed, 131 insertions, 53 deletions
diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index 20e0880f05..145ee5e0ba 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -325,22 +325,21 @@ CanvasNoteEvent::on_event(GdkEvent* ev) case Pressed: // Clicked if (editor.current_mouse_mode() == Editing::MouseRange) { _state = None; - if (_selected && !select_mod && _region.selection_size() > 1) { - _region.unique_select(this); - } else if (_selected) { + if (_selected) { _region.note_deselected(this, select_mod); } else { - _region.note_selected(this, select_mod); + bool extend = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::TertiaryModifier); + bool add = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier); + + if (!extend && !add && _region.selection_size() > 1) { + _region.unique_select(this); + } else { + _region.note_selected (this, (extend ? true : add), extend); + } } -#if 0 - } else if (midi_edit_mode == Editing::MidiEditErase) { - _region.start_delta_command(); - _region.command_remove_note(this); - _region.apply_command(); -#endif } - return true; + case Dragging: // Dropped _item->ungrab(ev->button.time); _state = None; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 758772598c..ab71c9453d 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -331,6 +331,8 @@ class Editor : public PublicEditor /* nudge is initiated by transport controls owned by ARDOUR_UI */ + nframes64_t get_nudge_distance (nframes64_t pos, nframes64_t& next); + void nudge_forward (bool next, bool force_playhead); void nudge_backward (bool next, bool force_playhead); @@ -1901,8 +1903,6 @@ public: Gtk::VBox nudge_vbox; AudioClock nudge_clock; - nframes64_t get_nudge_distance (nframes64_t pos, nframes64_t& next); - bool nudge_forward_release (GdkEventButton*); bool nudge_backward_release (GdkEventButton*); diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 248b2cfb9e..4efaa2eed2 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -214,6 +214,10 @@ MidiRegionView::canvas_event(GdkEvent* ev) static ArdourCanvas::SimpleRect* drag_rect = NULL; + /* XXX: note that as of August 2009, the GnomeCanvas does not propagate scroll events + to its items, which means that ev->type == GDK_SCROLL will never be seen + */ + switch (ev->type) { case GDK_SCROLL: if (Keyboard::modifier_state_equals (ev->scroll.state, Keyboard::Level4Modifier)) { @@ -273,11 +277,11 @@ MidiRegionView::canvas_event(GdkEvent* ev) } } else if (ev->key.keyval == GDK_Left) { - nudge_notes (-1.0); + nudge_notes (false); } else if (ev->key.keyval == GDK_Right) { - nudge_notes (1.0); + nudge_notes (true); } return false; @@ -1233,14 +1237,49 @@ MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev) } void -MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add) +MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend) { if (!add) { clear_selection_except(ev); } - if (!ev->selected()) { - add_to_selection (ev); + if (!extend) { + + if (!ev->selected()) { + add_to_selection (ev); + } + + } else { + /* find end of latest note selected, select all between that and the start of "ev" */ + + MidiModel::TimeType earliest = DBL_MAX; + MidiModel::TimeType latest = 0; + + for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) { + if ((*i)->note()->end_time() > latest) { + latest = (*i)->note()->end_time(); + } + if ((*i)->note()->time() < earliest) { + earliest = (*i)->note()->time(); + } + } + + if (ev->note()->end_time() > latest) { + earliest = latest; + latest = ev->note()->end_time(); + } else { + earliest = ev->note()->time(); + } + + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { + if ((*i)->note()->time() >= earliest && (*i)->note()->end_time() <= latest) { + add_to_selection (*i); + } + + if ((*i)->note()->end_time() > latest) { + break; + } + } } } @@ -1655,28 +1694,12 @@ MidiRegionView::change_note_time (CanvasNoteEvent* event, MidiModel::TimeType de } void -MidiRegionView::change_velocity(CanvasNoteEvent* ev, int8_t velocity, bool relative) +MidiRegionView::change_velocities (int8_t velocity, bool relative) { - start_delta_command(_("change velocity")); - - change_note_velocity(ev, velocity, relative); - - for (Selection::iterator i = _selection.begin(); i != _selection.end();) { - Selection::iterator next = i; - ++next; - if ( !(*((*i)->note()) == *(ev->note())) ) { - change_note_velocity(*i, velocity, relative); - } - i = next; + if (_selection.empty()) { + return; } - - apply_command(); -} - -void -MidiRegionView::change_velocities (int8_t velocity, bool relative) -{ start_delta_command(_("change velocities")); for (Selection::iterator i = _selection.begin(); i != _selection.end();) { @@ -1693,6 +1716,10 @@ MidiRegionView::change_velocities (int8_t velocity, bool relative) void MidiRegionView::transpose (bool up, bool fine) { + if (_selection.empty()) { + return; + } + int8_t delta; if (fine) { @@ -1718,8 +1745,40 @@ MidiRegionView::transpose (bool up, bool fine) } void -MidiRegionView::nudge_notes (MidiModel::TimeType delta) +MidiRegionView::nudge_notes (bool forward) { + if (_selection.empty()) { + return; + } + + /* pick a note as the point along the timeline to get the nudge distance. + its not necessarily the earliest note, so we may want to pull the notes out + into a vector and sort before using the first one. + */ + + nframes64_t ref_point = _region->position() + beats_to_frames ((*(_selection.begin()))->note()->time()); + nframes64_t next_pos = ref_point; + + if (forward) { + next_pos += 1; + } else { + if (next_pos == 0) { + return; + } + next_pos -= 1; + } + + trackview.editor().snap_to (next_pos, (forward ? 1 : -1), false); + nframes64_t distance = ref_point - next_pos; + + cerr << "ref was " << ref_point << " next is " << next_pos << endl; + + MidiModel::TimeType delta = frames_to_beats (fabs (distance)); + + if (!forward) { + delta = -delta; + } + start_delta_command (_("nudge")); for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) { @@ -1897,7 +1956,6 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb) copied_note->set_time (paste_pos_beats + copied_note->time() - beat_delta); /* make all newly added notes selected */ - cerr << "\tadd @ " << copied_note->time() << endl; command_add_note (copied_note, true); end_point = copied_note->end_time(); @@ -1911,15 +1969,12 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb) nframes64_t end_frame = _region->position() + beats_to_frames (end_point); nframes64_t region_end = _region->position() + _region->length() - 1; - cerr << "\tEnd frame = " << end_frame << " from " << end_point << " region end = " << region_end << endl; - if (end_frame > region_end) { trackview.session().begin_reversible_command (_("paste")); XMLNode& before (_region->get_state()); _region->set_length (end_frame, this); - cerr << "\textended to " << end_frame << endl; trackview.session().add_command (new MementoCommand<Region>(*_region, &before, &_region->get_state())); } @@ -1929,30 +1984,52 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb) void MidiRegionView::goto_next_note () { - nframes64_t pos = trackview.session().transport_frame(); + // nframes64_t pos = -1; + bool use_next = false; - for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { - nframes64_t npos = _region->position() + beats_to_frames ((*i)->note()->time()); + if (_events.back()->selected()) { + return; + } - if (npos >= pos && !(*i)->selected()) { + for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { + if ((*i)->selected()) { + use_next = true; + continue; + } else if (use_next) { unique_select (*i); - trackview.session().request_locate (npos); + // pos = _region->position() + beats_to_frames ((*i)->note()->time()); return; } } + + /* use the first one */ + + unique_select (_events.front()); + } void MidiRegionView::goto_previous_note () { - nframes64_t pos = trackview.session().transport_frame(); + // nframes64_t pos = -1; + bool use_next = false; + + if (_events.front()->selected()) { + return; + } for (Events::reverse_iterator i = _events.rbegin(); i != _events.rend(); ++i) { - nframes64_t npos = _region->position() + beats_to_frames ((*i)->note()->time()); - if (npos <= pos && !(*i)->selected()) { + if ((*i)->selected()) { + use_next = true; + continue; + } else if (use_next) { unique_select (*i); - trackview.session().request_locate (npos); + // pos = _region->position() + beats_to_frames ((*i)->note()->time()); return; } } + + /* use the last one */ + + unique_select (*(_events.rbegin())); } diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 83cbbc1d77..073b78ad1a 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -172,7 +172,7 @@ class MidiRegionView : public RegionView void note_entered(ArdourCanvas::CanvasNoteEvent* ev); void unique_select(ArdourCanvas::CanvasNoteEvent* ev); - void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add); + void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend=false); void note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add); void delete_selection(); size_t selection_size() { return _selection.size(); } @@ -265,7 +265,7 @@ class MidiRegionView : public RegionView void goto_next_note (); void change_velocities (int8_t velocity, bool relative); void transpose (bool up, bool fine); - void nudge_notes (ARDOUR::MidiModel::TimeType delta); + void nudge_notes (bool forward); protected: /** Allows derived types to specify their visibility requirements diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 85fb7faf70..f2d57a72a2 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -263,6 +263,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void mouse_add_new_marker (nframes64_t where, bool is_cd=false, bool is_xrun=false) = 0; virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0; virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 0; + virtual nframes64_t get_nudge_distance (nframes64_t pos, nframes64_t& next) = 0; + #ifdef WITH_CMT virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0; |