From fa19e1a9d0b97233e130d301d906b3867a585950 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 8 Jun 2012 13:21:05 +0000 Subject: [PATCH] When sounding notes on selection / note movements, play the note for as long as the mouse button is held down (#4574). git-svn-id: svn://localhost/ardour2/branches/3.0@12606 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-note.cc | 10 ++++-- gtk2_ardour/midi_region_view.cc | 58 +++++++++++++++++++++++++++------ gtk2_ardour/midi_region_view.h | 10 ++++-- gtk2_ardour/note_player.cc | 13 +++++++- gtk2_ardour/note_player.h | 3 +- 5 files changed, 78 insertions(+), 16 deletions(-) diff --git a/gtk2_ardour/canvas-note.cc b/gtk2_ardour/canvas-note.cc index f6497776a5..b98cbab5ff 100644 --- a/gtk2_ardour/canvas-note.cc +++ b/gtk2_ardour/canvas-note.cc @@ -22,11 +22,17 @@ CanvasNote::CanvasNote (MidiRegionView& region, bool CanvasNote::on_event(GdkEvent* ev) { + bool r = true; + if (!CanvasNoteEvent::on_event (ev)) { - return _region.get_time_axis_view().editor().canvas_note_event (ev, this); + r = _region.get_time_axis_view().editor().canvas_note_event (ev, this); } - return true; + if (ev->type == GDK_BUTTON_RELEASE) { + _region.note_button_release (); + } + + return r; } void diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 25ef2dfc33..70f080720d 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -110,6 +110,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & , _last_event_y (0) , pre_enter_cursor (0) , pre_press_cursor (0) + , _note_player (0) { _note_group->raise_to_top(); PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys)); @@ -150,6 +151,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & , _last_event_y (0) , pre_enter_cursor (0) , pre_press_cursor (0) + , _note_player (0) { _note_group->raise_to_top(); PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys)); @@ -198,6 +200,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other) , _last_event_y (0) , pre_enter_cursor (0) , pre_press_cursor (0) + , _note_player (0) { Gdk::Color c; int r,g,b,a; @@ -232,6 +235,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptrtype) { case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: @@ -357,7 +363,10 @@ MidiRegionView::canvas_event(GdkEvent* ev) return button_press (&ev->button); case GDK_BUTTON_RELEASE: - return button_release (&ev->button); + r = button_release (&ev->button); + delete _note_player; + _note_player = 0; + return r; case GDK_ENTER_NOTIFY: return enter_notify (&ev->crossing); @@ -1539,13 +1548,15 @@ MidiRegionView::play_midi_note(boost::shared_ptr note) return; } - NotePlayer* np = new NotePlayer (route_ui->midi_track()); + NotePlayer* np = new NotePlayer (route_ui->midi_track ()); np->add (note); np->play (); + + /* NotePlayer deletes itself */ } void -MidiRegionView::play_midi_chord (vector > notes) +MidiRegionView::start_playing_midi_note(boost::shared_ptr note) { if (_no_sound_notes || !Config->get_sound_midi_notes()) { return; @@ -1557,13 +1568,33 @@ MidiRegionView::play_midi_chord (vector > notes) return; } - NotePlayer* np = new NotePlayer (route_ui->midi_track()); + delete _note_player; + _note_player = new NotePlayer (route_ui->midi_track ()); + _note_player->add (note); + _note_player->on (); +} - for (vector >::iterator n = notes.begin(); n != notes.end(); ++n) { - np->add (*n); +void +MidiRegionView::start_playing_midi_chord (vector > notes) +{ + if (_no_sound_notes || !Config->get_sound_midi_notes()) { + return; } - np->play (); + RouteUI* route_ui = dynamic_cast (&trackview); + + if (!route_ui || !route_ui->midi_track()) { + return; + } + + delete _note_player; + _note_player = new NotePlayer (route_ui->midi_track()); + + for (vector >::iterator n = notes.begin(); n != notes.end(); ++n) { + _note_player->add (*n); + } + + _note_player->on (); } @@ -2338,7 +2369,7 @@ MidiRegionView::add_to_selection (CanvasNoteEvent* ev) if (_selection.insert (ev).second) { ev->set_selected (true); - play_midi_note ((ev)->note()); + start_playing_midi_note ((ev)->note()); } if (add_mrv_selection) { @@ -2379,13 +2410,13 @@ MidiRegionView::move_selection(double dx, double dy, double cumulative_dy) shifted.push_back (moved_note); } - play_midi_chord (shifted); + start_playing_midi_chord (shifted); } else if (!to_play.empty()) { boost::shared_ptr moved_note (new NoteType (*to_play.front())); moved_note->set_note (moved_note->note() + cumulative_dy); - play_midi_note (moved_note); + start_playing_midi_note (moved_note); } } } @@ -3794,3 +3825,10 @@ MidiRegionView::selection_cleared (MidiRegionView* rv) /* Clear our selection in sympathy; but don't signal the fact */ clear_selection (false); } + +void +MidiRegionView::note_button_release () +{ + delete _note_player; + _note_player = 0; +} diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 8ad1214c78..0663e75a7b 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -64,6 +64,7 @@ class AutomationRegionView; class MidiCutBuffer; class MidiListEditor; class EditNoteDialog; +class NotePlayer; class MidiRegionView : public RegionView { @@ -232,6 +233,8 @@ public: MouseState mouse_state() const { return _mouse_state; } + void note_button_release (); + struct NoteResizeData { ArdourCanvas::CanvasNote *canvas_note; ArdourCanvas::SimpleRect *resize_rect; @@ -338,8 +341,9 @@ private: /** Play the NoteOn event of the given note immediately * and schedule the playback of the corresponding NoteOff event. */ - void play_midi_note(boost::shared_ptr note); - void play_midi_chord (std::vector > notes); + void play_midi_note (boost::shared_ptr note); + void start_playing_midi_note (boost::shared_ptr note); + void start_playing_midi_chord (std::vector > notes); void clear_events(); @@ -473,6 +477,8 @@ private: Gdk::Cursor* pre_enter_cursor; Gdk::Cursor* pre_press_cursor; + + NotePlayer* _note_player; }; diff --git a/gtk2_ardour/note_player.cc b/gtk2_ardour/note_player.cc index b9f480a6be..cd5c058209 100644 --- a/gtk2_ardour/note_player.cc +++ b/gtk2_ardour/note_player.cc @@ -31,6 +31,11 @@ NotePlayer::NotePlayer (boost::shared_ptr mt) { } +NotePlayer::~NotePlayer () +{ + clear (); +} + void NotePlayer::add (boost::shared_ptr note) { @@ -45,11 +50,17 @@ NotePlayer::clear () } void -NotePlayer::play () +NotePlayer::on () { for (Notes::iterator n = notes.begin(); n != notes.end(); ++n) { track->write_immediate_event ((*n)->on_event().size(), (*n)->on_event().buffer()); } +} + +void +NotePlayer::play () +{ + on (); /* note: if there is more than 1 note, we will silence them all at the same time */ diff --git a/gtk2_ardour/note_player.h b/gtk2_ardour/note_player.h index c39d352dd6..4a1df8c319 100644 --- a/gtk2_ardour/note_player.h +++ b/gtk2_ardour/note_player.h @@ -34,10 +34,11 @@ public: typedef Evoral::Note NoteType; NotePlayer (boost::shared_ptr); - ~NotePlayer () {} + ~NotePlayer (); void add (boost::shared_ptr); void play (); + void on (); void off (); void clear ();