114 lines
3.4 KiB
C++
114 lines
3.4 KiB
C++
/// ReMixer
|
|
/// A Public Domain C++ Audio Playback Library
|
|
/// By william @ RedactedSoftware. Thanks to Dawsh & Maxine.
|
|
/// (c) 2024 Redacted Software
|
|
/// This work is explicitly dedicated to the public domain, for the hopeful betterment of the software industry.
|
|
|
|
/// @file PulseSubsystem.h
|
|
/// @desc A PulseAudio implementation of the AudioSubsystem class.
|
|
/// @edit 2024-08-29
|
|
|
|
#pragma once
|
|
|
|
#include <pulse/pulseaudio.h>
|
|
#include <pulse/thread-mainloop.h>
|
|
#include <iostream>
|
|
#include <pulse/error.h>
|
|
#include <pulse/volume.h>
|
|
#include <pulse/stream.h>
|
|
#include <pulse/introspect.h>
|
|
|
|
|
|
|
|
#include <format>
|
|
#include <map>
|
|
|
|
#include "ReMixer/IAudioDevice.hpp"
|
|
|
|
namespace ReMixer
|
|
{
|
|
namespace PulseAudio {
|
|
class PulseDevice : public IAudioDevice {
|
|
public:
|
|
PulseDevice(const AudioDeviceInfo& info, uint32_t buffer_size_frames);
|
|
~PulseDevice() override;
|
|
|
|
bool Initialize(const AudioFormat &requestedFormat, uint32_t bufferSizeFrames) override;
|
|
void Shutdown() override;
|
|
bool Start() override;
|
|
bool Stop() override;
|
|
bool IsRunning() const override;
|
|
|
|
void
|
|
|
|
|
|
};
|
|
}
|
|
|
|
|
|
|
|
/// A PulseAudio implementation of the SoundSubsystem.
|
|
class PulseAudioSubsystem : public SoundSubsystem
|
|
{
|
|
std::map<std::string, PulseStream> streams;
|
|
public:
|
|
Event<> OnReady;
|
|
Event<> OnTerminate;
|
|
Event<> OnFail;
|
|
Event<> OnStateChange;
|
|
Event<bool> OnSuccess;
|
|
Event<const pa_server_info*> OnServerInfo;
|
|
public:
|
|
/// Constructs a new PulseAudio context with the given name.
|
|
/// @param context_name The context name. All streams created with this context will be grouped together by this name.
|
|
PulseAudioSubsystem(const std::string& context_name);
|
|
|
|
/// Plays the given sound over the given audio stream.
|
|
void Play(PulseStream& stream, const Sound& sound);
|
|
|
|
void ListDevices();
|
|
|
|
/// Returns the name of the PulseAudio context.
|
|
std::string ContextName() const;
|
|
|
|
void SetContextName(const std::string& ctx_name);
|
|
|
|
bool Connected() const;
|
|
std::string ServerName() const;
|
|
|
|
PulseStream CreateStream(const std::string& stream_name);
|
|
protected:
|
|
private:
|
|
struct pa_impl
|
|
{
|
|
pa_threaded_mainloop* mainloop;
|
|
pa_context* context;
|
|
pa_stream_direction_t* direction;
|
|
pa_mainloop_api* api;
|
|
|
|
const void* read_data;
|
|
size_t read_index, read_length;
|
|
|
|
int operation_success;
|
|
};
|
|
private:
|
|
|
|
#pragma region PulseAudio Internal Callbacks
|
|
static void OnCtxSuccess(pa_context* c, int success, void* userdata);
|
|
static void OnCtxStateChange(pa_context* c, void* userdata);
|
|
static void OnSinkDevice(pa_context* c, const pa_sink_info* info, int eol, void* userdata);
|
|
static void OnSourceDevice(pa_context* c, const pa_source_info* info, int eol, void* userdata);
|
|
static void OnListServerInfo(pa_context* c, const pa_server_info* i, void* userdata);
|
|
static void OnListSinkInfo(pa_context* c, const pa_sink_info* i, int eol, void* userdata);
|
|
static void OnStreamStateChange(pa_stream* s, void* userdata);
|
|
static void OnStreamRequest(pa_stream* s, size_t length, void* userdata);
|
|
#pragma endregion
|
|
|
|
pa_impl* pa;
|
|
bool ctx_connected = false;
|
|
std::string ctx_name;
|
|
|
|
|
|
};
|
|
}
|