sysaudio: add workaround for wine

wine crashes when using AudioClient3. it's weird since it returns success when quering
This commit is contained in:
Ali Chraghi 2023-01-19 17:39:07 +03:30 committed by Stephen Gutekanst
parent 7315d1ab62
commit 36a40dc51a
2 changed files with 36 additions and 35 deletions

View file

@ -9,6 +9,7 @@ pub const Context = struct {
devices_info: util.DevicesInfo,
enumerator: ?*win32.IMMDeviceEnumerator,
watcher: ?Watcher,
is_wine: bool,
const Watcher = struct {
deviceChangeFn: main.DeviceChangeFn,
@ -72,6 +73,15 @@ pub const Context = struct {
},
},
} else null,
.is_wine = blk: {
const hntdll = win32.GetModuleHandleA("ntdll.dll");
if (hntdll) |_| {
if (win32.GetProcAddress(hntdll, "wine_get_version")) |_| {
break :blk true;
}
}
break :blk false;
},
};
if (options.deviceChangeFn) |_| {
@ -303,17 +313,6 @@ pub const Context = struct {
},
.formats = blk: {
var audio_client: ?*win32.IAudioClient = null;
var audio_client3: ?*win32.IAudioClient3 = null;
hr = imm_device.?.Activate(win32.IID_IAudioClient3, win32.CLSCTX_ALL, null, @ptrCast(?*?*anyopaque, &audio_client3));
if (hr == win32.S_OK) {
hr = audio_client3.?.QueryInterface(win32.IID_IAudioClient, @ptrCast(?*?*anyopaque, &audio_client));
switch (hr) {
win32.S_OK => {},
win32.E_NOINTERFACE => unreachable,
win32.E_POINTER => unreachable,
else => return error.OpeningDevice,
}
} else {
hr = imm_device.?.Activate(win32.IID_IAudioClient, win32.CLSCTX_ALL, null, @ptrCast(?*?*anyopaque, &audio_client));
switch (hr) {
win32.S_OK => {},
@ -324,7 +323,6 @@ pub const Context = struct {
win32.AUDCLNT_E_DEVICE_INVALIDATED => unreachable,
else => return error.OpeningDevice,
}
}
var fmt_arr = std.ArrayList(main.Format).init(self.allocator);
var closest_match: ?*win32.WAVEFORMATEX = null;
@ -493,10 +491,10 @@ pub const Context = struct {
.SubFormat = toSubFormat(format) catch return error.OpeningDevice,
};
if (audio_client3) |_| {
if (!self.is_wine and audio_client3 != null) {
hr = audio_client3.?.InitializeSharedAudioStream(
win32.AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
0,
0, // TODO: use the advantage of AudioClient3
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)),
null,
);
@ -600,11 +598,11 @@ pub const Context = struct {
.ready_event = ready_event,
.aborted = .{ .value = false },
.is_paused = false,
.sample_rate = sample_rate,
.writeFn = writeFn,
.user_data = options.user_data,
.channels = device.channels,
.format = format,
.sample_rate = sample_rate,
.write_step = format.frameSize(device.channels.len),
};
return .{ .wasapi = player };
@ -658,16 +656,16 @@ pub const Player = struct {
audio_client: ?*win32.IAudioClient,
audio_client3: ?*win32.IAudioClient3,
render_client: ?*win32.IAudioRenderClient,
ready_event: win32.HANDLE,
ready_event: *anyopaque,
aborted: std.atomic.Atomic(bool),
is_paused: bool,
sample_rate: u24,
writeFn: main.WriteFn,
user_data: ?*anyopaque,
write_step: u8,
channels: []main.Channel,
format: main.Format,
sample_rate: u24,
write_step: u8,
pub fn deinit(self: *Player) void {
self.aborted.store(true, .Unordered);
@ -821,9 +819,6 @@ pub const Player = struct {
}
return vol;
}
pub fn sampleRate(self: Player) u24 {
return self.sample_rate;
}
};
pub fn freeDevice(allocator: std.mem.Allocator, self: main.Device) void {

View file

@ -222,11 +222,18 @@ pub extern "kernel32" fn CreateEventA(
bManualReset: BOOL,
bInitialState: BOOL,
lpName: ?[*:0]const u8,
) callconv(WINAPI) ?HANDLE;
) callconv(WINAPI) ?*anyopaque;
pub extern "kernel32" fn WaitForSingleObject(
hHandle: ?HANDLE,
hHandle: ?*anyopaque,
dwMilliseconds: u32,
) callconv(WINAPI) u32;
pub extern "kernel32" fn GetModuleHandleA(
lpModuleName: ?[*:0]const u8,
) callconv(WINAPI) ?*anyopaque;
pub extern "kernel32" fn GetProcAddress(
hModule: ?*anyopaque,
lpProcName: ?[*:0]const u8,
) callconv(WINAPI) ?*const fn () callconv(WINAPI) isize;
pub const INFINITE = 4294967295;
pub const SECURITY_ATTRIBUTES = extern struct {
nLength: u32,
@ -1168,7 +1175,6 @@ pub const AUDCLNT_SHAREMODE = enum(i32) {
SHARED = 0,
EXCLUSIVE = 1,
};
pub const HANDLE = @import("std").os.windows.HANDLE;
pub const IID_IAudioClient = &Guid.initString("1cb9ad4c-dbfa-4c32-b178-c2f568a703b2");
pub const IAudioClient = extern struct {
pub const VTable = extern struct {
@ -1220,7 +1226,7 @@ pub const IAudioClient = extern struct {
) callconv(WINAPI) HRESULT,
SetEventHandle: *const fn (
self: *const IAudioClient,
eventHandle: ?HANDLE,
eventHandle: ?*anyopaque,
) callconv(WINAPI) HRESULT,
GetService: *const fn (
self: *const IAudioClient,
@ -1262,7 +1268,7 @@ pub const IAudioClient = extern struct {
pub inline fn Reset(self: *const T) HRESULT {
return @ptrCast(*const IAudioClient.VTable, self.vtable).Reset(@ptrCast(*const IAudioClient, self));
}
pub inline fn SetEventHandle(self: *const T, eventHandle: ?HANDLE) HRESULT {
pub inline fn SetEventHandle(self: *const T, eventHandle: ?*anyopaque) HRESULT {
return @ptrCast(*const IAudioClient.VTable, self.vtable).SetEventHandle(@ptrCast(*const IAudioClient, self), eventHandle);
}
pub inline fn GetService(self: *const T, riid: ?*const Guid, ppv: ?*?*anyopaque) HRESULT {