From 9dbb063dedd3a759f11e9abd14ab4f89ffddfc40 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Thu, 4 Apr 2019 00:55:47 -0500 Subject: [PATCH] Persist any error returned by JUCE during initialise() method, such as sample rate issues on Windows (when playback and recording sample rates do not match, which breaks WASAPI) --- include/Qt/AudioPlaybackThread.h | 82 +++++++++++++++++--------------- include/QtPlayer.h | 3 ++ src/Frame.cpp | 8 +++- src/Qt/AudioPlaybackThread.cpp | 9 +++- src/QtPlayer.cpp | 14 ++++-- 5 files changed, 71 insertions(+), 45 deletions(-) diff --git a/include/Qt/AudioPlaybackThread.h b/include/Qt/AudioPlaybackThread.h index 68a2be3b..1d654756 100644 --- a/include/Qt/AudioPlaybackThread.h +++ b/include/Qt/AudioPlaybackThread.h @@ -57,12 +57,15 @@ namespace openshot class AudioDeviceManagerSingleton { private: /// Default constructor (Don't allow user to create an instance of this singleton) - AudioDeviceManagerSingleton(){}; + AudioDeviceManagerSingleton(){ initialise_error=""; }; /// Private variable to keep track of singleton instance static AudioDeviceManagerSingleton * m_pInstance; public: + /// Error found during JUCE initialise method + string initialise_error; + /// Create or get an instance of this singleton (invoke the class with this method) static AudioDeviceManagerSingleton * Instance(int numChannels); @@ -78,52 +81,55 @@ namespace openshot */ class AudioPlaybackThread : Thread { - AudioSourcePlayer player; - AudioTransportSource transport; - MixerAudioSource mixer; - AudioReaderSource *source; - double sampleRate; - int numChannels; - WaitableEvent play; - WaitableEvent played; - int buffer_size; - bool is_playing; - SafeTimeSliceThread time_thread; - - /// Constructor - AudioPlaybackThread(); - /// Destructor - ~AudioPlaybackThread(); + AudioSourcePlayer player; + AudioTransportSource transport; + MixerAudioSource mixer; + AudioReaderSource *source; + double sampleRate; + int numChannels; + WaitableEvent play; + WaitableEvent played; + int buffer_size; + bool is_playing; + SafeTimeSliceThread time_thread; - /// Set the current thread's reader - void Reader(ReaderBase *reader); + /// Constructor + AudioPlaybackThread(); + /// Destructor + ~AudioPlaybackThread(); - /// Get the current frame object (which is filling the buffer) - std::shared_ptr getFrame(); + /// Set the current thread's reader + void Reader(ReaderBase *reader); - /// Get the current frame number being played - int64_t getCurrentFramePosition(); + /// Get the current frame object (which is filling the buffer) + std::shared_ptr getFrame(); - /// Play the audio - void Play(); + /// Get the current frame number being played + int64_t getCurrentFramePosition(); - /// Seek the audio thread - void Seek(int64_t new_position); + /// Play the audio + void Play(); - /// Stop the audio playback - void Stop(); + /// Seek the audio thread + void Seek(int64_t new_position); - /// Start thread - void run(); - - /// Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...) - void setSpeed(int new_speed) { if (source) source->setSpeed(new_speed); } + /// Stop the audio playback + void Stop(); - /// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...) - int getSpeed() const { if (source) return source->getSpeed(); else return 1; } + /// Start thread + void run(); - friend class PlayerPrivate; - friend class QtPlayer; + /// Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...) + void setSpeed(int new_speed) { if (source) source->setSpeed(new_speed); } + + /// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...) + int getSpeed() const { if (source) return source->getSpeed(); else return 1; } + + /// Get Audio Error (if any) + string getError() { return AudioDeviceManagerSingleton::Instance(numChannels)->initialise_error; } + + friend class PlayerPrivate; + friend class QtPlayer; }; } diff --git a/include/QtPlayer.h b/include/QtPlayer.h index 354bbfc8..a1a7ee0c 100644 --- a/include/QtPlayer.h +++ b/include/QtPlayer.h @@ -59,6 +59,9 @@ namespace openshot /// Close audio device void CloseAudioDevice(); + /// Get Error (if any) + string GetError(); + /// Play the video void Play(); diff --git a/src/Frame.cpp b/src/Frame.cpp index a00fc232..24b653a9 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -953,11 +953,15 @@ void Frame::Play() return; AudioDeviceManager deviceManager; - deviceManager.initialise (0, /* number of input channels */ + String error = deviceManager.initialise (0, /* number of input channels */ 2, /* number of output channels */ 0, /* no XML settings.. */ true /* select default device on failure */); - //deviceManager.playTestSound(); + + // Output error (if any) + if (error.isNotEmpty()) { + cout << "Error on initialise(): " << error.toStdString() << endl; + } AudioSourcePlayer audioSourcePlayer; deviceManager.addAudioCallback (&audioSourcePlayer); diff --git a/src/Qt/AudioPlaybackThread.cpp b/src/Qt/AudioPlaybackThread.cpp index fac2e3fc..c64bd688 100644 --- a/src/Qt/AudioPlaybackThread.cpp +++ b/src/Qt/AudioPlaybackThread.cpp @@ -42,11 +42,18 @@ namespace openshot m_pInstance = new AudioDeviceManagerSingleton; // Initialize audio device only 1 time - m_pInstance->audioDeviceManager.initialise ( + String error = m_pInstance->audioDeviceManager.initialise ( 0, /* number of input channels */ numChannels, /* number of output channels */ 0, /* no XML settings.. */ true /* select default device on failure */); + + // Persist any errors detected + if (error.isNotEmpty()) { + m_pInstance->initialise_error = error.toStdString(); + } else { + m_pInstance->initialise_error = ""; + } } return m_pInstance; diff --git a/src/QtPlayer.cpp b/src/QtPlayer.cpp index 028a9b70..4f53c7ca 100644 --- a/src/QtPlayer.cpp +++ b/src/QtPlayer.cpp @@ -59,12 +59,21 @@ void QtPlayer::CloseAudioDevice() AudioDeviceManagerSingleton::Instance(0)->CloseAudioDevice(); } +// Return any error string during initialization +string QtPlayer::GetError() { + if (reader && threads_started) { + // Get error from audio thread (if any) + return p->audioPlayback->getError(); + } else { + return ""; + } +} + void QtPlayer::SetSource(const std::string &source) { FFmpegReader *ffreader = new FFmpegReader(source); ffreader->DisplayInfo(); - //reader = new FrameMapper(ffreader, ffreader->info.fps, PULLDOWN_NONE, ffreader->info.sample_rate, ffreader->info.channels, ffreader->info.channel_layout); reader = new Timeline(ffreader->info.width, ffreader->info.height, ffreader->info.fps, ffreader->info.sample_rate, ffreader->info.channels, ffreader->info.channel_layout); Clip *c = new Clip(source); @@ -72,9 +81,6 @@ void QtPlayer::SetSource(const std::string &source) tm->AddClip(c); tm->Open(); -// ZmqLogger::Instance()->Path("/home/jonathan/.openshot_qt/libopenshot.log"); -// ZmqLogger::Instance()->Enable(true); - // Set the reader Reader(reader); }