summaryrefslogtreecommitdiff
path: root/gtk2_ardour/midi_region_view.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-08-17 15:58:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-08-17 15:58:47 +0000
commit3162ffb4f418d85088d53d5e0a4a5d6ce7235e04 (patch)
tree851bf4f3ad5d7ae0e9a8917dfc3ad8d2c2f7899c /gtk2_ardour/midi_region_view.cc
parent902a087f15dbdb5546b42930b6cd69294cb0851f (diff)
move assignments out of assert() in editor_drag (thanks lincoln); change mouse mode buttons when in internal/MIDI mode; arrow key control of note velocity, value and position - hey look ma, MIDI editing!
git-svn-id: svn://localhost/ardour2/branches/3.0@5539 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour/midi_region_view.cc')
-rw-r--r--gtk2_ardour/midi_region_view.cc189
1 files changed, 186 insertions, 3 deletions
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 4967886b7c..248b2cfb9e 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -210,10 +210,27 @@ MidiRegionView::canvas_event(GdkEvent* ev)
static double last_x, last_y;
double event_x, event_y;
nframes64_t event_frame = 0;
+ uint8_t d_velocity = 10;
static ArdourCanvas::SimpleRect* drag_rect = NULL;
switch (ev->type) {
+ case GDK_SCROLL:
+ if (Keyboard::modifier_state_equals (ev->scroll.state, Keyboard::Level4Modifier)) {
+ d_velocity = 1;
+ }
+
+ if (ev->scroll.direction == GDK_SCROLL_UP) {
+ change_velocities (d_velocity, true);
+ return true;
+ } else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
+ change_velocities(-d_velocity, true);
+ return true;
+ } else {
+ return false;
+ }
+ break;
+
case GDK_KEY_PRESS:
if (ev->key.keyval == GDK_Shift_L || ev->key.keyval == GDK_Control_L) {
_mouse_state = SelectTouchDragging;
@@ -232,6 +249,36 @@ MidiRegionView::canvas_event(GdkEvent* ev)
} else if (ev->key.keyval == GDK_Shift_L || ev->key.keyval == GDK_Control_L) {
_mouse_state = None;
return true;
+ } else if (ev->key.keyval == GDK_Tab) {
+ if (Keyboard::modifier_state_equals (ev->key.state, Keyboard::PrimaryModifier)) {
+ goto_previous_note ();
+ } else {
+ goto_next_note ();
+ }
+ return true;
+ } else if (ev->key.keyval == GDK_Up) {
+
+ if (Keyboard::modifier_state_equals (ev->key.state, Keyboard::PrimaryModifier)) {
+ change_velocities (1, true);
+ } else {
+ transpose (true, false);
+ }
+
+ } else if (ev->key.keyval == GDK_Down) {
+
+ if (Keyboard::modifier_state_equals (ev->key.state, Keyboard::PrimaryModifier)) {
+ change_velocities (-1, true);
+ } else {
+ transpose (false, false);
+ }
+ } else if (ev->key.keyval == GDK_Left) {
+
+ nudge_notes (-1.0);
+
+ } else if (ev->key.keyval == GDK_Right) {
+
+ nudge_notes (1.0);
+
}
return false;
@@ -468,7 +515,6 @@ MidiRegionView::clear_events()
void
MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
{
- cerr << "MRV: display mode, enable = " << _enable_display << endl;
_model = model;
content_connection.disconnect ();
content_connection = _model->ContentsChanged.connect(sigc::mem_fun(this, &MidiRegionView::redisplay_model));
@@ -542,7 +588,6 @@ MidiRegionView::abort_command()
void
MidiRegionView::redisplay_model()
{
- cerr << "MRV: display mode, active notes = " << _active_notes << endl;
// Don't redisplay the model if we're currently recording and displaying that
if (_active_notes) {
return;
@@ -1570,6 +1615,46 @@ MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bo
}
void
+MidiRegionView::change_note_note (CanvasNoteEvent* event, int8_t note, bool relative)
+{
+ const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get())));
+
+ if (relative) {
+ uint8_t new_note = copy->note() + note;
+ clamp_to_0_127(new_note);
+ copy->set_note(new_note);
+ } else {
+ copy->set_note(note);
+ }
+
+ command_remove_note(event);
+ command_add_note(copy, event->selected(), false);
+}
+
+void
+MidiRegionView::change_note_time (CanvasNoteEvent* event, MidiModel::TimeType delta, bool relative)
+{
+ const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get())));
+
+ if (relative) {
+ if (delta < 0.0) {
+ if (copy->time() < -delta) {
+ copy->set_time (0);
+ } else {
+ copy->set_time (copy->time() + delta);
+ }
+ } else {
+ copy->set_time (copy->time() + delta);
+ }
+ } else {
+ copy->set_time (delta);
+ }
+
+ command_remove_note(event);
+ command_add_note(copy, event->selected(), false);
+}
+
+void
MidiRegionView::change_velocity(CanvasNoteEvent* ev, int8_t velocity, bool relative)
{
start_delta_command(_("change velocity"));
@@ -1588,6 +1673,66 @@ MidiRegionView::change_velocity(CanvasNoteEvent* ev, int8_t velocity, bool relat
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();) {
+ Selection::iterator next = i;
+ ++next;
+ change_note_velocity (*i, velocity, relative);
+ i = next;
+ }
+
+ apply_command();
+}
+
+
+void
+MidiRegionView::transpose (bool up, bool fine)
+{
+ int8_t delta;
+
+ if (fine) {
+ delta = 1;
+ } else {
+ delta = 12;
+ }
+
+ if (!up) {
+ delta = -delta;
+ }
+
+ start_delta_command (_("transpose"));
+
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
+ Selection::iterator next = i;
+ ++next;
+ change_note_note (*i, delta, true);
+ i = next;
+ }
+
+ apply_command ();
+}
+
+void
+MidiRegionView::nudge_notes (MidiModel::TimeType delta)
+{
+ start_delta_command (_("nudge"));
+
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
+ Selection::iterator next = i;
+ ++next;
+ change_note_time (*i, delta, true);
+ i = next;
+ }
+
+ apply_command ();
+}
+
+
void
MidiRegionView::change_channel(uint8_t channel)
{
@@ -1752,6 +1897,7 @@ 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();
@@ -1762,14 +1908,51 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
/* if we pasted past the current end of the region, extend the region */
- nframes64_t end_frame = beats_to_frames (end_point);
+ 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()));
}
apply_command ();
}
+
+void
+MidiRegionView::goto_next_note ()
+{
+ nframes64_t pos = trackview.session().transport_frame();
+
+ for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
+ nframes64_t npos = _region->position() + beats_to_frames ((*i)->note()->time());
+
+ if (npos >= pos && !(*i)->selected()) {
+ unique_select (*i);
+ trackview.session().request_locate (npos);
+ return;
+ }
+ }
+}
+
+void
+MidiRegionView::goto_previous_note ()
+{
+ nframes64_t pos = trackview.session().transport_frame();
+
+ 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()) {
+ unique_select (*i);
+ trackview.session().request_locate (npos);
+ return;
+ }
+ }
+}