changeset 212:fe83e6e68683

* Fix crash on document deletion (new session, or application exit) after loading session with alignments
author Chris Cannam
date Sun, 24 Oct 2010 22:09:42 +0200
parents 84422236db20
children eed79c69be61
files audioio/AudioCallbackPlaySource.cpp framework/Document.cpp framework/SVFileReader.cpp
diffstat 3 files changed, 50 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp	Sun Oct 24 17:39:00 2010 +0200
+++ b/audioio/AudioCallbackPlaySource.cpp	Sun Oct 24 22:09:42 2010 +0200
@@ -106,7 +106,10 @@
     m_exiting = true;
 
     if (m_fillThread) {
-	m_condition.wakeAll();
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource dtor: awakening thread" << std::endl;
+#endif
+        m_condition.wakeAll();
 	m_fillThread->wait();
 	delete m_fillThread;
     }
@@ -252,6 +255,10 @@
     connect(model, SIGNAL(modelChanged(size_t, size_t)),
             this, SLOT(modelChanged(size_t, size_t)));
 
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource::addModel: awakening thread" << std::endl;
+#endif
+
     m_condition.wakeAll();
 }
 
@@ -304,10 +311,10 @@
     }
     m_lastModelEndFrame = lastEnd;
 
+    m_audioGenerator->removeModel(model);
+
     m_mutex.unlock();
 
-    m_audioGenerator->removeModel(model);
-
     clearRingBuffers();
 }
 
@@ -441,6 +448,11 @@
     m_lastRetrievalTimestamp = 0;
     m_lastCurrentFrame = 0;
     m_playing = true;
+
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource::play: awakening thread" << std::endl;
+#endif
+
     m_condition.wakeAll();
     if (changed) {
         emit playStatusChanged(m_playing);
@@ -453,8 +465,16 @@
 void
 AudioCallbackPlaySource::stop()
 {
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cerr << "AudioCallbackPlaySource::stop()" << std::endl;
+#endif
     bool changed = m_playing;
     m_playing = false;
+
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource::stop: awakening thread" << std::endl;
+#endif
+
     m_condition.wakeAll();
     m_lastRetrievalTimestamp = 0;
     if (changed) {
@@ -1058,6 +1078,10 @@
 	return 0;
     }
 
+#ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
+    std::cerr << "AudioCallbackPlaySource::getSourceSamples: Playing" << std::endl;
+#endif
+
     // Ensure that all buffers have at least the amount of data we
     // need -- else reduce the size of our requests correspondingly
 
@@ -1151,6 +1175,10 @@
 
         applyAuditioningEffect(count, buffer);
 
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource::getSamples: awakening thread" << std::endl;
+#endif
+
         m_condition.wakeAll();
 
 	return got;
@@ -1239,6 +1267,10 @@
 
     applyAuditioningEffect(count, buffer);
 
+#ifdef DEBUG_AUDIO_PLAY_SOURCE
+    std::cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << std::endl;
+#endif
+
     m_condition.wakeAll();
 
     return count;
--- a/framework/Document.cpp	Sun Oct 24 17:39:00 2010 +0200
+++ b/framework/Document.cpp	Sun Oct 24 22:09:42 2010 +0200
@@ -31,6 +31,7 @@
 #include <QTextStream>
 #include <QSettings>
 #include <iostream>
+#include <typeinfo>
 
 // For alignment:
 #include "data/model/AggregateWaveModel.h"
@@ -630,7 +631,8 @@
 
     if (m_layers.find(layer) == m_layers.end()) {
 	std::cerr << "Document::deleteLayer: Layer "
-		  << layer << " does not exist, or has already been deleted "
+                  << layer << " (" << typeid(layer).name() <<
+                  ") does not exist, or has already been deleted "
 		  << "(this may not be as serious as it sounds)" << std::endl;
 	return;
     }
--- a/framework/SVFileReader.cpp	Sun Oct 24 17:39:00 2010 +0200
+++ b/framework/SVFileReader.cpp	Sun Oct 24 22:09:42 2010 +0200
@@ -412,8 +412,18 @@
     
     for (std::set<Model *>::iterator i = unaddedModels.begin();
          i != unaddedModels.end(); ++i) {
-        m_document->addImportedModel(*i);
-        m_addedModels.insert(*i);
+        Model *model = *i;
+        // don't want to add these models, because their lifespans
+        // are entirely dictated by the models that "own" them even
+        // though they were read independently from the .sv file.
+        // (pity we don't have a nicer way)
+        if (!dynamic_cast<PathModel *>(model) &&
+            !dynamic_cast<AlignmentModel *>(model)) {
+            m_document->addImportedModel(model);
+        }
+        // but we add all models here, so they don't get deleted
+        // when the file loader is destroyed
+        m_addedModels.insert(model);
     }
 }