mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:47:35 +00:00
LibAudio: Create a playback class with a PulseAudio implementation
This adds an abstract `Audio::PlaybackStream` class to allow cross- platform audio playback to be done in an opaque manner by applications in both Serenity and Lagom. Currently, the only supported audio API is PulseAudio, but a Serenity implementation should be added shortly as well.
This commit is contained in:
parent
fe672989a9
commit
bc4d4f0f95
9 changed files with 1041 additions and 0 deletions
62
Userland/Libraries/LibAudio/PlaybackStreamPulseAudio.h
Normal file
62
Userland/Libraries/LibAudio/PlaybackStreamPulseAudio.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Gregory Bertilson <zaggy1024@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibAudio/PlaybackStream.h>
|
||||
#include <LibAudio/PulseAudioWrappers.h>
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class PlaybackStreamPulseAudio final
|
||||
: public PlaybackStream {
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<PlaybackStream>> create(OutputState initial_state, u32 sample_rate, u8 channels, u32 target_latency_ms, AudioDataRequestCallback&& data_request_callback);
|
||||
|
||||
virtual void set_underrun_callback(Function<void()>) override;
|
||||
|
||||
virtual NonnullRefPtr<Core::ThreadedPromise<Duration>> resume() override;
|
||||
virtual NonnullRefPtr<Core::ThreadedPromise<void>> drain_buffer_and_suspend() override;
|
||||
virtual NonnullRefPtr<Core::ThreadedPromise<void>> discard_buffer_and_suspend() override;
|
||||
|
||||
virtual ErrorOr<Duration> total_time_played() override;
|
||||
|
||||
virtual NonnullRefPtr<Core::ThreadedPromise<void>> 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<InternalState> {
|
||||
public:
|
||||
void set_thread(NonnullRefPtr<Threading::Thread> const&);
|
||||
|
||||
void set_stream(NonnullRefPtr<PulseAudioStream> const&);
|
||||
RefPtr<PulseAudioStream> stream();
|
||||
|
||||
void enqueue(Function<void()>&&);
|
||||
void thread_loop();
|
||||
ErrorOr<void> check_is_running();
|
||||
void exit();
|
||||
|
||||
private:
|
||||
RefPtr<PulseAudioStream> m_stream { nullptr };
|
||||
|
||||
Queue<Function<void()>> m_tasks;
|
||||
Threading::Mutex m_mutex;
|
||||
Threading::ConditionVariable m_wake_condition { m_mutex };
|
||||
|
||||
Atomic<bool> m_exit { false };
|
||||
|
||||
RefPtr<Threading::Thread> m_thread { nullptr };
|
||||
};
|
||||
|
||||
PlaybackStreamPulseAudio(NonnullRefPtr<InternalState>);
|
||||
~PlaybackStreamPulseAudio();
|
||||
|
||||
RefPtr<InternalState> m_state;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue