changeset 70:716e9d2f91c7

* Skip ID3 block when reading MP3 files (so long as ID3 support is included) * Show progress when retrieving audio file from playlist * Avoid -- but do not actually fix -- segmentation fault on exit. I am totally stumped at the moment about why both the PA and JACK audio targets should crash when properly shut down. For the moment, we just don't shut them down... * Fix incorrect behaviour (introduced on Friday as part of a different fix) when replacing main model in situation where no current main model exists
author Chris Cannam
date Fri, 30 Nov 2007 17:31:09 +0000
parents cedeab01d4c8
children 4aa40182321f
files audioio/AudioCallbackPlayTarget.h audioio/AudioJACKTarget.cpp audioio/AudioJACKTarget.h audioio/AudioPortAudioTarget.cpp audioio/AudioPortAudioTarget.h framework/Document.cpp framework/MainWindowBase.cpp
diffstat 7 files changed, 77 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/audioio/AudioCallbackPlayTarget.h	Thu Nov 29 17:10:53 2007 +0000
+++ b/audioio/AudioCallbackPlayTarget.h	Fri Nov 30 17:31:09 2007 +0000
@@ -30,6 +30,8 @@
 
     virtual bool isOK() const = 0;
 
+    virtual void shutdown() = 0;
+
     float getOutputGain() const {
 	return m_outputGain;
     }
