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
This commit is contained in:
parent
902a087f15
commit
3162ffb4f4
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -1569,6 +1614,46 @@ MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bo
|
|||
command_add_note(copy, event->selected(), true);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue