Files
ReMixer/include/Backend/Pulse/PulseDevice.h
2025-07-22 13:59:00 -05:00

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;
};
}