output/jack: implement Interrupt()

This commit is contained in:
Max Kellermann 2020-10-02 10:55:49 +02:00
parent b80a135cf3
commit 4484d7a5c2
2 changed files with 37 additions and 1 deletions

2
NEWS
View File

@ -1,7 +1,7 @@
ver 0.22.1 (not yet released)
* output
- alsa: don't deadlock when the ALSA driver is buggy
- pulse: reduce the delay when stopping or pausing playback
- jack, pulse: reduce the delay when stopping or pausing playback
ver 0.22 (2020/09/23)
* protocol

View File

@ -20,6 +20,7 @@
#include "config.h"
#include "JackOutputPlugin.hxx"
#include "../OutputAPI.hxx"
#include "../Error.hxx"
#include "output/Features.h"
#include "thread/Mutex.hxx"
#include "util/ScopeExit.hxx"
@ -79,6 +80,15 @@ class JackOutput final : public AudioOutput {
*/
std::atomic_bool pause;
/**
* Was Interrupt() called? This will unblock Play(). It will
* be reset by Cancel() and Pause(), as documented by the
* #AudioOutput interface.
*
* Only initialized while the output is open.
*/
bool interrupted;
/**
* Protects #error.
*/
@ -156,6 +166,8 @@ public:
Stop();
}
void Interrupt() noexcept override;
std::chrono::steady_clock::duration Delay() const noexcept override {
return pause && !LockWasShutdown()
? std::chrono::seconds(1)
@ -164,6 +176,7 @@ public:
size_t Play(const void *chunk, size_t size) override;
void Cancel() noexcept override;
bool Pause() override;
private:
@ -613,9 +626,21 @@ JackOutput::Open(AudioFormat &new_audio_format)
new_audio_format.format = SampleFormat::FLOAT;
audio_format = new_audio_format;
interrupted = false;
Start();
}
void
JackOutput::Interrupt() noexcept
{
const std::unique_lock<Mutex> lock(mutex);
/* the "interrupted" flag will prevent Play() from waiting,
and will instead throw AudioOutputInterrupted */
interrupted = true;
}
inline size_t
JackOutput::WriteSamples(const float *src, size_t n_frames)
{
@ -671,6 +696,9 @@ JackOutput::Play(const void *chunk, size_t size)
const std::lock_guard<Mutex> lock(mutex);
if (error)
std::rethrow_exception(error);
if (interrupted)
throw AudioOutputInterrupted{};
}
size_t frames_written =
@ -684,11 +712,19 @@ JackOutput::Play(const void *chunk, size_t size)
}
}
void
JackOutput::Cancel() noexcept
{
const std::unique_lock<Mutex> lock(mutex);
interrupted = false;
}
inline bool
JackOutput::Pause()
{
{
const std::lock_guard<Mutex> lock(mutex);
interrupted = false;
if (error)
std::rethrow_exception(error);
}