sysaudio:wasapi: wait for audio client to be ready

This commit is contained in:
Ali Chraghi 2022-12-18 23:38:42 +03:30 committed by Stephen Gutekanst
parent a3d23b199d
commit dc3f4b4c00
2 changed files with 52 additions and 11 deletions

View file

@ -472,7 +472,8 @@ pub const Context = struct {
hr = audio_client.?.Initialize( hr = audio_client.?.Initialize(
.SHARED, .SHARED,
win32.AUDCLNT_STREAMFLAGS_NOPERSIST, win32.AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
win32.AUDCLNT_STREAMFLAGS_NOPERSIST,
0, 0,
0, 0,
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)), @ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)),
@ -526,6 +527,18 @@ pub const Context = struct {
else => return error.OpeningDevice, 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 .{ return .{
.wasapi = .{ .wasapi = .{
.thread = undefined, .thread = undefined,
@ -538,6 +551,7 @@ pub const Context = struct {
.simple_volume = simple_volume, .simple_volume = simple_volume,
.imm_device = imm_device, .imm_device = imm_device,
.render_client = render_client, .render_client = render_client,
.ready_event = ready_event,
.is_paused = false, .is_paused = false,
.vol = 1.0, .vol = 1.0,
.aborted = .{ .value = false }, .aborted = .{ .value = false },
@ -595,6 +609,7 @@ pub const Player = struct {
imm_device: ?*win32.IMMDevice, imm_device: ?*win32.IMMDevice,
audio_client: ?*win32.IAudioClient, audio_client: ?*win32.IAudioClient,
render_client: ?*win32.IAudioRenderClient, render_client: ?*win32.IAudioRenderClient,
ready_event: win32.HANDLE,
aborted: std.atomic.Atomic(bool), aborted: std.atomic.Atomic(bool),
is_paused: bool, is_paused: bool,
vol: f32, vol: f32,
@ -634,8 +649,10 @@ pub const Player = struct {
} }
while (!self.aborted.load(.Unordered)) { while (!self.aborted.load(.Unordered)) {
var frames_buf: u32 = 0; _ = win32.WaitForSingleObject(self.ready_event, win32.INFINITE);
hr = self.audio_client.?.GetBufferSize(&frames_buf);
var buf_frames: u32 = 0;
hr = self.audio_client.?.GetBufferSize(&buf_frames);
switch (hr) { switch (hr) {
win32.S_OK => {}, win32.S_OK => {},
win32.E_POINTER => unreachable, win32.E_POINTER => unreachable,
@ -645,8 +662,8 @@ pub const Player = struct {
else => unreachable, else => unreachable,
} }
var frames_used: u32 = 0; var padding_frames: u32 = 0;
hr = self.audio_client.?.GetCurrentPadding(&frames_used); hr = self.audio_client.?.GetCurrentPadding(&padding_frames);
switch (hr) { switch (hr) {
win32.S_OK => {}, win32.S_OK => {},
win32.E_POINTER => unreachable, win32.E_POINTER => unreachable,
@ -655,10 +672,10 @@ pub const Player = struct {
win32.AUDCLNT_E_SERVICE_NOT_RUNNING => return, win32.AUDCLNT_E_SERVICE_NOT_RUNNING => return,
else => unreachable, else => unreachable,
} }
const writable_frame_count = frames_buf - frames_used; const frames = buf_frames - padding_frames;
if (writable_frame_count > 0) { if (frames > 0) {
var data: [*]u8 = undefined; 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) { switch (hr) {
win32.S_OK => {}, win32.S_OK => {},
win32.E_POINTER => unreachable, win32.E_POINTER => unreachable,
@ -676,8 +693,9 @@ pub const Player = struct {
ch.*.ptr = data + self.format().frameSize(i); ch.*.ptr = data + self.format().frameSize(i);
} }
self.writeFn(parent, writable_frame_count); self.writeFn(parent, frames);
hr = self.render_client.?.ReleaseBuffer(writable_frame_count, 0);
hr = self.render_client.?.ReleaseBuffer(frames, 0);
switch (hr) { switch (hr) {
win32.S_OK => {}, win32.S_OK => {},
win32.E_INVALIDARG => unreachable, win32.E_INVALIDARG => unreachable,
@ -776,4 +794,4 @@ pub fn freeDevice(allocator: std.mem.Allocator, self: main.Device) void {
test { test {
std.testing.refAllDeclsRecursive(@This()); std.testing.refAllDeclsRecursive(@This());
} }

View file

@ -217,6 +217,22 @@ pub extern "ole32" fn CoCreateInstance(
riid: *const Guid, riid: *const Guid,
ppv: ?*?*anyopaque, ppv: ?*?*anyopaque,
) callconv(WINAPI) HRESULT; ) 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 IID_IUnknown = &Guid.initString("00000000-0000-0000-c000-000000000046");
pub const IUnknown = extern struct { pub const IUnknown = extern struct {
pub const VTable = extern struct { pub const VTable = extern struct {
@ -1576,7 +1592,14 @@ pub const IMMEndpoint = extern struct {
} }
pub usingnamespace MethodMixin(@This()); 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_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 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 CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = &Guid.initString("00000003-0000-0010-8000-00aa00389b71");
pub const SPEAKER_FRONT_LEFT = 1; pub const SPEAKER_FRONT_LEFT = 1;