Commit 4484d7a5 authored by Max Kellermann's avatar Max Kellermann

output/jack: implement Interrupt()

parent b80a135c
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
......
......@@ -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"
......@@ -80,6 +81,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.
*/
mutable Mutex mutex;
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment