mirror of https://github.com/mgba-emu/mgba.git
Qt: Fix hang if audio sync is enabled and audio fails to initialize
This commit is contained in:
parent
a763b764ed
commit
899a74d1c0
1
CHANGES
1
CHANGES
|
@ -2,6 +2,7 @@
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- VFS: Fix reading 7z archives without rewinding first
|
- VFS: Fix reading 7z archives without rewinding first
|
||||||
- Qt: Fix sending gameStopped twice
|
- Qt: Fix sending gameStopped twice
|
||||||
|
- Qt: Fix hang if audio sync is enabled and audio fails to initialize
|
||||||
Misc:
|
Misc:
|
||||||
- GBA: Slightly optimize GBAProcessEvents
|
- GBA: Slightly optimize GBAProcessEvents
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
virtual unsigned sampleRate() const = 0;
|
virtual unsigned sampleRate() const = 0;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void start() = 0;
|
virtual bool start() = 0;
|
||||||
virtual void pause() = 0;
|
virtual void pause() = 0;
|
||||||
|
|
||||||
virtual void setBufferSamples(int samples) = 0;
|
virtual void setBufferSamples(int samples) = 0;
|
||||||
|
|
|
@ -34,10 +34,10 @@ void AudioProcessorQt::setInput(GBAThread* input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessorQt::start() {
|
bool AudioProcessorQt::start() {
|
||||||
if (!input()) {
|
if (!input()) {
|
||||||
LOG(WARN) << tr("Can't start an audio processor without input");
|
LOG(WARN) << tr("Can't start an audio processor without input");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_device) {
|
if (!m_device) {
|
||||||
|
@ -62,6 +62,7 @@ void AudioProcessorQt::start() {
|
||||||
m_audioOutput->setBufferSize(input()->audioBuffers * 4);
|
m_audioOutput->setBufferSize(input()->audioBuffers * 4);
|
||||||
|
|
||||||
m_audioOutput->start(m_device);
|
m_audioOutput->start(m_device);
|
||||||
|
return m_audioOutput->state() == QAudio::ActiveState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessorQt::pause() {
|
void AudioProcessorQt::pause() {
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
virtual unsigned sampleRate() const override;
|
virtual unsigned sampleRate() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void start() override;
|
virtual bool start() override;
|
||||||
virtual void pause() override;
|
virtual void pause() override;
|
||||||
|
|
||||||
virtual void setBufferSamples(int samples) override;
|
virtual void setBufferSamples(int samples) override;
|
||||||
|
|
|
@ -23,19 +23,20 @@ AudioProcessorSDL::~AudioProcessorSDL() {
|
||||||
GBASDLDeinitAudio(&m_audio);
|
GBASDLDeinitAudio(&m_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessorSDL::start() {
|
bool AudioProcessorSDL::start() {
|
||||||
if (!input()) {
|
if (!input()) {
|
||||||
LOG(WARN) << tr("Can't start an audio processor without input");
|
LOG(WARN) << tr("Can't start an audio processor without input");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_audio.thread) {
|
if (m_audio.thread) {
|
||||||
GBASDLResumeAudio(&m_audio);
|
GBASDLResumeAudio(&m_audio);
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (!m_audio.samples) {
|
if (!m_audio.samples) {
|
||||||
m_audio.samples = input()->audioBuffers;
|
m_audio.samples = input()->audioBuffers;
|
||||||
}
|
}
|
||||||
GBASDLInitAudio(&m_audio, input());
|
return GBASDLInitAudio(&m_audio, input());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
virtual unsigned sampleRate() const override;
|
virtual unsigned sampleRate() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void start() override;
|
virtual bool start() override;
|
||||||
virtual void pause() override;
|
virtual void pause() override;
|
||||||
|
|
||||||
virtual void setBufferSamples(int samples) override;
|
virtual void setBufferSamples(int samples) override;
|
||||||
|
|
|
@ -204,9 +204,7 @@ GameController::GameController(QObject* parent)
|
||||||
m_audioThread->setObjectName("Audio Thread");
|
m_audioThread->setObjectName("Audio Thread");
|
||||||
m_audioThread->start(QThread::TimeCriticalPriority);
|
m_audioThread->start(QThread::TimeCriticalPriority);
|
||||||
m_audioProcessor->moveToThread(m_audioThread);
|
m_audioProcessor->moveToThread(m_audioThread);
|
||||||
connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start()));
|
|
||||||
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
|
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
|
||||||
connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start()));
|
|
||||||
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents()));
|
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents()));
|
||||||
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateAutofire()));
|
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateAutofire()));
|
||||||
}
|
}
|
||||||
|
@ -341,6 +339,17 @@ void GameController::openGame(bool biosOnly) {
|
||||||
if (!GBAThreadStart(&m_threadContext)) {
|
if (!GBAThreadStart(&m_threadContext)) {
|
||||||
m_gameOpen = false;
|
m_gameOpen = false;
|
||||||
emit gameFailed();
|
emit gameFailed();
|
||||||
|
} else if (m_audioProcessor) {
|
||||||
|
bool started = false;
|
||||||
|
QMetaObject::invokeMethod(m_audioProcessor, "start", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, started));
|
||||||
|
if (!started) {
|
||||||
|
LOG(ERROR) << tr("Failed to start audio processor");
|
||||||
|
// Don't freeze!
|
||||||
|
m_audioSync = false;
|
||||||
|
m_videoSync = true;
|
||||||
|
m_threadContext.sync.audioWait = false;
|
||||||
|
m_threadContext.sync.videoFrameWait = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,12 +909,19 @@ void GameController::reloadAudioDriver() {
|
||||||
m_audioProcessor->requestSampleRate(sampleRate);
|
m_audioProcessor->requestSampleRate(sampleRate);
|
||||||
}
|
}
|
||||||
m_audioProcessor->moveToThread(m_audioThread);
|
m_audioProcessor->moveToThread(m_audioThread);
|
||||||
connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start()));
|
|
||||||
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
|
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
|
||||||
connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start()));
|
|
||||||
if (isLoaded()) {
|
if (isLoaded()) {
|
||||||
m_audioProcessor->setInput(&m_threadContext);
|
m_audioProcessor->setInput(&m_threadContext);
|
||||||
QMetaObject::invokeMethod(m_audioProcessor, "start");
|
bool started = false;
|
||||||
|
QMetaObject::invokeMethod(m_audioProcessor, "start", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, started));
|
||||||
|
if (!started) {
|
||||||
|
LOG(ERROR) << tr("Failed to start audio processor");
|
||||||
|
// Don't freeze!
|
||||||
|
m_audioSync = false;
|
||||||
|
m_videoSync = true;
|
||||||
|
m_threadContext.sync.audioWait = false;
|
||||||
|
m_threadContext.sync.videoFrameWait = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue