summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-08-18 02:37:57 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-08-18 02:37:57 +0000
commitb116282bbb91404f5772643473485e23946a9b40 (patch)
treef7e7239e4a10a9a9df1a1274dedb0bae781e513c
parent3162ffb4f418d85088d53d5e0a4a5d6ce7235e04 (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.cc21
-rw-r--r--gtk2_ardour/editor.h4
-rw-r--r--gtk2_ardour/midi_region_view.cc153
-rw-r--r--gtk2_ardour/midi_region_view.h4
-rw-r--r--gtk2_ardour/public_editor.h2
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;