changeset 571:2cf4978eb724

Fix failure of "Form Note from Selection" to work correctly when an existing note spanned one end of the selection but did not reach the other. Also update subrepos to fix a deadlock
author Chris Cannam
date Thu, 20 Jun 2019 11:10:59 +0100
parents c6c8c1645ab6
children 3f0b44418a19 3c884bad3d44
files repoint-lock.json src/MainWindow.cpp
diffstat 2 files changed, 31 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/repoint-lock.json	Wed Jun 19 13:33:33 2019 +0100
+++ b/repoint-lock.json	Thu Jun 20 11:10:59 2019 +0100
@@ -4,7 +4,7 @@
       "pin": "62987b6d6a3b"
     },
     "svcore": {
-      "pin": "78fe29adfd16"
+      "pin": "8efce64dd85e"
     },
     "svgui": {
       "pin": "de41a11cabc2"
--- a/src/MainWindow.cpp	Wed Jun 19 13:33:33 2019 +0100
+++ b/src/MainWindow.cpp	Thu Jun 20 11:10:59 2019 +0100
@@ -2652,11 +2652,10 @@
 void
 MainWindow::formNoteFromSelection()
 {
+    Pane *pane = m_analyser->getPane();
     Layer *layer0 = m_analyser->getLayer(Analyser::Notes);
     NoteModel *model = qobject_cast<NoteModel *>(layer0->getModel());
-
-    FlexiNoteLayer *layer =
-        qobject_cast<FlexiNoteLayer *>(m_analyser->getLayer(Analyser::Notes));
+    FlexiNoteLayer *layer = qobject_cast<FlexiNoteLayer *>(layer0);
     if (!layer) return;
 
     MultiSelection::SelectionList selections = m_viewManager->getSelections();
@@ -2665,21 +2664,37 @@
     
         CommandHistory::getInstance()->startCompoundOperation
             (tr("Form Note from Selection"), true);
+
         for (MultiSelection::SelectionList::iterator k = selections.begin();
              k != selections.end(); ++k) {
-            //!!! This fails in the case where an existing note spans
-            //!!! one end of the selection but does not reach the
-            //!!! other end - it doesn't get extended
-            if (!model->getEventsSpanning(k->getStartFrame(),
-                                          k->getEndFrame() - k->getStartFrame()).empty()) {
-                layer->splitNotesAt(m_analyser->getPane(), k->getStartFrame());
-                layer->splitNotesAt(m_analyser->getPane(), k->getEndFrame());
-                layer->mergeNotes(m_analyser->getPane(), *k, false);
-            } else {
-                layer->addNoteOn(k->getStartFrame(), 100, 100);
-                layer->addNoteOff(k->getEndFrame(), 100);
-                layer->mergeNotes(m_analyser->getPane(), *k, false); // only so the note adapts in case of existing pitch track
+
+            // Chop existing events at start and end frames; remember
+            // the first starting pitch, to use as default for new
+            // note; delete existing events; create new note; ask
+            // layer to merge, just in order to adapt the note to the
+            // existing pitch track if possible. This way we should
+            // handle all the possible cases of existing notes that
+            // may or may not overlap the start or end times
+            
+            sv_frame_t start = k->getStartFrame();
+            sv_frame_t end = k->getEndFrame();
+
+            EventVector existing =
+                model->getEventsStartingWithin(start, end - start);
+
+            int defaultPitch = 100;
+            if (!existing.empty()) {
+                defaultPitch = int(roundf(existing.begin()->getValue()));
             }
+            
+            layer->splitNotesAt(pane, start);
+            layer->splitNotesAt(pane, end);
+            layer->deleteSelection(*k);
+            
+            layer->addNoteOn(start, defaultPitch, 100);
+            layer->addNoteOff(end, defaultPitch);
+            
+            layer->mergeNotes(pane, *k, false);
         }
 
         CommandHistory::getInstance()->endCompoundOperation();