You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
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)
This commit is contained in:
@@ -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<Frame> 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<Frame> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ namespace openshot
|
||||
/// Close audio device
|
||||
void CloseAudioDevice();
|
||||
|
||||
/// Get Error (if any)
|
||||
string GetError();
|
||||
|
||||
/// Play the video
|
||||
void Play();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user