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 unsigned char *(*BmswClientGetBuffer_t)(void *, uint32_t);
|
||||
typedef int(*BmswClientReleaseBuffer_t)(void *, uint32_t);
|
||||
typedef int(*BmswClientAwaitBuffer_t)(void *);
|
||||
typedef void (*BmswClientUpdateCallback_t)(void *, void *, void *);
|
||||
static BmswConfigInit_t BmswConfigInit;
|
||||
[[maybe_unused]] static BmswExperimentalForceProfile_t BmswExperimentalForceProfile;
|
||||
@@ -57,6 +58,7 @@ static BmswClientStop_t BmswClientStop;
|
||||
static BmswClientDestroy_t BmswClientDestroy;
|
||||
static BmswClientGetBuffer_t BmswClientGetBuffer;
|
||||
static BmswClientReleaseBuffer_t BmswClientReleaseBuffer;
|
||||
static BmswClientAwaitBuffer_t BmswClientAwaitBuffer;
|
||||
[[maybe_unused]] static BmswClientUpdateCallback_t BmswClientUpdateCallback;
|
||||
static HMODULE bmsw_ = nullptr;
|
||||
|
||||
@@ -93,6 +95,7 @@ HRESULT PipewireBackend::on_initialize(AUDCLNT_SHAREMODE *ShareMode, DWORD *Stre
|
||||
|
||||
// Initialize pipewire client (without starting the thread)
|
||||
client_ = BmswClientCreate(GAME_INSTANCE->title(), nullptr, nullptr);//(void *)callback_notify,this
|
||||
notif_ = std::thread(PipewireBackend::notif_poll, this);
|
||||
|
||||
if (!client_)
|
||||
log_fatal("audio::pipewire", "Client could not be initialized");
|
||||
@@ -134,7 +137,7 @@ HRESULT PipewireBackend::on_start() noexcept
|
||||
BmswClientStart(client_);
|
||||
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__);
|
||||
|
||||
@@ -152,6 +155,7 @@ PipewireBackend::PipewireBackend() : relay_handle_(nullptr), format_(hooks::audi
|
||||
BmswClientDestroy = (BmswClientDestroy_t) GetProcAddress(bmsw_, "BmswClientDestroy");
|
||||
BmswClientGetBuffer = (BmswClientGetBuffer_t) GetProcAddress(bmsw_, "BmswClientGetBuffer");
|
||||
BmswClientReleaseBuffer = (BmswClientReleaseBuffer_t) GetProcAddress(bmsw_, "BmswClientReleaseBuffer");
|
||||
BmswClientAwaitBuffer = (BmswClientAwaitBuffer_t) GetProcAddress(bmsw_, "BmswClientAwaitBuffer");
|
||||
BmswClientUpdateCallback = (BmswClientUpdateCallback_t) GetProcAddress(bmsw_, "BmswClientUpdateCallback");
|
||||
|
||||
// Load config
|
||||
@@ -179,11 +183,21 @@ inline static void callback_notify(void *self)
|
||||
{
|
||||
DWORD last_error = GetLastError();
|
||||
|
||||
log_warning("audio::asio", "AsioBackend::buffer_switch: SetEvent failed: {} ({})",
|
||||
log_warning("audio::pipewire", "SetEvent failed: {} ({})",
|
||||
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)
|
||||
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);
|
||||
callback_notify(this);
|
||||
if(notif_state_ == -1) callback_notify(this);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -243,6 +257,15 @@ HRESULT PipewireBackend::on_stop() noexcept
|
||||
PipewireBackend::~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_);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,15 @@ public:
|
||||
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;
|
||||
static void notif_poll(PipewireBackend *self);
|
||||
|
||||
private:
|
||||
int fpc_;
|
||||
REFERENCE_TIME wrt_;
|
||||
const WAVEFORMATEXTENSIBLE &format_;
|
||||
void *client_;
|
||||
std::thread notif_;
|
||||
volatile int notif_state_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user