From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winecoreaudio.drv/coreaudio.c | 52 ++++++++++++++++++------------ dlls/winecoreaudio.drv/mmdevdrv.c | 35 +++++++++++--------- dlls/winecoreaudio.drv/unixlib.h | 8 ++--- 3 files changed, 55 insertions(+), 40 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index 2a9dcde0675..dc67ccca376 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -72,6 +72,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
+#define MAX_DEV_NAME_LEN 10 /* Max 32 bit digits */ + struct coreaudio_stream { OSSpinLock lock; @@ -266,17 +268,20 @@ static NTSTATUS get_endpoint_ids(void *args) endpoint = params->endpoints;
for(i = 0; i < params->num; i++){ - SIZE_T len = CFStringGetLength(info[i].name); - needed += (len + 1) * sizeof(WCHAR); + const SIZE_T name_len = CFStringGetLength(info[i].name) + 1; + const SIZE_T device_len = MAX_DEV_NAME_LEN + 1; + needed += name_len * sizeof(WCHAR) + ((device_len + 1) & ~1);
if(needed <= params->size){ endpoint->name = offset; ptr = (UniChar *)((char *)params->endpoints + offset); - CFStringGetCharacters(info[i].name, CFRangeMake(0, len), ptr); - ptr[len] = 0; - endpoint->id = info[i].id; + CFStringGetCharacters(info[i].name, CFRangeMake(0, name_len - 1), ptr); + ptr[name_len - 1] = 0; + offset += name_len * sizeof(WCHAR); + endpoint->device = offset; + sprintf((char *)params->endpoints + offset, "%u", (unsigned int)info[i].id); + offset += (device_len + 1) & ~1; endpoint++; - offset += (len + 1) * sizeof(WCHAR); } CFRelease(info[i].name); if(info[i].id == default_id) params->default_idx = i; @@ -624,6 +629,11 @@ static ULONG_PTR zero_bits(void) #endif }
+static AudioDeviceID dev_id_from_device(const char *device) +{ + return strtoul(device, NULL, 10); +} + static NTSTATUS create_stream(void *args) { struct create_stream_params *params = args; @@ -645,7 +655,7 @@ static NTSTATUS create_stream(void *args)
stream->period_ms = params->period / 10000; stream->period_frames = muldiv(params->period, stream->fmt->nSamplesPerSec, 10000000); - stream->dev_id = params->dev_id; + stream->dev_id = dev_id_from_device(params->device); stream->flow = params->flow; stream->share = params->share;
@@ -903,6 +913,7 @@ static NTSTATUS get_mix_format(void *args) UInt32 size; OSStatus sc; int i; + const AudioDeviceID dev_id = dev_id_from_device(params->device);
params->fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
@@ -910,10 +921,10 @@ static NTSTATUS get_mix_format(void *args) addr.mElement = 0; addr.mSelector = kAudioDevicePropertyPreferredChannelLayout;
- sc = AudioObjectGetPropertyDataSize(params->dev_id, &addr, 0, NULL, &size); + sc = AudioObjectGetPropertyDataSize(dev_id, &addr, 0, NULL, &size); if(sc == noErr){ layout = malloc(size); - sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, layout); + sc = AudioObjectGetPropertyData(dev_id, &addr, 0, NULL, &size, layout); if(sc == noErr){ TRACE("Got channel layout: {tag: 0x%x, bitmap: 0x%x, num_descs: %u}\n", (unsigned int)layout->mChannelLayoutTag, (unsigned int)layout->mChannelBitmap, @@ -942,7 +953,7 @@ static NTSTATUS get_mix_format(void *args) addr.mElement = 0; addr.mSelector = kAudioDevicePropertyStreamConfiguration;
- sc = AudioObjectGetPropertyDataSize(params->dev_id, &addr, 0, NULL, &size); + sc = AudioObjectGetPropertyDataSize(dev_id, &addr, 0, NULL, &size); if(sc != noErr){ WARN("Unable to get size for _StreamConfiguration property: %x\n", (int)sc); params->result = osstatus_to_hresult(sc); @@ -955,7 +966,7 @@ static NTSTATUS get_mix_format(void *args) return STATUS_SUCCESS; }
- sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, buffers); + sc = AudioObjectGetPropertyData(dev_id, &addr, 0, NULL, &size, buffers); if(sc != noErr){ free(buffers); WARN("Unable to get _StreamConfiguration property: %x\n", (int)sc); @@ -973,7 +984,7 @@ static NTSTATUS get_mix_format(void *args)
addr.mSelector = kAudioDevicePropertyNominalSampleRate; size = sizeof(Float64); - sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, &rate); + sc = AudioObjectGetPropertyData(dev_id, &addr, 0, NULL, &size, &rate); if(sc != noErr){ WARN("Unable to get _NominalSampleRate property: %x\n", (int)sc); params->result = osstatus_to_hresult(sc); @@ -1002,6 +1013,7 @@ static NTSTATUS is_format_supported(void *args) AudioStreamBasicDescription dev_desc; AudioConverterRef converter; AudioComponentInstance unit; + const AudioDeviceID dev_id = dev_id_from_device(params->device);
params->result = S_OK;
@@ -1031,7 +1043,7 @@ static NTSTATUS is_format_supported(void *args) params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; return STATUS_SUCCESS; } - unit = get_audiounit(params->flow, params->dev_id); + unit = get_audiounit(params->flow, dev_id);
converter = NULL; params->result = ca_setup_audiounit(params->flow, unit, params->fmt_in, &dev_desc, &converter); @@ -1046,8 +1058,8 @@ unsupported: if(params->fmt_out){ struct get_mix_format_params get_mix_params = { + .device = params->device, .flow = params->flow, - .dev_id = params->dev_id, .fmt = params->fmt_out, };
@@ -1695,7 +1707,7 @@ static NTSTATUS wow64_create_stream(void *args) { struct { - DWORD dev_id; + PTR32 device; EDataFlow flow; AUDCLNT_SHAREMODE share; REFERENCE_TIME duration; @@ -1706,7 +1718,7 @@ static NTSTATUS wow64_create_stream(void *args) } *params32 = args; struct create_stream_params params = { - .dev_id = params32->dev_id, + .device = ULongToPtr(params32->device), .flow = params32->flow, .share = params32->share, .duration = params32->duration, @@ -1773,8 +1785,8 @@ static NTSTATUS wow64_is_format_supported(void *args) { struct { + PTR32 device; EDataFlow flow; - DWORD dev_id; AUDCLNT_SHAREMODE share; PTR32 fmt_in; PTR32 fmt_out; @@ -1782,8 +1794,8 @@ static NTSTATUS wow64_is_format_supported(void *args) } *params32 = args; struct is_format_supported_params params = { + .device = ULongToPtr(params32->device), .flow = params32->flow, - .dev_id = params32->dev_id, .share = params32->share, .fmt_in = ULongToPtr(params32->fmt_in), .fmt_out = ULongToPtr(params32->fmt_out) @@ -1797,15 +1809,15 @@ static NTSTATUS wow64_get_mix_format(void *args) { struct { + PTR32 device; EDataFlow flow; - DWORD dev_id; PTR32 fmt; HRESULT result; } *params32 = args; struct get_mix_format_params params = { + .device = ULongToPtr(params32->device), .flow = params32->flow, - .dev_id = params32->dev_id, .fmt = ULongToPtr(params32->fmt) }; get_mix_format(¶ms); diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 69b61781058..2d061db4e1b 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -97,7 +97,6 @@ struct ACImpl { HANDLE event; float *vols;
- DWORD dev_id; HANDLE timer;
AudioSession *session; @@ -105,6 +104,8 @@ struct ACImpl {
stream_handle stream; struct list entry; + + char device_name[1]; };
static const IAudioClient3Vtbl AudioClient3_Vtbl; @@ -261,7 +262,7 @@ exit: RegCloseKey(drv_key); }
-static void get_device_guid(EDataFlow flow, DWORD device_id, GUID *guid) +static void get_device_guid(EDataFlow flow, const char *dev, GUID *guid) { HKEY key = NULL, dev_key; DWORD type, size = sizeof(*guid); @@ -273,7 +274,7 @@ static void get_device_guid(EDataFlow flow, DWORD device_id, GUID *guid) key_name[0] = '0'; key_name[1] = ',';
- swprintf(key_name + 2, ARRAY_SIZE(key_name), L"%u", device_id); + MultiByteToWideChar(CP_UNIXCP, 0, dev, -1, key_name + 2, ARRAY_SIZE(key_name) - 2);
if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_WRITE|KEY_READ, &key) == ERROR_SUCCESS){ if(RegOpenKeyExW(key, key_name, 0, KEY_READ, &dev_key) == ERROR_SUCCESS){ @@ -341,8 +342,9 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, }
for(i = 0; i < params.num; i++){ - WCHAR *name = (WCHAR *)((char *)params.endpoints + params.endpoints[i].name); - int size = (wcslen(name) + 1) * sizeof(WCHAR); + const WCHAR *name = (WCHAR *)((char *)params.endpoints + params.endpoints[i].name); + const char *device = (char *)params.endpoints + params.endpoints[i].device; + const unsigned int size = (wcslen(name) + 1) * sizeof(WCHAR);
ids[i] = heap_alloc(size); if(!ids[i]){ @@ -350,7 +352,7 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, goto end; } memcpy(ids[i], name, size); - get_device_guid(flow, params.endpoints[i].id, guids + i); + get_device_guid(flow, device, guids + i); } *def_index = params.default_idx;
@@ -371,7 +373,7 @@ end: return params.result; }
-static BOOL get_deviceid_by_guid(GUID *guid, DWORD *id, EDataFlow *flow) +static BOOL get_device_name_by_guid(const GUID *guid, char *name, const SIZE_T name_size, EDataFlow *flow) { HKEY devices_key; UINT i = 0; @@ -416,7 +418,7 @@ static BOOL get_deviceid_by_guid(GUID *guid, DWORD *id, EDataFlow *flow) return FALSE; }
- *id = wcstoul(key_name + 2, NULL, 10); + WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, name, name_size, NULL, NULL);
return TRUE; } @@ -435,19 +437,21 @@ static BOOL get_deviceid_by_guid(GUID *guid, DWORD *id, EDataFlow *flow) HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient **out) { ACImpl *This; - DWORD dev_id; + char name[256]; + SIZE_T name_len; EDataFlow dataflow; HRESULT hr;
TRACE("%s %p %p\n", debugstr_guid(guid), dev, out);
- if(!get_deviceid_by_guid(guid, &dev_id, &dataflow)) + if(!get_device_name_by_guid(guid, name, sizeof(name), &dataflow)) return AUDCLNT_E_DEVICE_INVALIDATED;
if(dataflow != eRender && dataflow != eCapture) return E_INVALIDARG;
- This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl)); + name_len = strlen(name); + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, offsetof(ACImpl, device_name[name_len + 1])); if(!This) return E_OUTOFMEMORY;
@@ -459,6 +463,7 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient This->IAudioStreamVolume_iface.lpVtbl = &AudioStreamVolume_Vtbl;
This->dataflow = dataflow; + memcpy(This->device_name, name, name_len + 1);
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&This->IAudioClient3_iface, &This->pUnkFTMarshal); if (FAILED(hr)) { @@ -469,8 +474,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient This->parent = dev; IMMDevice_AddRef(This->parent);
- This->dev_id = dev_id; - *out = (IAudioClient *)&This->IAudioClient3_iface; IAudioClient3_AddRef(&This->IAudioClient3_iface);
@@ -731,7 +734,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, return AUDCLNT_E_ALREADY_INITIALIZED; }
- params.dev_id = This->dev_id; + params.device = This->device_name; params.flow = This->dataflow; params.share = mode; params.duration = duration; @@ -849,7 +852,7 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface, TRACE("(%p)->(%x, %p, %p)\n", This, mode, pwfx, outpwfx); if(pwfx) dump_fmt(pwfx);
- params.dev_id = This->dev_id; + params.device = This->device_name; params.flow = This->dataflow; params.share = mode; params.fmt_in = pwfx; @@ -882,7 +885,7 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, return E_POINTER; *pwfx = NULL;
- params.dev_id = This->dev_id; + params.device = This->device_name; params.flow = This->dataflow; params.fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); if(!params.fmt) diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h index 1c7dcebb52d..f0b78f610d3 100644 --- a/dlls/winecoreaudio.drv/unixlib.h +++ b/dlls/winecoreaudio.drv/unixlib.h @@ -24,7 +24,7 @@ typedef UINT64 stream_handle; struct endpoint { unsigned int name; - DWORD id; + unsigned int device; };
struct get_endpoint_ids_params @@ -39,7 +39,7 @@ struct get_endpoint_ids_params
struct create_stream_params { - DWORD dev_id; + const char *device; EDataFlow flow; AUDCLNT_SHAREMODE share; REFERENCE_TIME duration; @@ -109,16 +109,16 @@ struct release_capture_buffer_params
struct get_mix_format_params { + const char *device; EDataFlow flow; - DWORD dev_id; WAVEFORMATEXTENSIBLE *fmt; HRESULT result; };
struct is_format_supported_params { + const char *device; EDataFlow flow; - DWORD dev_id; AUDCLNT_SHAREMODE share; const WAVEFORMATEX *fmt_in; WAVEFORMATEXTENSIBLE *fmt_out;