output/jack: implement Interrupt()
This commit is contained in:
		
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
ver 0.22.1 (not yet released)
 | 
					ver 0.22.1 (not yet released)
 | 
				
			||||||
* output
 | 
					* output
 | 
				
			||||||
  - alsa: don't deadlock when the ALSA driver is buggy
 | 
					  - 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)
 | 
					ver 0.22 (2020/09/23)
 | 
				
			||||||
* protocol
 | 
					* protocol
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "JackOutputPlugin.hxx"
 | 
					#include "JackOutputPlugin.hxx"
 | 
				
			||||||
#include "../OutputAPI.hxx"
 | 
					#include "../OutputAPI.hxx"
 | 
				
			||||||
 | 
					#include "../Error.hxx"
 | 
				
			||||||
#include "output/Features.h"
 | 
					#include "output/Features.h"
 | 
				
			||||||
#include "thread/Mutex.hxx"
 | 
					#include "thread/Mutex.hxx"
 | 
				
			||||||
#include "util/ScopeExit.hxx"
 | 
					#include "util/ScopeExit.hxx"
 | 
				
			||||||
@@ -79,6 +80,15 @@ class JackOutput final : public AudioOutput {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	std::atomic_bool pause;
 | 
						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.
 | 
						 * Protects #error.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
@@ -156,6 +166,8 @@ public:
 | 
				
			|||||||
		Stop();
 | 
							Stop();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Interrupt() noexcept override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::chrono::steady_clock::duration Delay() const noexcept override {
 | 
						std::chrono::steady_clock::duration Delay() const noexcept override {
 | 
				
			||||||
		return pause && !LockWasShutdown()
 | 
							return pause && !LockWasShutdown()
 | 
				
			||||||
			? std::chrono::seconds(1)
 | 
								? std::chrono::seconds(1)
 | 
				
			||||||
@@ -164,6 +176,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	size_t Play(const void *chunk, size_t size) override;
 | 
						size_t Play(const void *chunk, size_t size) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Cancel() noexcept override;
 | 
				
			||||||
	bool Pause() override;
 | 
						bool Pause() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
@@ -613,9 +626,21 @@ JackOutput::Open(AudioFormat &new_audio_format)
 | 
				
			|||||||
	new_audio_format.format = SampleFormat::FLOAT;
 | 
						new_audio_format.format = SampleFormat::FLOAT;
 | 
				
			||||||
	audio_format = new_audio_format;
 | 
						audio_format = new_audio_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						interrupted = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Start();
 | 
						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
 | 
					inline size_t
 | 
				
			||||||
JackOutput::WriteSamples(const float *src, size_t n_frames)
 | 
					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);
 | 
								const std::lock_guard<Mutex> lock(mutex);
 | 
				
			||||||
			if (error)
 | 
								if (error)
 | 
				
			||||||
				std::rethrow_exception(error);
 | 
									std::rethrow_exception(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (interrupted)
 | 
				
			||||||
 | 
									throw AudioOutputInterrupted{};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		size_t frames_written =
 | 
							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
 | 
					inline bool
 | 
				
			||||||
JackOutput::Pause()
 | 
					JackOutput::Pause()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		const std::lock_guard<Mutex> lock(mutex);
 | 
							const std::lock_guard<Mutex> lock(mutex);
 | 
				
			||||||
 | 
							interrupted = false;
 | 
				
			||||||
		if (error)
 | 
							if (error)
 | 
				
			||||||
			std::rethrow_exception(error);
 | 
								std::rethrow_exception(error);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user