mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
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
This commit is contained in:
parent
3162ffb4f4
commit
b116282bbb
5 changed files with 133 additions and 55 deletions
|
|
@ -325,22 +325,21 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
|
||||||
case Pressed: // Clicked
|
case Pressed: // Clicked
|
||||||
if (editor.current_mouse_mode() == Editing::MouseRange) {
|
if (editor.current_mouse_mode() == Editing::MouseRange) {
|
||||||
_state = None;
|
_state = None;
|
||||||
if (_selected && !select_mod && _region.selection_size() > 1) {
|
if (_selected) {
|
||||||
_region.unique_select(this);
|
|
||||||
} else if (_selected) {
|
|
||||||
_region.note_deselected(this, select_mod);
|
_region.note_deselected(this, select_mod);
|
||||||
} else {
|
} 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 0
|
|
||||||
} else if (midi_edit_mode == Editing::MidiEditErase) {
|
|
||||||
_region.start_delta_command();
|
|
||||||
_region.command_remove_note(this);
|
|
||||||
_region.apply_command();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!extend && !add && _region.selection_size() > 1) {
|
||||||
|
_region.unique_select(this);
|
||||||
|
} else {
|
||||||
|
_region.note_selected (this, (extend ? true : add), extend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Dragging: // Dropped
|
case Dragging: // Dropped
|
||||||
_item->ungrab(ev->button.time);
|
_item->ungrab(ev->button.time);
|
||||||
_state = None;
|
_state = None;
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,8 @@ class Editor : public PublicEditor
|
||||||
|
|
||||||
/* nudge is initiated by transport controls owned by ARDOUR_UI */
|
/* 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_forward (bool next, bool force_playhead);
|
||||||
void nudge_backward (bool next, bool force_playhead);
|
void nudge_backward (bool next, bool force_playhead);
|
||||||
|
|
||||||
|
|
@ -1901,8 +1903,6 @@ public:
|
||||||
Gtk::VBox nudge_vbox;
|
Gtk::VBox nudge_vbox;
|
||||||
AudioClock nudge_clock;
|
AudioClock nudge_clock;
|
||||||
|
|
||||||
nframes64_t get_nudge_distance (nframes64_t pos, nframes64_t& next);
|
|
||||||
|
|
||||||
bool nudge_forward_release (GdkEventButton*);
|
bool nudge_forward_release (GdkEventButton*);
|
||||||
bool nudge_backward_release (GdkEventButton*);
|
bool nudge_backward_release (GdkEventButton*);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,10 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
|
|
||||||
static ArdourCanvas::SimpleRect* drag_rect = NULL;
|
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) {
|
switch (ev->type) {
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
if (Keyboard::modifier_state_equals (ev->scroll.state, Keyboard::Level4Modifier)) {
|
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) {
|
} else if (ev->key.keyval == GDK_Left) {
|
||||||
|
|
||||||
nudge_notes (-1.0);
|
nudge_notes (false);
|
||||||
|
|
||||||
} else if (ev->key.keyval == GDK_Right) {
|
} else if (ev->key.keyval == GDK_Right) {
|
||||||
|
|
||||||
nudge_notes (1.0);
|
nudge_notes (true);
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1233,14 +1237,49 @@ MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add)
|
MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend)
|
||||||
{
|
{
|
||||||
if (!add) {
|
if (!add) {
|
||||||
clear_selection_except(ev);
|
clear_selection_except(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ev->selected()) {
|
if (!extend) {
|
||||||
add_to_selection (ev);
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1654,29 +1693,13 @@ MidiRegionView::change_note_time (CanvasNoteEvent* event, MidiModel::TimeType de
|
||||||
command_add_note(copy, event->selected(), false);
|
command_add_note(copy, event->selected(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MidiRegionView::change_velocity(CanvasNoteEvent* ev, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_command();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::change_velocities (int8_t velocity, bool relative)
|
MidiRegionView::change_velocities (int8_t velocity, bool relative)
|
||||||
{
|
{
|
||||||
|
if (_selection.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
start_delta_command(_("change velocities"));
|
start_delta_command(_("change velocities"));
|
||||||
|
|
||||||
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {
|
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {
|
||||||
|
|
@ -1693,6 +1716,10 @@ MidiRegionView::change_velocities (int8_t velocity, bool relative)
|
||||||
void
|
void
|
||||||
MidiRegionView::transpose (bool up, bool fine)
|
MidiRegionView::transpose (bool up, bool fine)
|
||||||
{
|
{
|
||||||
|
if (_selection.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int8_t delta;
|
int8_t delta;
|
||||||
|
|
||||||
if (fine) {
|
if (fine) {
|
||||||
|
|
@ -1718,8 +1745,40 @@ MidiRegionView::transpose (bool up, bool fine)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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"));
|
start_delta_command (_("nudge"));
|
||||||
|
|
||||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
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);
|
copied_note->set_time (paste_pos_beats + copied_note->time() - beat_delta);
|
||||||
|
|
||||||
/* make all newly added notes selected */
|
/* make all newly added notes selected */
|
||||||
cerr << "\tadd @ " << copied_note->time() << endl;
|
|
||||||
|
|
||||||
command_add_note (copied_note, true);
|
command_add_note (copied_note, true);
|
||||||
end_point = copied_note->end_time();
|
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 end_frame = _region->position() + beats_to_frames (end_point);
|
||||||
nframes64_t region_end = _region->position() + _region->length() - 1;
|
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) {
|
if (end_frame > region_end) {
|
||||||
|
|
||||||
trackview.session().begin_reversible_command (_("paste"));
|
trackview.session().begin_reversible_command (_("paste"));
|
||||||
|
|
||||||
XMLNode& before (_region->get_state());
|
XMLNode& before (_region->get_state());
|
||||||
_region->set_length (end_frame, this);
|
_region->set_length (end_frame, this);
|
||||||
cerr << "\textended to " << end_frame << endl;
|
|
||||||
trackview.session().add_command (new MementoCommand<Region>(*_region, &before, &_region->get_state()));
|
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
|
void
|
||||||
MidiRegionView::goto_next_note ()
|
MidiRegionView::goto_next_note ()
|
||||||
{
|
{
|
||||||
nframes64_t pos = trackview.session().transport_frame();
|
// nframes64_t pos = -1;
|
||||||
|
bool use_next = false;
|
||||||
|
|
||||||
|
if (_events.back()->selected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
|
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||||
nframes64_t npos = _region->position() + beats_to_frames ((*i)->note()->time());
|
if ((*i)->selected()) {
|
||||||
|
use_next = true;
|
||||||
if (npos >= pos && !(*i)->selected()) {
|
continue;
|
||||||
|
} else if (use_next) {
|
||||||
unique_select (*i);
|
unique_select (*i);
|
||||||
trackview.session().request_locate (npos);
|
// pos = _region->position() + beats_to_frames ((*i)->note()->time());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* use the first one */
|
||||||
|
|
||||||
|
unique_select (_events.front());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::goto_previous_note ()
|
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) {
|
for (Events::reverse_iterator i = _events.rbegin(); i != _events.rend(); ++i) {
|
||||||
nframes64_t npos = _region->position() + beats_to_frames ((*i)->note()->time());
|
if ((*i)->selected()) {
|
||||||
if (npos <= pos && !(*i)->selected()) {
|
use_next = true;
|
||||||
|
continue;
|
||||||
|
} else if (use_next) {
|
||||||
unique_select (*i);
|
unique_select (*i);
|
||||||
trackview.session().request_locate (npos);
|
// pos = _region->position() + beats_to_frames ((*i)->note()->time());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* use the last one */
|
||||||
|
|
||||||
|
unique_select (*(_events.rbegin()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ class MidiRegionView : public RegionView
|
||||||
|
|
||||||
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
|
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
|
||||||
void unique_select(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 note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add);
|
||||||
void delete_selection();
|
void delete_selection();
|
||||||
size_t selection_size() { return _selection.size(); }
|
size_t selection_size() { return _selection.size(); }
|
||||||
|
|
@ -265,7 +265,7 @@ class MidiRegionView : public RegionView
|
||||||
void goto_next_note ();
|
void goto_next_note ();
|
||||||
void change_velocities (int8_t velocity, bool relative);
|
void change_velocities (int8_t velocity, bool relative);
|
||||||
void transpose (bool up, bool fine);
|
void transpose (bool up, bool fine);
|
||||||
void nudge_notes (ARDOUR::MidiModel::TimeType delta);
|
void nudge_notes (bool forward);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Allows derived types to specify their visibility requirements
|
/** Allows derived types to specify their visibility requirements
|
||||||
|
|
|
||||||
|
|
@ -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 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 foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
|
||||||
virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 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
|
#ifdef WITH_CMT
|
||||||
virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
|
virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue