feat: Update pipewire backend to support the latest bmsound_wine
> minimal necessary implementation for `loopback_signal` bmsound_wine profile
This commit is contained in:
@@ -45,6 +45,7 @@ typedef int(*BmswClientStop_t)(void *);
|
|||||||
typedef int(*BmswClientDestroy_t)(void *);
|
typedef int(*BmswClientDestroy_t)(void *);
|
||||||
typedef unsigned char *(*BmswClientGetBuffer_t)(void *, uint32_t);
|
typedef unsigned char *(*BmswClientGetBuffer_t)(void *, uint32_t);
|
||||||
typedef int(*BmswClientReleaseBuffer_t)(void *, uint32_t);
|
typedef int(*BmswClientReleaseBuffer_t)(void *, uint32_t);
|
||||||
|
typedef int(*BmswClientAwaitBuffer_t)(void *);
|
||||||
typedef void (*BmswClientUpdateCallback_t)(void *, void *, void *);
|
typedef void (*BmswClientUpdateCallback_t)(void *, void *, void *);
|
||||||
static BmswConfigInit_t BmswConfigInit;
|
static BmswConfigInit_t BmswConfigInit;
|
||||||
[[maybe_unused]] static BmswExperimentalForceProfile_t BmswExperimentalForceProfile;
|
[[maybe_unused]] static BmswExperimentalForceProfile_t BmswExperimentalForceProfile;
|
||||||
@@ -57,6 +58,7 @@ static BmswClientStop_t BmswClientStop;
|
|||||||
static BmswClientDestroy_t BmswClientDestroy;
|
static BmswClientDestroy_t BmswClientDestroy;
|
||||||
static BmswClientGetBuffer_t BmswClientGetBuffer;
|
static BmswClientGetBuffer_t BmswClientGetBuffer;
|
||||||
static BmswClientReleaseBuffer_t BmswClientReleaseBuffer;
|
static BmswClientReleaseBuffer_t BmswClientReleaseBuffer;
|
||||||
|
static BmswClientAwaitBuffer_t BmswClientAwaitBuffer;
|
||||||
[[maybe_unused]] static BmswClientUpdateCallback_t BmswClientUpdateCallback;
|
[[maybe_unused]] static BmswClientUpdateCallback_t BmswClientUpdateCallback;
|
||||||
static HMODULE bmsw_ = nullptr;
|
static HMODULE bmsw_ = nullptr;
|
||||||
|
|
||||||
@@ -93,6 +95,7 @@ HRESULT PipewireBackend::on_initialize(AUDCLNT_SHAREMODE *ShareMode, DWORD *Stre
|
|||||||
|
|
||||||
// Initialize pipewire client (without starting the thread)
|
// Initialize pipewire client (without starting the thread)
|
||||||
client_ = BmswClientCreate(GAME_INSTANCE->title(), nullptr, nullptr);//(void *)callback_notify,this
|
client_ = BmswClientCreate(GAME_INSTANCE->title(), nullptr, nullptr);//(void *)callback_notify,this
|
||||||
|
notif_ = std::thread(PipewireBackend::notif_poll, this);
|
||||||
|
|
||||||
if (!client_)
|
if (!client_)
|
||||||
log_fatal("audio::pipewire", "Client could not be initialized");
|
log_fatal("audio::pipewire", "Client could not be initialized");
|
||||||
@@ -134,7 +137,7 @@ HRESULT PipewireBackend::on_start() noexcept
|
|||||||
BmswClientStart(client_);
|
BmswClientStart(client_);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
PipewireBackend::PipewireBackend() : relay_handle_(nullptr), format_(hooks::audio::FORMAT), client_(nullptr)
|
PipewireBackend::PipewireBackend() : relay_handle_(nullptr), format_(hooks::audio::FORMAT), client_(nullptr), notif_state_(-1)
|
||||||
{
|
{
|
||||||
log_info("audio::pipewire", "{}", __FUNCTION__);
|
log_info("audio::pipewire", "{}", __FUNCTION__);
|
||||||
|
|
||||||
@@ -152,6 +155,7 @@ PipewireBackend::PipewireBackend() : relay_handle_(nullptr), format_(hooks::audi
|
|||||||
BmswClientDestroy = (BmswClientDestroy_t) GetProcAddress(bmsw_, "BmswClientDestroy");
|
BmswClientDestroy = (BmswClientDestroy_t) GetProcAddress(bmsw_, "BmswClientDestroy");
|
||||||
BmswClientGetBuffer = (BmswClientGetBuffer_t) GetProcAddress(bmsw_, "BmswClientGetBuffer");
|
BmswClientGetBuffer = (BmswClientGetBuffer_t) GetProcAddress(bmsw_, "BmswClientGetBuffer");
|
||||||
BmswClientReleaseBuffer = (BmswClientReleaseBuffer_t) GetProcAddress(bmsw_, "BmswClientReleaseBuffer");
|
BmswClientReleaseBuffer = (BmswClientReleaseBuffer_t) GetProcAddress(bmsw_, "BmswClientReleaseBuffer");
|
||||||
|
BmswClientAwaitBuffer = (BmswClientAwaitBuffer_t) GetProcAddress(bmsw_, "BmswClientAwaitBuffer");
|
||||||
BmswClientUpdateCallback = (BmswClientUpdateCallback_t) GetProcAddress(bmsw_, "BmswClientUpdateCallback");
|
BmswClientUpdateCallback = (BmswClientUpdateCallback_t) GetProcAddress(bmsw_, "BmswClientUpdateCallback");
|
||||||
|
|
||||||
// Load config
|
// Load config
|
||||||
@@ -179,11 +183,21 @@ inline static void callback_notify(void *self)
|
|||||||
{
|
{
|
||||||
DWORD last_error = GetLastError();
|
DWORD last_error = GetLastError();
|
||||||
|
|
||||||
log_warning("audio::asio", "AsioBackend::buffer_switch: SetEvent failed: {} ({})",
|
log_warning("audio::pipewire", "SetEvent failed: {} ({})",
|
||||||
last_error,
|
last_error,
|
||||||
std::system_category().message(last_error));
|
std::system_category().message(last_error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void PipewireBackend::notif_poll(PipewireBackend *self)
|
||||||
|
{
|
||||||
|
self->notif_state_ = BmswClientAwaitBuffer(self->client_);
|
||||||
|
while (self->notif_state_ == 1)
|
||||||
|
{
|
||||||
|
BmswClientAwaitBuffer(self->client_);
|
||||||
|
callback_notify(self);
|
||||||
|
}
|
||||||
|
self->notif_state_ = -1;
|
||||||
|
}
|
||||||
// Amount in frames of data we may handle at once (which should always end up being what gets send by client, unless overrun happens)
|
// Amount in frames of data we may handle at once (which should always end up being what gets send by client, unless overrun happens)
|
||||||
HRESULT PipewireBackend::on_get_buffer_size(uint32_t *buffer_frames) noexcept
|
HRESULT PipewireBackend::on_get_buffer_size(uint32_t *buffer_frames) noexcept
|
||||||
{
|
{
|
||||||
@@ -228,7 +242,7 @@ HRESULT PipewireBackend::on_release_buffer(uint32_t num_frames_written, DWORD dw
|
|||||||
}
|
}
|
||||||
|
|
||||||
BmswClientReleaseBuffer(client_, num_frames_written);
|
BmswClientReleaseBuffer(client_, num_frames_written);
|
||||||
callback_notify(this);
|
if(notif_state_ == -1) callback_notify(this);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -243,6 +257,15 @@ HRESULT PipewireBackend::on_stop() noexcept
|
|||||||
PipewireBackend::~PipewireBackend()
|
PipewireBackend::~PipewireBackend()
|
||||||
{
|
{
|
||||||
log_info("audio::pipewire", "~PipewireBackend");
|
log_info("audio::pipewire", "~PipewireBackend");
|
||||||
|
if (notif_state_ == 1)
|
||||||
|
{
|
||||||
|
notif_state_ = 0;
|
||||||
|
notif_.join();
|
||||||
|
if (notif_state_ != -1)
|
||||||
|
{
|
||||||
|
log_warning("audio::pipewire", "Errors during thread cleanup: '{}'", (const int) notif_state_);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (client_) BmswClientDestroy(client_);
|
if (client_) BmswClientDestroy(client_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,15 @@ public:
|
|||||||
HRESULT on_set_event_handle(HANDLE *event_handle) override;
|
HRESULT on_set_event_handle(HANDLE *event_handle) override;
|
||||||
HRESULT on_get_buffer(uint32_t num_frames_requested, BYTE **ppData) 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;
|
HRESULT on_release_buffer(uint32_t num_frames_written, DWORD dwFlags) override;
|
||||||
|
static void notif_poll(PipewireBackend *self);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fpc_;
|
int fpc_;
|
||||||
REFERENCE_TIME wrt_;
|
REFERENCE_TIME wrt_;
|
||||||
const WAVEFORMATEXTENSIBLE &format_;
|
const WAVEFORMATEXTENSIBLE &format_;
|
||||||
void *client_;
|
void *client_;
|
||||||
|
std::thread notif_;
|
||||||
|
volatile int notif_state_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user