summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-10-02 10:55:49 +0200
committerMax Kellermann <max@musicpd.org>2020-10-02 11:00:04 +0200
commit4484d7a5c2faabd6632e9ca6bc88712781cd4fa6 (patch)
tree2c6068e9536226e7b4767093aa88a28cb592758a /src
parentb80a135cf3cab19dfaef2ddc95a72e67d6c55f2a (diff)
output/jack: implement Interrupt()
Diffstat (limited to 'src')
-rw-r--r--src/output/plugins/JackOutputPlugin.cxx36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx
index 8c6da5405..e2f0a63f1 100644
--- a/src/output/plugins/JackOutputPlugin.cxx
+++ b/src/output/plugins/JackOutputPlugin.cxx
@@ -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);
}