feat: Add pipewire backend

> only for testing current bmsound_wine implementation wine-side
This commit is contained in:
[ ]
2023-10-02 23:51:45 +09:00
parent 15cd228b8d
commit f6f62e0e9d
6 changed files with 171 additions and 1 deletions
+3
View File
@@ -11,6 +11,7 @@ namespace hooks::audio {
enum class Backend {
Asio,
WaveOut,
Pipewire,
None
};
@@ -28,6 +29,8 @@ namespace hooks::audio {
return Backend::Asio;
} else if (_stricmp(value, "waveout") == 0) {
return Backend::WaveOut;
} else if (_stricmp(value, "pipewire") == 0) {
return Backend::Pipewire;
} else if (_stricmp(value, "none") == 0) {
return Backend::None;
}
@@ -9,6 +9,7 @@
#include "hooks/audio/backends/wasapi/util.h"
#include "hooks/audio/implementations/asio.h"
#include "hooks/audio/implementations/wave_out.h"
#include "hooks/audio/implementations/pipewire.h"
#include "hooks/audio/implementations/none.h"
//#include "util/co_task_mem_ptr.h"
@@ -161,6 +162,9 @@ IAudioClient *wrap_audio_client(IAudioClient *audio_client) {
case hooks::audio::Backend::WaveOut:
backend = new WaveOutBackend();
break;
case hooks::audio::Backend::Pipewire:
backend = new PipewireBackend();
break;
case hooks::audio::Backend::None:
backend = new NoneBackend();
break;
+111
View File
@@ -0,0 +1,111 @@
#include "pipewire.h"
#include "hooks/audio/audio.h"
#include "hooks/audio/backends/wasapi/audio_client.h"
#include "util/libutils.h"
#include "launcher/launcher.h"
/* Imports (refer to bmsound-wine.dll.spec) */
typedef void(*BmswClientInit_t)(const char*);
const WAVEFORMATEXTENSIBLE &PipewireBackend::format() const noexcept {
return format_;
}
HRESULT PipewireBackend::on_initialize(
AUDCLNT_SHAREMODE *ShareMode,
DWORD *StreamFlags,
REFERENCE_TIME *hnsBufferDuration,
REFERENCE_TIME *hnsPeriodicity,
const WAVEFORMATEX *pFormat,
LPCGUID AudioSessionGuid) noexcept
{
log_info("audio::pipewire", "on_initialize");
// WASAPI init
*ShareMode = AUDCLNT_SHAREMODE_SHARED;
*StreamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
AUDCLNT_STREAMFLAGS_RATEADJUST |
AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM |
AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
*hnsBufferDuration = 100000;
*hnsPeriodicity = 100000;
// Start pipewire thread
if (!bmsw_) log_fatal("audio::pipewire", "Library not found: '{}'", (MODULE_PATH / "bmsound-wine.dll").string());
auto pipewireinit = (BmswClientInit_t)GetProcAddress(bmsw_, "BmswClientInit");
if (!pipewireinit) log_fatal("audio::pipewire", "Library invalid: '{}'", (MODULE_PATH / "bmsound-wine.dll").string());
internal_ = std::thread(pipewireinit,"GAME TITLE");
return S_OK;
}
HRESULT PipewireBackend::on_get_buffer_size(uint32_t *buffer_frames) noexcept {
*buffer_frames = 0;
return S_OK;
}
HRESULT PipewireBackend::on_get_stream_latency(REFERENCE_TIME *latency) noexcept {
*latency = 100000;
return S_OK;
}
HRESULT PipewireBackend::on_get_current_padding(std::optional<uint32_t> &padding_frames) noexcept {
padding_frames = 0;
return S_OK;
}
HRESULT PipewireBackend::on_is_format_supported(
AUDCLNT_SHAREMODE *ShareMode,
const WAVEFORMATEX *pFormat,
WAVEFORMATEX **ppClosestMatch) noexcept
{
// only accept 44.1 kHz, stereo, 16-bits per channel
if (*ShareMode == AUDCLNT_SHAREMODE_EXCLUSIVE &&
pFormat->nChannels == 2 &&
pFormat->nSamplesPerSec == 44100 &&
pFormat->wBitsPerSample == 16)
{
return S_OK;
}
return AUDCLNT_E_UNSUPPORTED_FORMAT;
}
HRESULT PipewireBackend::on_get_mix_format(WAVEFORMATEX **pp_device_format) noexcept {
return E_NOTIMPL;
}
HRESULT PipewireBackend::on_get_device_period(
REFERENCE_TIME *default_device_period,
REFERENCE_TIME *minimum_device_period)
{
*default_device_period = 10000;
*minimum_device_period = 10000;
return S_OK;
}
HRESULT PipewireBackend::on_start() noexcept {
return S_OK;
}
HRESULT PipewireBackend::on_stop() noexcept {
return S_OK;
}
HRESULT PipewireBackend::on_set_event_handle(HANDLE *event_handle) {
*event_handle = CreateEvent(nullptr, true, false, nullptr);
return S_OK;
}
HRESULT PipewireBackend::on_get_buffer(uint32_t num_frames_requested, BYTE **ppData) {
static BYTE buf[10000];
*ppData = buf;
return S_OK;
}
HRESULT PipewireBackend::on_release_buffer(uint32_t num_frames_written, DWORD dwFlags) {
return S_OK;
}
PipewireBackend::PipewireBackend() : format_(hooks::audio::FORMAT), bmsw_(libutils::try_library(MODULE_PATH / "bmsound-wine.dll"))
{
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include "backend.h"
#include <thread>
struct PipewireBackend final : AudioBackend {
public:
explicit PipewireBackend();
~PipewireBackend() final = default;
[[nodiscard]] const WAVEFORMATEXTENSIBLE &format() const noexcept override;
HRESULT on_initialize(
AUDCLNT_SHAREMODE *ShareMode,
DWORD *StreamFlags,
REFERENCE_TIME *hnsBufferDuration,
REFERENCE_TIME *hnsPeriodicity,
const WAVEFORMATEX *pFormat,
LPCGUID AudioSessionGuid) noexcept override;
HRESULT on_get_buffer_size(uint32_t *buffer_frames) noexcept override;
HRESULT on_get_stream_latency(REFERENCE_TIME *latency) noexcept override;
HRESULT on_get_current_padding(std::optional<uint32_t> &padding_frames) noexcept override;
HRESULT on_is_format_supported(
AUDCLNT_SHAREMODE *ShareMode,
const WAVEFORMATEX *pFormat,
WAVEFORMATEX **ppClosestMatch) noexcept override;
HRESULT on_get_mix_format(WAVEFORMATEX **pp_device_format) noexcept override;
HRESULT on_get_device_period(
REFERENCE_TIME *default_device_period,
REFERENCE_TIME *minimum_device_period) override;
HRESULT on_start() noexcept override;
HRESULT on_stop() noexcept override;
HRESULT on_set_event_handle(HANDLE *event_handle) override;
HRESULT on_get_buffer(uint32_t num_frames_requested, BYTE **ppData) override;
HRESULT on_release_buffer(uint32_t num_frames_written, DWORD dwFlags) override;
private:
const WAVEFORMATEXTENSIBLE &format_;
std::thread internal_;
HMODULE bmsw_;
//BYTE *active_sound_buffer = nullptr;
};