sysaudio:wasapi: wait for audio client to be ready
This commit is contained in:
parent
a3d23b199d
commit
dc3f4b4c00
2 changed files with 52 additions and 11 deletions
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue