Poking at pulseaudio api still

This commit is contained in:
2024-08-25 20:50:29 -04:00
parent ab265a05b7
commit 828048b882
4 changed files with 143 additions and 5 deletions

View File

@@ -16,6 +16,11 @@ CPMAddPackage(
URL https://git.redacted.cc/Redacted/uuid/archive/Release-1.zip
)
CPMAddPackage(
NAME Event
URL https://git.redacted.cc/josh/Event/archive/Release-11.zip
)
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In-Source builds are not allowed")
endif()
@@ -39,6 +44,9 @@ add_executable(ReMixer-Test main.cpp)
set_target_properties(ReMixer PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(ReMixer-Test PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(ReMixer PUBLIC ${Event_SOURCE_DIR}/include)
target_link_libraries(ReMixer PUBLIC Event)
if(UNIX AND NOT APPLE)
target_link_libraries(ReMixer PUBLIC vorbisfile vorbis pulse-simple pulse uuid)
endif()
@@ -51,7 +59,8 @@ target_link_libraries(ReMixer-Test PUBLIC ReMixer)
add_executable(pacat pacat_simple.cpp
pacat_advanced.cpp
src/windows/ReMixer.cpp)
src/windows/ReMixer.cpp
include/ReMixer/PulseSubsystem.h)
target_link_libraries(pacat pulse-simple pulse)
add_executable(vorbis_decode vorbis_decode.cpp)

View File

@@ -0,0 +1,8 @@
//
// Created by dawsh on 8/23/24.
//
#ifndef REMIXER_PULSESUBSYSTEM_H
#define REMIXER_PULSESUBSYSTEM_H
#endif //REMIXER_PULSESUBSYSTEM_H

View File

@@ -1,10 +1,89 @@
#pragma once
#include <Event.h>
/// A managed sound handler object.
class Sound
{
public:
virtual bool IsPlaying() = 0;
virtual bool IsPaused() = 0;
virtual bool IsFinished() = 0;
float PlaybackLoudness();
int ChannelCount();
bool Looped();
float PlaybackSpeed();
float TimeLength();
float TimePosition();
float Volume();
void SetTimePosition(float timePos);
void SetVolume(float vol);
void SetPlaybackSpeed(float speed);
virtual void Pause() = 0;
virtual void Play() = 0;
void Resume();
void Stop();
Event<int> DidLoop;
Event<> Ended;
Event<> Paused;
Event<> Played;
Event<> Resumed;
protected:
private:
};
/// TODO: Equalizer Effect
/// TODO: Compressor Effect
/// TODO: Reverb Effect
/// TODO: Chorus Effect
/// TODO: Distortion Effect
/// TODO: Echo Effect
/// TODO: Flange Effect
/// TODO: Pitch Shift Effect
/// TODO: Tremolo Effect
/// TODO: Positional Sound Object?
/// Physical representation of Pulse-Code-Modulated sound data.
class PCM
{
};
class Decibels
{
};
class AudioDevice {};
class PlaybackDevice : public AudioDevice {};
class RecordingDevice : public AudioDevice {};
/// An abstract class that defines the SoundSubsystem which will be used by the higher-level ReMixer API.
/// Since it is common for sound APIs to operate on a separate (or even multiple) threads,
/// The subsystem also functions as a "controller" that manages these separate threads.
/// Therefore, it is safe to use in a single-threaded application.
class SoundSubsystem
{
public:
std::vector<AudioDevice> GetAudioDevices();
std::vector<PlaybackDevice> GetPlaybackDevices();
std::vector<RecordingDevice> GetRecordingDevices();
std::string GetPlaybackDevice();
std::string GetRecordingDevice();
void SetPlaybackDevice();
void SetRecordingDevice();
void SetMasterVolume(Decibels db);
protected:
private:
@@ -25,4 +104,5 @@ class WASAPISubsystem : public SoundSubsystem
public:
protected:
private:
};
};

View File

@@ -4,8 +4,10 @@
#include <pulse/error.h>
#include <pulse/volume.h>
#include <pulse/stream.h>
#include <pulse/introspect.h>
#include <format>
#include <cstring>
#include <thread>
#include <iostream>
#include <cstdio>
@@ -18,8 +20,6 @@
// https://habr.com/en/articles/663352/#linux-and-pulseaudio
/// The pa_system structure holds all the PulseAudio structures together
struct pa_system
{
@@ -499,6 +499,35 @@ pa_usec_t pa_system_get_latency(pa_system* p, int *rerror) {
#define BUFSIZE 1024
static void list_sink_info(pa_context* c, pa_sink_info* i, int eol, void* userdata)
{
if (eol != 0)
{
auto *p = static_cast<pa_system *>(userdata);
pa_threaded_mainloop_signal(p->mainloop, 0);
}
if (i == nullptr)
{
std::cerr << "Sink info is null!" << std::endl;
return;
}
std::cout << i->name << std::endl;
}
static void list_server_info(pa_context* c, pa_server_info* i, void* userdata)
{
auto *p = static_cast<pa_system *>(userdata);
pa_threaded_mainloop_signal(p->mainloop, 0);
}
static void stream_success_cb(pa_stream* s, int success, void* userdata)
{
auto *p = static_cast<pa_system *>(userdata);
pa_threaded_mainloop_signal(p->mainloop, 0);
}
int main(int argc, char* argv[]) {
if (argc == 1 || argv[1] == "-h" || argv[1] == "help")
{
@@ -506,7 +535,6 @@ int main(int argc, char* argv[]) {
std::cout << "usage: pacat <file> (presumably output.raw)\n" << std::endl;
}
//argv[1] = "output.raw";
static const pa_sample_spec ss = {
@@ -541,6 +569,9 @@ int main(int argc, char* argv[]) {
goto finish;
}
pa_context_get_server_info(s->context, reinterpret_cast<pa_server_info_cb_t>(list_server_info), s);
pa_context_get_sink_info_list(s->context, reinterpret_cast<pa_sink_info_cb_t>(list_sink_info), s);
pa_system_enumerate_devices(s);
@@ -574,6 +605,16 @@ int main(int argc, char* argv[]) {
}
}
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
pa_stream_cork(s->stream, 1, stream_success_cb, s);
std::this_thread::sleep_for(1s);
pa_stream_cork(s->stream, 0, stream_success_cb, s);
/* Make sure that every single sample was played */
if (pa_system_drain(s, &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(error));