sysaudio: add workaround for wine
wine crashes when using AudioClient3. it's weird since it returns success when quering
This commit is contained in:
parent
7315d1ab62
commit
36a40dc51a
2 changed files with 36 additions and 35 deletions
|
|
@ -9,6 +9,7 @@ pub const Context = struct {
|
||||||
devices_info: util.DevicesInfo,
|
devices_info: util.DevicesInfo,
|
||||||
enumerator: ?*win32.IMMDeviceEnumerator,
|
enumerator: ?*win32.IMMDeviceEnumerator,
|
||||||
watcher: ?Watcher,
|
watcher: ?Watcher,
|
||||||
|
is_wine: bool,
|
||||||
|
|
||||||
const Watcher = struct {
|
const Watcher = struct {
|
||||||
deviceChangeFn: main.DeviceChangeFn,
|
deviceChangeFn: main.DeviceChangeFn,
|
||||||
|
|
@ -72,6 +73,15 @@ pub const Context = struct {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} else null,
|
} 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) |_| {
|
if (options.deviceChangeFn) |_| {
|
||||||
|
|
@ -303,27 +313,15 @@ pub const Context = struct {
|
||||||
},
|
},
|
||||||
.formats = blk: {
|
.formats = blk: {
|
||||||
var audio_client: ?*win32.IAudioClient = null;
|
var audio_client: ?*win32.IAudioClient = null;
|
||||||
var audio_client3: ?*win32.IAudioClient3 = null;
|
hr = imm_device.?.Activate(win32.IID_IAudioClient, win32.CLSCTX_ALL, null, @ptrCast(?*?*anyopaque, &audio_client));
|
||||||
hr = imm_device.?.Activate(win32.IID_IAudioClient3, win32.CLSCTX_ALL, null, @ptrCast(?*?*anyopaque, &audio_client3));
|
switch (hr) {
|
||||||
if (hr == win32.S_OK) {
|
win32.S_OK => {},
|
||||||
hr = audio_client3.?.QueryInterface(win32.IID_IAudioClient, @ptrCast(?*?*anyopaque, &audio_client));
|
win32.E_POINTER => unreachable,
|
||||||
switch (hr) {
|
win32.E_INVALIDARG => unreachable,
|
||||||
win32.S_OK => {},
|
win32.E_NOINTERFACE => unreachable,
|
||||||
win32.E_NOINTERFACE => unreachable,
|
win32.E_OUTOFMEMORY => return error.OutOfMemory,
|
||||||
win32.E_POINTER => unreachable,
|
win32.AUDCLNT_E_DEVICE_INVALIDATED => unreachable,
|
||||||
else => return error.OpeningDevice,
|
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 => {},
|
|
||||||
win32.E_POINTER => unreachable,
|
|
||||||
win32.E_INVALIDARG => unreachable,
|
|
||||||
win32.E_NOINTERFACE => unreachable,
|
|
||||||
win32.E_OUTOFMEMORY => return error.OutOfMemory,
|
|
||||||
win32.AUDCLNT_E_DEVICE_INVALIDATED => unreachable,
|
|
||||||
else => return error.OpeningDevice,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var fmt_arr = std.ArrayList(main.Format).init(self.allocator);
|
var fmt_arr = std.ArrayList(main.Format).init(self.allocator);
|
||||||
|
|
@ -493,10 +491,10 @@ pub const Context = struct {
|
||||||
.SubFormat = toSubFormat(format) catch return error.OpeningDevice,
|
.SubFormat = toSubFormat(format) catch return error.OpeningDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (audio_client3) |_| {
|
if (!self.is_wine and audio_client3 != null) {
|
||||||
hr = audio_client3.?.InitializeSharedAudioStream(
|
hr = audio_client3.?.InitializeSharedAudioStream(
|
||||||
win32.AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
win32.AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||||
0,
|
0, // TODO: use the advantage of AudioClient3
|
||||||
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)),
|
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), &wave_format)),
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
@ -600,11 +598,11 @@ pub const Context = struct {
|
||||||
.ready_event = ready_event,
|
.ready_event = ready_event,
|
||||||
.aborted = .{ .value = false },
|
.aborted = .{ .value = false },
|
||||||
.is_paused = false,
|
.is_paused = false,
|
||||||
.sample_rate = sample_rate,
|
|
||||||
.writeFn = writeFn,
|
.writeFn = writeFn,
|
||||||
.user_data = options.user_data,
|
.user_data = options.user_data,
|
||||||
.channels = device.channels,
|
.channels = device.channels,
|
||||||
.format = format,
|
.format = format,
|
||||||
|
.sample_rate = sample_rate,
|
||||||
.write_step = format.frameSize(device.channels.len),
|
.write_step = format.frameSize(device.channels.len),
|
||||||
};
|
};
|
||||||
return .{ .wasapi = player };
|
return .{ .wasapi = player };
|
||||||
|
|
@ -658,16 +656,16 @@ pub const Player = struct {
|
||||||
audio_client: ?*win32.IAudioClient,
|
audio_client: ?*win32.IAudioClient,
|
||||||
audio_client3: ?*win32.IAudioClient3,
|
audio_client3: ?*win32.IAudioClient3,
|
||||||
render_client: ?*win32.IAudioRenderClient,
|
render_client: ?*win32.IAudioRenderClient,
|
||||||
ready_event: win32.HANDLE,
|
ready_event: *anyopaque,
|
||||||
aborted: std.atomic.Atomic(bool),
|
aborted: std.atomic.Atomic(bool),
|
||||||
is_paused: bool,
|
is_paused: bool,
|
||||||
sample_rate: u24,
|
|
||||||
writeFn: main.WriteFn,
|
writeFn: main.WriteFn,
|
||||||
user_data: ?*anyopaque,
|
user_data: ?*anyopaque,
|
||||||
|
|
||||||
write_step: u8,
|
|
||||||
channels: []main.Channel,
|
channels: []main.Channel,
|
||||||
format: main.Format,
|
format: main.Format,
|
||||||
|
sample_rate: u24,
|
||||||
|
write_step: u8,
|
||||||
|
|
||||||
pub fn deinit(self: *Player) void {
|
pub fn deinit(self: *Player) void {
|
||||||
self.aborted.store(true, .Unordered);
|
self.aborted.store(true, .Unordered);
|
||||||
|
|
@ -821,9 +819,6 @@ pub const Player = struct {
|
||||||
}
|
}
|
||||||
return vol;
|
return vol;
|
||||||
}
|
}
|
||||||
pub fn sampleRate(self: Player) u24 {
|
|
||||||
return self.sample_rate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn freeDevice(allocator: std.mem.Allocator, self: main.Device) void {
|
pub fn freeDevice(allocator: std.mem.Allocator, self: main.Device) void {
|
||||||
|
|
|
||||||
|
|
@ -222,11 +222,18 @@ pub extern "kernel32" fn CreateEventA(
|
||||||
bManualReset: BOOL,
|
bManualReset: BOOL,
|
||||||
bInitialState: BOOL,
|
bInitialState: BOOL,
|
||||||
lpName: ?[*:0]const u8,
|
lpName: ?[*:0]const u8,
|
||||||
) callconv(WINAPI) ?HANDLE;
|
) callconv(WINAPI) ?*anyopaque;
|
||||||
pub extern "kernel32" fn WaitForSingleObject(
|
pub extern "kernel32" fn WaitForSingleObject(
|
||||||
hHandle: ?HANDLE,
|
hHandle: ?*anyopaque,
|
||||||
dwMilliseconds: u32,
|
dwMilliseconds: u32,
|
||||||
) callconv(WINAPI) 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 INFINITE = 4294967295;
|
||||||
pub const SECURITY_ATTRIBUTES = extern struct {
|
pub const SECURITY_ATTRIBUTES = extern struct {
|
||||||
nLength: u32,
|
nLength: u32,
|
||||||
|
|
@ -1168,7 +1175,6 @@ pub const AUDCLNT_SHAREMODE = enum(i32) {
|
||||||
SHARED = 0,
|
SHARED = 0,
|
||||||
EXCLUSIVE = 1,
|
EXCLUSIVE = 1,
|
||||||
};
|
};
|
||||||
pub const HANDLE = @import("std").os.windows.HANDLE;
|
|
||||||
pub const IID_IAudioClient = &Guid.initString("1cb9ad4c-dbfa-4c32-b178-c2f568a703b2");
|
pub const IID_IAudioClient = &Guid.initString("1cb9ad4c-dbfa-4c32-b178-c2f568a703b2");
|
||||||
pub const IAudioClient = extern struct {
|
pub const IAudioClient = extern struct {
|
||||||
pub const VTable = extern struct {
|
pub const VTable = extern struct {
|
||||||
|
|
@ -1220,7 +1226,7 @@ pub const IAudioClient = extern struct {
|
||||||
) callconv(WINAPI) HRESULT,
|
) callconv(WINAPI) HRESULT,
|
||||||
SetEventHandle: *const fn (
|
SetEventHandle: *const fn (
|
||||||
self: *const IAudioClient,
|
self: *const IAudioClient,
|
||||||
eventHandle: ?HANDLE,
|
eventHandle: ?*anyopaque,
|
||||||
) callconv(WINAPI) HRESULT,
|
) callconv(WINAPI) HRESULT,
|
||||||
GetService: *const fn (
|
GetService: *const fn (
|
||||||
self: *const IAudioClient,
|
self: *const IAudioClient,
|
||||||
|
|
@ -1262,7 +1268,7 @@ pub const IAudioClient = extern struct {
|
||||||
pub inline fn Reset(self: *const T) HRESULT {
|
pub inline fn Reset(self: *const T) HRESULT {
|
||||||
return @ptrCast(*const IAudioClient.VTable, self.vtable).Reset(@ptrCast(*const IAudioClient, self));
|
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);
|
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 {
|
pub inline fn GetService(self: *const T, riid: ?*const Guid, ppv: ?*?*anyopaque) HRESULT {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue