Skip to content

Commit

Permalink
sysaudio:wasapi: wait for audio client to be ready
Browse files Browse the repository at this point in the history
  • Loading branch information
alichraghi committed Dec 18, 2022
1 parent ae1c091 commit c059c2a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 11 deletions.
40 changes: 29 additions & 11 deletions libs/sysaudio/src/wasapi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ pub const Context = struct {

hr = audio_client.?.Initialize(
.SHARED,
win32.AUDCLNT_STREAMFLAGS_NOPERSIST,
win32.AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
win32.AUDCLNT_STREAMFLAGS_NOPERSIST,
0,
0,
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)),
Expand Down Expand Up @@ -526,6 +527,18 @@ pub const Context = struct {
else => return error.OpeningDevice,
}

var ready_event = win32.CreateEventA(null, 0, 0, null) orelse return error.SystemResources;
hr = audio_client.?.SetEventHandle(ready_event);
switch (hr) {
win32.S_OK => {},
win32.E_INVALIDARG => unreachable,
win32.AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED => unreachable,
win32.AUDCLNT_E_NOT_INITIALIZED => unreachable,
win32.AUDCLNT_E_DEVICE_INVALIDATED => return error.OpeningDevice,
win32.AUDCLNT_E_SERVICE_NOT_RUNNING => return error.OpeningDevice,
else => return error.OpeningDevice,
}

return .{
.wasapi = .{
.thread = undefined,
Expand All @@ -538,6 +551,7 @@ pub const Context = struct {
.simple_volume = simple_volume,
.imm_device = imm_device,
.render_client = render_client,
.ready_event = ready_event,
.is_paused = false,
.vol = 1.0,
.aborted = .{ .value = false },
Expand Down Expand Up @@ -595,6 +609,7 @@ pub const Player = struct {
imm_device: ?*win32.IMMDevice,
audio_client: ?*win32.IAudioClient,
render_client: ?*win32.IAudioRenderClient,
ready_event: win32.HANDLE,
aborted: std.atomic.Atomic(bool),
is_paused: bool,
vol: f32,
Expand Down Expand Up @@ -634,8 +649,10 @@ pub const Player = struct {
}

while (!self.aborted.load(.Unordered)) {
var frames_buf: u32 = 0;
hr = self.audio_client.?.GetBufferSize(&frames_buf);
_ = win32.WaitForSingleObject(self.ready_event, win32.INFINITE);

var buf_frames: u32 = 0;
hr = self.audio_client.?.GetBufferSize(&buf_frames);
switch (hr) {
win32.S_OK => {},
win32.E_POINTER => unreachable,
Expand All @@ -645,8 +662,8 @@ pub const Player = struct {
else => unreachable,
}

var frames_used: u32 = 0;
hr = self.audio_client.?.GetCurrentPadding(&frames_used);
var padding_frames: u32 = 0;
hr = self.audio_client.?.GetCurrentPadding(&padding_frames);
switch (hr) {
win32.S_OK => {},
win32.E_POINTER => unreachable,
Expand All @@ -655,10 +672,10 @@ pub const Player = struct {
win32.AUDCLNT_E_SERVICE_NOT_RUNNING => return,
else => unreachable,
}
const writable_frame_count = frames_buf - frames_used;
if (writable_frame_count > 0) {
const frames = buf_frames - padding_frames;
if (frames > 0) {
var data: [*]u8 = undefined;
hr = self.render_client.?.GetBuffer(writable_frame_count, @ptrCast(?*?*u8, &data));
hr = self.render_client.?.GetBuffer(frames, @ptrCast(?*?*u8, &data));
switch (hr) {
win32.S_OK => {},
win32.E_POINTER => unreachable,
Expand All @@ -676,8 +693,9 @@ pub const Player = struct {
ch.*.ptr = data + self.format().frameSize(i);
}

self.writeFn(parent, writable_frame_count);
hr = self.render_client.?.ReleaseBuffer(writable_frame_count, 0);
self.writeFn(parent, frames);

hr = self.render_client.?.ReleaseBuffer(frames, 0);
switch (hr) {
win32.S_OK => {},
win32.E_INVALIDARG => unreachable,
Expand Down Expand Up @@ -776,4 +794,4 @@ pub fn freeDevice(allocator: std.mem.Allocator, self: main.Device) void {

test {
std.testing.refAllDeclsRecursive(@This());
}
}
23 changes: 23 additions & 0 deletions libs/sysaudio/src/wasapi/win32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,22 @@ pub extern "ole32" fn CoCreateInstance(
riid: *const Guid,
ppv: ?*?*anyopaque,
) callconv(WINAPI) HRESULT;
pub extern "kernel32" fn CreateEventA(
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
bManualReset: BOOL,
bInitialState: BOOL,
lpName: ?[*:0]const u8,
) callconv(WINAPI) ?HANDLE;
pub extern "kernel32" fn WaitForSingleObject(
hHandle: ?HANDLE,
dwMilliseconds: u32,
) callconv(WINAPI) u32;
pub const INFINITE = 4294967295;
pub const SECURITY_ATTRIBUTES = extern struct {
nLength: u32,
lpSecurityDescriptor: ?*anyopaque,
bInheritHandle: BOOL,
};
pub const IID_IUnknown = &Guid.initString("00000000-0000-0000-c000-000000000046");
pub const IUnknown = extern struct {
pub const VTable = extern struct {
Expand Down Expand Up @@ -1576,7 +1592,14 @@ pub const IMMEndpoint = extern struct {
}
pub usingnamespace MethodMixin(@This());
};
pub const AUDCLNT_STREAMFLAGS_CROSSPROCESS = 65536;
pub const AUDCLNT_STREAMFLAGS_LOOPBACK = 131072;
pub const AUDCLNT_STREAMFLAGS_EVENTCALLBACK = 262144;
pub const AUDCLNT_STREAMFLAGS_NOPERSIST = 524288;
pub const AUDCLNT_STREAMFLAGS_RATEADJUST = 1048576;
pub const AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY = 134217728;
pub const AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM = 2147483648;
pub const AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED = 268435456;
pub const PKEY_Device_FriendlyName = PROPERTYKEY{ .fmtid = Guid.initString("a45c254e-df1c-4efd-8020-67d146a850e0"), .pid = 14 };
pub const CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = &Guid.initString("00000003-0000-0010-8000-00aa00389b71");
pub const SPEAKER_FRONT_LEFT = 1;
Expand Down

0 comments on commit c059c2a

Please sign in to comment.