--- a/audioio/AudioJACKTarget.cpp	Thu Nov 29 17:10:53 2007 +0000
+++ b/audioio/AudioJACKTarget.cpp	Fri Nov 30 17:31:09 2007 +0000
@@ -69,9 +69,9 @@
                                                jack_options_t options,
                                                jack_status_t *status, ...)
 {
-    typedef jack_client_t (*func)(const char *client_name,
-                                  jack_options_t options,
-                                  jack_status_t *status, ...);
+    typedef jack_client_t *(*func)(const char *client_name,
+                                   jack_options_t options,
+                                   jack_status_t *status, ...);
     void *s = symbol("jack_client_open");
     if (!s) return 0;
     func f = (func)s;
@@ -211,7 +211,8 @@
     AudioCallbackPlayTarget(source),
     m_client(0),
     m_bufferSize(0),
-    m_sampleRate(0)
+    m_sampleRate(0),
+    m_done(false)
 {
     JackOptions options = JackNullOption;
 #ifdef HAVE_PORTAUDIO
@@ -247,13 +248,37 @@
 AudioJACKTarget::~AudioJACKTarget()
 {
     std::cerr << "AudioJACKTarget::~AudioJACKTarget()" << std::endl;
+
+    shutdown();
+
     if (m_client) {
+
+        while (m_outputs.size() > 0) {
+            std::vector<jack_port_t *>::iterator itr = m_outputs.end();
+            --itr;
+            jack_port_t *port = *itr;
+            std::cerr << "unregister " << m_outputs.size() << std::endl;
+            if (port) jack_port_unregister(m_client, port);
+            m_outputs.erase(itr);
+        }
+        std::cerr << "Deactivating... ";
 	jack_deactivate(m_client);
+        std::cerr << "done\nClosing... ";
 	jack_client_close(m_client);
+        std::cerr << "done" << std::endl;
     }
+
+    m_client = 0;
+
     std::cerr << "AudioJACKTarget::~AudioJACKTarget() done" << std::endl;
 }
 
+void
+AudioJACKTarget::shutdown()
+{
+    m_done = true;
+}
+
 bool
 AudioJACKTarget::isOK() const
 {
@@ -342,6 +367,8 @@
 int
 AudioJACKTarget::process(jack_nframes_t nframes)
 {
+    if (m_done) return 0;
+
     if (!m_mutex.tryLock()) {
 	return 0;
     }
--- a/audioio/AudioJACKTarget.h	Thu Nov 29 17:10:53 2007 +0000
+++ b/audioio/AudioJACKTarget.h	Fri Nov 30 17:31:09 2007 +0000
@@ -35,6 +35,8 @@
     AudioJACKTarget(AudioCallbackPlaySource *source);
     virtual ~AudioJACKTarget();
 
+    virtual void shutdown();
+
     virtual bool isOK() const;
 
 public slots:
@@ -52,6 +54,7 @@
     jack_nframes_t              m_bufferSize;
     jack_nframes_t              m_sampleRate;
     QMutex                      m_mutex;
+    bool                        m_done;
 };
 
 #endif /* HAVE_JACK */
--- a/audioio/AudioPortAudioTarget.cpp	Thu Nov 29 17:10:53 2007 +0000
+++ b/audioio/AudioPortAudioTarget.cpp	Fri Nov 30 17:31:09 2007 +0000
@@ -29,7 +29,8 @@
     m_stream(0),
     m_bufferSize(0),
     m_sampleRate(0),
-    m_latency(0)
+    m_latency(0),
+    m_done(false)
 {
     PaError err;
 
@@ -105,17 +106,37 @@
 
 AudioPortAudioTarget::~AudioPortAudioTarget()
 {
+    std::cerr << "AudioPortAudioTarget::~AudioPortAudioTarget()" << std::endl;
+
+    shutdown();
+
     if (m_stream) {
+
+        std::cerr << "closing stream" << std::endl;
+
 	PaError err;
 	err = Pa_CloseStream(m_stream);
 	if (err != paNoError) {
 	    std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream: " << Pa_GetErrorText(err) << std::endl;
 	}
+
+        std::cerr << "terminating" << std::endl;
+
 	err = Pa_Terminate();
         if (err != paNoError) {
             std::cerr << "ERROR: AudioPortAudioTarget: Failed to terminate PortAudio: " << Pa_GetErrorText(err) << std::endl;
 	}   
     }
+
+    m_stream = 0;
+
+    std::cerr << "AudioPortAudioTarget::~AudioPortAudioTarget() done" << std::endl;
+}
+
+void 
+AudioPortAudioTarget::shutdown()
+{
+    m_done = true;
 }
 
 bool
@@ -169,7 +190,7 @@
     std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl;
 #endif
 
-    if (!m_source) return 0;
+    if (!m_source || m_done) return 0;
 
     float *output = (float *)outputBuffer;
 
--- a/audioio/AudioPortAudioTarget.h	Thu Nov 29 17:10:53 2007 +0000
+++ b/audioio/AudioPortAudioTarget.h	Fri Nov 30 17:31:09 2007 +0000
@@ -37,6 +37,8 @@
     AudioPortAudioTarget(AudioCallbackPlaySource *source);
     virtual ~AudioPortAudioTarget();
 
+    virtual void shutdown();
+
     virtual bool isOK() const;
 
 public slots:
@@ -70,6 +72,7 @@
     int m_bufferSize;
     int m_sampleRate;
     int m_latency;
+    bool m_done;
 };
 
 #endif /* HAVE_PORTAUDIO */
--- a/framework/Document.cpp	Thu Nov 29 17:10:53 2007 +0000
+++ b/framework/Document.cpp	Fri Nov 30 17:31:09 2007 +0000
@@ -259,8 +259,8 @@
     // using one of these.  Carry out this replacement before we
     // delete any of the models.
 
-    std::cerr << "Document::setMainModel: Have "
-              << m_layers.size() << " layers" << std::endl;
+//    std::cerr << "Document::setMainModel: Have "
+//              << m_layers.size() << " layers" << std::endl;
 
     for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
 
@@ -271,13 +271,13 @@
 //                  << (model ? model->objectName().toStdString() : "(null)") << " in layer "
 //                  << layer->objectName().toStdString() << std::endl;
 
-	if (model && (model == oldMainModel)) {
+	if (model == oldMainModel) {
 //            std::cerr << "... it uses the old main model, replacing" << std::endl;
 	    LayerFactory::getInstance()->setModel(layer, m_mainModel);
 	    continue;
 	}
 
-	if (m_models.find(model) == m_models.end()) {
+	if (model && (m_models.find(model) == m_models.end())) {
 	    std::cerr << "WARNING: Document::setMainModel: Unknown model "
 		      << model << " in layer " << layer << std::endl;
 	    // get rid of this hideous degenerate
@@ -285,7 +285,8 @@
 	    continue;
 	}
 	    
-	if (m_models[model].source && (m_models[model].source == oldMainModel)) {
+	if (m_models[model].source &&
+            (m_models[model].source == oldMainModel)) {
 
 //            std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl;
 
@@ -311,12 +312,12 @@
                 }
 		obsoleteLayers.push_back(layer);
 	    } else {
-                std::cerr << "Replacing model " << model << " (type "
-                          << typeid(*model).name() << ") with model "
-                          << replacementModel << " (type "
-                          << typeid(*replacementModel).name() << ") in layer "
-                          << layer << " (name " << layer->objectName().toStdString() << ")"
-                          << std::endl;
+//                std::cerr << "Replacing model " << model << " (type "
+//                          << typeid(*model).name() << ") with model "
+//                          << replacementModel << " (type "
+//                          << typeid(*replacementModel).name() << ") in layer "
+//                          << layer << " (name " << layer->objectName().toStdString() << ")"
+//                          << std::endl;
                 RangeSummarisableTimeValueModel *rm =
                     dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel);
                 if (rm) {
--- a/framework/MainWindowBase.cpp	Thu Nov 29 17:10:53 2007 +0000
+++ b/framework/MainWindowBase.cpp	Fri Nov 30 17:31:09 2007 +0000
@@ -201,7 +201,8 @@
 
 MainWindowBase::~MainWindowBase()
 {
-    delete m_playTarget;
+    if (m_playTarget) m_playTarget->shutdown();
+//    delete m_playTarget;
     delete m_playSource;
     delete m_viewManager;
     delete m_oscQueue;
@@ -1007,7 +1008,7 @@
     for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
          i != playlist.end(); ++i) {
 
-        FileOpenStatus status = openAudio(*i, mode);
+        FileOpenStatus status = openAudio(FileSource(*i, true), mode);
 
         if (status == FileOpenCancelled) {
             return FileOpenCancelled;