# HG changeset patch # User Chris Cannam # Date 1196443869 0 # Node ID 716e9d2f91c75040c86bd3170fbda2addfdf3d2d # Parent cedeab01d4c81a3ae793d26807e96281816b7343 * 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 diff -r cedeab01d4c8 -r 716e9d2f91c7 audioio/AudioCallbackPlayTarget.h --- 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; } diff -r cedeab01d4c8 -r 716e9d2f91c7 audioio/AudioJACKTarget.cpp --- 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::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; } diff -r cedeab01d4c8 -r 716e9d2f91c7 audioio/AudioJACKTarget.h --- 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 */ diff -r cedeab01d4c8 -r 716e9d2f91c7 audioio/AudioPortAudioTarget.cpp --- 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; diff -r cedeab01d4c8 -r 716e9d2f91c7 audioio/AudioPortAudioTarget.h --- 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 */ diff -r cedeab01d4c8 -r 716e9d2f91c7 framework/Document.cpp --- 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(replacementModel); if (rm) { diff -r cedeab01d4c8 -r 716e9d2f91c7 framework/MainWindowBase.cpp --- 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;