From 3193ee9701637b6a4e270947a20007b4249b71c6 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 21 Mar 2017 10:56:19 -0500 Subject: [PATCH] Wrapping AudioDeviceManager in singleton wrapper, to ensure only a single instance can be created. This solves lots of weird issues with the preview dialog. --- include/Qt/AudioPlaybackThread.h | 20 +++++++++++++++++++- src/Qt/AudioPlaybackThread.cpp | 31 +++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/include/Qt/AudioPlaybackThread.h b/include/Qt/AudioPlaybackThread.h index 37718b58..ad6bcc2c 100644 --- a/include/Qt/AudioPlaybackThread.h +++ b/include/Qt/AudioPlaybackThread.h @@ -51,12 +51,30 @@ namespace openshot } }; + /** + * @brief Singleton wrapper for AudioDeviceManager (to prevent multiple instances). + */ + class AudioDeviceManagerSingleton { + private: + /// Default constructor (Don't allow user to create an instance of this singleton) + AudioDeviceManagerSingleton(){}; + + /// Private variable to keep track of singleton instance + static AudioDeviceManagerSingleton * m_pInstance; + + public: + /// Create or get an instance of this singleton (invoke the class with this method) + static AudioDeviceManagerSingleton * Instance(); + + /// Public device manager property + AudioDeviceManager audioDeviceManager; + }; + /** * @brief The audio playback thread */ class AudioPlaybackThread : Thread { - AudioDeviceManager audioDeviceManager; AudioSourcePlayer player; AudioTransportSource transport; MixerAudioSource mixer; diff --git a/src/Qt/AudioPlaybackThread.cpp b/src/Qt/AudioPlaybackThread.cpp index 29b3bf0e..e3054efe 100644 --- a/src/Qt/AudioPlaybackThread.cpp +++ b/src/Qt/AudioPlaybackThread.cpp @@ -30,10 +30,24 @@ namespace openshot { + + // Global reference to device manager + AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::m_pInstance = NULL; + + // Create or Get an instance of the device manager singleton + AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::Instance() + { + if (!m_pInstance) { + // Create the actual instance of device manager only once + m_pInstance = new AudioDeviceManagerSingleton; + } + + return m_pInstance; + } + // Construtor AudioPlaybackThread::AudioPlaybackThread() : Thread("audio-playback") - , audioDeviceManager() , player() , transport() , mixer() @@ -112,17 +126,14 @@ namespace openshot // Start new audio device // Init audio device - // TODO: We should never create more than a single instance of audioDeviceManager, so this needs to be - // refactored in some way, so multiple audio playback threads will always use the same manager. Perhaps - // a singleton wrapper around it. - audioDeviceManager.initialise ( + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.initialise ( 0, /* number of input channels */ numChannels, /* number of output channels */ 0, /* no XML settings.. */ true /* select default device on failure */); // Add callback - audioDeviceManager.addAudioCallback(&player); + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.addAudioCallback(&player); // Create TimeSliceThread for audio buffering time_thread.startThread(); @@ -156,10 +167,10 @@ namespace openshot transport.setSource(NULL); player.setSource(NULL); - audioDeviceManager.removeAudioCallback(&player); - audioDeviceManager.closeAudioDevice(); - audioDeviceManager.removeAllChangeListeners(); - audioDeviceManager.dispatchPendingMessages(); + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.removeAudioCallback(&player); + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.closeAudioDevice(); + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.removeAllChangeListeners(); + AudioDeviceManagerSingleton::Instance()->audioDeviceManager.dispatchPendingMessages(); // Remove source delete source;