+NoteBase*
+MidiRegionView::copy_selection ()
+{
+ NoteBase* note;
+ _copy_drag_events.clear ();
+
+ if (_selection.empty()) {
+ return 0;
+ }
+
+ for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
+ boost::shared_ptr<NoteType> g (new NoteType (*((*i)->note())));
+ if (midi_view()->note_mode() == Sustained) {
+ Note* n = new Note (*this, _note_group, g);
+ update_sustained (n, false);
+ note = n;
+ } else {
+ Hit* h = new Hit (*this, _note_group, 10, g);
+ update_hit (h, false);
+ note = h;
+ }
+
+ _copy_drag_events.push_back (note);
+ }
+
+ return _copy_drag_events.front ();
+}
+
+void
+MidiRegionView::move_copies (double dx, double dy, double cumulative_dy)
+{
+ typedef vector<boost::shared_ptr<NoteType> > PossibleChord;
+ PossibleChord to_play;
+ Evoral::Beats earliest = Evoral::MaxBeats;
+
+ for (CopyDragEvents::iterator i = _copy_drag_events.begin(); i != _copy_drag_events.end(); ++i) {
+ if ((*i)->note()->time() < earliest) {
+ earliest = (*i)->note()->time();
+ }
+ }
+
+ for (CopyDragEvents::iterator i = _copy_drag_events.begin(); i != _copy_drag_events.end(); ++i) {
+ if ((*i)->note()->time() == earliest) {
+ to_play.push_back ((*i)->note());
+ }
+ (*i)->move_event(dx, dy);
+ }
+
+ if (dy && !_copy_drag_events.empty() && !_no_sound_notes && UIConfiguration::instance().get_sound_midi_notes()) {
+
+ if (to_play.size() > 1) {
+
+ PossibleChord shifted;
+
+ for (PossibleChord::iterator n = to_play.begin(); n != to_play.end(); ++n) {
+ boost::shared_ptr<NoteType> moved_note (new NoteType (**n));
+ moved_note->set_note (moved_note->note() + cumulative_dy);
+ shifted.push_back (moved_note);
+ }
+
+ start_playing_midi_chord (shifted);
+
+ } else if (!to_play.empty()) {
+
+ boost::shared_ptr<NoteType> moved_note (new NoteType (*to_play.front()));
+ moved_note->set_note (moved_note->note() + cumulative_dy);
+ start_playing_midi_note (moved_note);
+ }
+ }
+}
+