/* * Copyright (c) 2023, Gregory Bertilson * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include "PlaybackStream.h" #include "PulseAudioWrappers.h" namespace Audio { class PlaybackStreamPulseAudio final : public PlaybackStream { public: static ErrorOr> create(OutputState initial_state, u32 sample_rate, u8 channels, u32 target_latency_ms, AudioDataRequestCallback&& data_request_callback); virtual void set_underrun_callback(Function) override; virtual NonnullRefPtr> resume() override; virtual NonnullRefPtr> drain_buffer_and_suspend() override; virtual NonnullRefPtr> discard_buffer_and_suspend() override; virtual ErrorOr total_time_played() override; virtual NonnullRefPtr> set_volume(double) override; private: // This struct is kept alive until the control thread exits to prevent a use-after-free without blocking on // the UI thread. class InternalState : public AtomicRefCounted { public: void set_stream(NonnullRefPtr const&); RefPtr stream(); void enqueue(Function&&); void thread_loop(); ErrorOr check_is_running(); void exit(); private: RefPtr m_stream { nullptr }; Queue> m_tasks; Threading::Mutex m_mutex; Threading::ConditionVariable m_wake_condition { m_mutex }; Atomic m_exit { false }; }; PlaybackStreamPulseAudio(NonnullRefPtr); ~PlaybackStreamPulseAudio(); RefPtr m_state; }; }