diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-17 15:58:47 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-17 15:58:47 +0000 |
commit | 3162ffb4f418d85088d53d5e0a4a5d6ce7235e04 (patch) | |
tree | 851bf4f3ad5d7ae0e9a8917dfc3ad8d2c2f7899c | |
parent | 902a087f15dbdb5546b42930b6cd69294cb0851f (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
-rw-r--r-- | gtk2_ardour/canvas-note-event.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 10 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 9 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 189 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 10 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 6 | ||||
-rw-r--r-- | libs/evoral/src/Note.cpp | 2 |
7 files changed, 216 insertions, 26 deletions
diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index 52e7ac5eef..20e0880f05 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -224,24 +224,8 @@ CanvasNoteEvent::on_event(GdkEvent* ev) static double last_x, last_y; double event_x, event_y, dx, dy; bool select_mod; - uint8_t d_velocity = 10; 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) { - _region.change_velocity(this, d_velocity, true); - return true; - } else if (ev->scroll.direction == GDK_SCROLL_DOWN) { - _region.change_velocity(this, -d_velocity, true); - return true; - } else { - return false; - } - case GDK_ENTER_NOTIFY: _region.note_entered(this); //_item->grab_focus(); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 1f7447ca0e..70f5f4d692 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -891,10 +891,14 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred) /* get the playlist where this drag started. we can't use rv->region()->playlist() because we may have copied the region and it has not been attached to a playlist. */ + + source_tv = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view()); + ds = source_tv->get_diskstream(); + from_playlist = ds->playlist(); - assert ((source_tv = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view()))); - assert ((ds = source_tv->get_diskstream())); - assert ((from_playlist = ds->playlist())); + assert (source_tv); + assert (ds); + assert (from_playlist); /* moved to a different audio track, without copying */ diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 02c13fb251..41d14c4f1e 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2558,5 +2558,14 @@ void Editor::set_internal_edit (bool yn) { _internal_editing = yn; + + if (yn) { + mouse_select_button.set_image (*(manage (new Image (::get_icon("midi_tool_select"))))); + mouse_move_button.set_image (*(manage (new Image (::get_icon("midi_tool_pencil"))))); + } else { + mouse_select_button.set_image (*(manage (new Image (::get_xpm("tool_range.xpm"))))); + mouse_move_button.set_image (*(manage (new Image (::get_icon("tool_object"))))); + } + set_canvas_cursor (); } 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; + } + } +} diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index d759b7c411..83cbbc1d77 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -260,7 +260,13 @@ class MidiRegionView : public RegionView /** Return the current selection as a MidiModel or null if there is no selection */ ARDOUR::MidiModel* selection_as_model () const; - + + void goto_previous_note (); + 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); + protected: /** Allows derived types to specify their visibility requirements * to the TimeAxisViewItem parent class. @@ -300,6 +306,8 @@ class MidiRegionView : public RegionView void midi_patch_settings_changed(std::string model, std::string custom_device_mode); void change_note_velocity(ArdourCanvas::CanvasNoteEvent* ev, int8_t vel, bool relative=false); + void change_note_note(ArdourCanvas::CanvasNoteEvent* ev, int8_t note, bool relative=false); + void change_note_time(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::TimeType, bool relative=false); void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev); void clear_selection() { clear_selection_except(NULL); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 32ef8f58c5..c782882c0f 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2151,10 +2151,12 @@ Session::begin_reversible_command(const string& name) { UndoTransaction* trans = new UndoTransaction(); trans->set_name(name); + if (!_current_trans.empty()) { - _current_trans.top()->add_command(trans); + _current_trans.top()->add_command (trans); + } else { + _current_trans.push(trans); } - _current_trans.push(trans); } void diff --git a/libs/evoral/src/Note.cpp b/libs/evoral/src/Note.cpp index 51aee00958..d86f7b8948 100644 --- a/libs/evoral/src/Note.cpp +++ b/libs/evoral/src/Note.cpp @@ -39,7 +39,7 @@ Note<Time>::Note(uint8_t chan, Time t, Time l, uint8_t n, uint8_t v) _off_event.buffer()[2] = 0x40; assert(time() == t); - assert(length() - l <= std::numeric_limits<Time>::epsilon()); + assert(length() - l <= 1.0/1920.0); /* acceptable tolerance is 1/ppqn. Nice if there was no magic number here */ assert(note() == n); assert(velocity() == v); assert(_on_event.channel() == _off_event.channel()); |