mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 20:04:06 +00:00
winecoreaudio: Move get_endpoint_ids to a unixlib.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0e52d77f92
commit
c84923b200
|
@ -1,4 +1,5 @@
|
|||
MODULE = winecoreaudio.drv
|
||||
UNIXLIB = winecoreaudio.so
|
||||
IMPORTS = uuid ole32 user32 advapi32
|
||||
DELAYIMPORTS = winmm
|
||||
EXTRALIBS = $(COREAUDIO_LIBS)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/*
|
||||
* Wine Driver for CoreAudio
|
||||
* Unixlib for winecoreaudio driver.
|
||||
*
|
||||
* Copyright 2011 Andrew Eikum for CodeWeavers
|
||||
* Copyright 2021 Huw Davies
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,16 +18,230 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#pragma makedep unix
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define LoadResource __carbon_LoadResource
|
||||
#define CompareString __carbon_CompareString
|
||||
#define GetCurrentThread __carbon_GetCurrentThread
|
||||
#define GetCurrentProcess __carbon_GetCurrentProcess
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <fenv.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <AudioToolbox/AudioFormat.h>
|
||||
#include <AudioToolbox/AudioConverter.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#undef LoadResource
|
||||
#undef CompareString
|
||||
#undef GetCurrentThread
|
||||
#undef GetCurrentProcess
|
||||
#undef _CDECL
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "mmddk.h"
|
||||
#include "coreaudio.h"
|
||||
#include "winnls.h"
|
||||
#include "winreg.h"
|
||||
#include "mmdeviceapi.h"
|
||||
#include "initguid.h"
|
||||
#include "audioclient.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/unixlib.h"
|
||||
|
||||
#include "unixlib.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
|
||||
|
||||
static HRESULT osstatus_to_hresult(OSStatus sc)
|
||||
{
|
||||
switch(sc){
|
||||
case kAudioFormatUnsupportedDataFormatError:
|
||||
case kAudioFormatUnknownFormatError:
|
||||
case kAudioDeviceUnsupportedFormatError:
|
||||
return AUDCLNT_E_UNSUPPORTED_FORMAT;
|
||||
case kAudioHardwareBadDeviceError:
|
||||
return AUDCLNT_E_DEVICE_INVALIDATED;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static AudioObjectPropertyScope get_scope(EDataFlow flow)
|
||||
{
|
||||
return (flow == eRender) ? kAudioDevicePropertyScopeOutput : kAudioDevicePropertyScopeInput;
|
||||
}
|
||||
|
||||
static BOOL device_has_channels(AudioDeviceID device, EDataFlow flow)
|
||||
{
|
||||
AudioObjectPropertyAddress addr;
|
||||
AudioBufferList *buffers;
|
||||
BOOL ret = FALSE;
|
||||
OSStatus sc;
|
||||
UInt32 size;
|
||||
int i;
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||
addr.mScope = get_scope(flow);
|
||||
addr.mElement = 0;
|
||||
|
||||
sc = AudioObjectGetPropertyDataSize(device, &addr, 0, NULL, &size);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _StreamConfiguration property size for device %u: %x\n",
|
||||
(unsigned int)device, (int)sc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buffers = malloc(size);
|
||||
if(!buffers) return FALSE;
|
||||
|
||||
sc = AudioObjectGetPropertyData(device, &addr, 0, NULL, &size, buffers);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _StreamConfiguration property for device %u: %x\n",
|
||||
(unsigned int)device, (int)sc);
|
||||
free(buffers);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for(i = 0; i < buffers->mNumberBuffers; i++){
|
||||
if(buffers->mBuffers[i].mNumberChannels > 0){
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buffers);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static NTSTATUS get_endpoint_ids(void *args)
|
||||
{
|
||||
struct get_endpoint_ids_params *params = args;
|
||||
unsigned int num_devices, i, needed;
|
||||
AudioDeviceID *devices, default_id;
|
||||
AudioObjectPropertyAddress addr;
|
||||
struct endpoint *endpoint;
|
||||
UInt32 devsize, size;
|
||||
struct endpoint_info
|
||||
{
|
||||
CFStringRef name;
|
||||
AudioDeviceID id;
|
||||
} *info;
|
||||
OSStatus sc;
|
||||
WCHAR *ptr;
|
||||
|
||||
params->num = 0;
|
||||
params->default_idx = 0;
|
||||
|
||||
addr.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
addr.mElement = kAudioObjectPropertyElementMaster;
|
||||
if(params->flow == eRender) addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
else if(params->flow == eCapture) addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
else{
|
||||
params->result = E_INVALIDARG;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
size = sizeof(default_id);
|
||||
sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, &default_id);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _DefaultInputDevice property failed: %x\n", (int)sc);
|
||||
default_id = -1;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioHardwarePropertyDevices;
|
||||
sc = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0, NULL, &devsize);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _Devices property size failed: %x\n", (int)sc);
|
||||
params->result = osstatus_to_hresult(sc);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
num_devices = devsize / sizeof(AudioDeviceID);
|
||||
devices = malloc(devsize);
|
||||
info = malloc(num_devices * sizeof(*info));
|
||||
if(!devices || !info){
|
||||
free(info);
|
||||
free(devices);
|
||||
params->result = E_OUTOFMEMORY;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &devsize, devices);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _Devices property failed: %x\n", (int)sc);
|
||||
free(info);
|
||||
free(devices);
|
||||
params->result = osstatus_to_hresult(sc);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioObjectPropertyName;
|
||||
addr.mScope = get_scope(params->flow);
|
||||
addr.mElement = 0;
|
||||
|
||||
for(i = 0; i < num_devices; i++){
|
||||
if(!device_has_channels(devices[i], params->flow)) continue;
|
||||
|
||||
size = sizeof(CFStringRef);
|
||||
sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL, &size, &info[params->num].name);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _Name property for device %u: %x\n",
|
||||
(unsigned int)devices[i], (int)sc);
|
||||
continue;
|
||||
}
|
||||
info[params->num++].id = devices[i];
|
||||
}
|
||||
free(devices);
|
||||
|
||||
needed = sizeof(*endpoint) * params->num;
|
||||
endpoint = params->endpoints;
|
||||
ptr = (WCHAR *)(endpoint + params->num);
|
||||
|
||||
for(i = 0; i < params->num; i++){
|
||||
SIZE_T len = CFStringGetLength(info[i].name);
|
||||
needed += (len + 1) * sizeof(WCHAR);
|
||||
|
||||
if(needed <= params->size){
|
||||
endpoint->name = ptr;
|
||||
CFStringGetCharacters(info[i].name, CFRangeMake(0, len), (UniChar*)endpoint->name);
|
||||
ptr[len] = 0;
|
||||
endpoint->id = info[i].id;
|
||||
endpoint++;
|
||||
ptr += len + 1;
|
||||
}
|
||||
CFRelease(info[i].name);
|
||||
if(info[i].id == default_id) params->default_idx = i;
|
||||
}
|
||||
free(info);
|
||||
|
||||
if(needed > params->size){
|
||||
params->size = needed;
|
||||
params->result = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
else params->result = S_OK;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
unixlib_entry_t __wine_unix_call_funcs[] =
|
||||
{
|
||||
get_endpoint_ids,
|
||||
};
|
||||
|
|
|
@ -56,8 +56,10 @@
|
|||
#include "winnls.h"
|
||||
#include "winreg.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/unixlib.h"
|
||||
|
||||
#include "ole2.h"
|
||||
#include "mmdeviceapi.h"
|
||||
|
@ -69,9 +71,12 @@
|
|||
#include "endpointvolume.h"
|
||||
#include "audioclient.h"
|
||||
#include "audiopolicy.h"
|
||||
#include "unixlib.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
|
||||
|
||||
unixlib_handle_t coreaudio_handle = 0;
|
||||
|
||||
#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
|
||||
|
||||
static const REFERENCE_TIME DefaultPeriod = 100000;
|
||||
|
@ -245,6 +250,9 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
|
|||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
if(NtQueryVirtualMemory(GetCurrentProcess(), dll, MemoryWineUnixFuncs,
|
||||
&coreaudio_handle, sizeof(coreaudio_handle), NULL))
|
||||
return FALSE;
|
||||
g_timer_q = CreateTimerQueue();
|
||||
if(!g_timer_q)
|
||||
return FALSE;
|
||||
|
@ -319,7 +327,7 @@ exit:
|
|||
RegCloseKey(drv_key);
|
||||
}
|
||||
|
||||
static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
|
||||
static void get_device_guid(EDataFlow flow, DWORD device_id, GUID *guid)
|
||||
{
|
||||
HKEY key = NULL, dev_key;
|
||||
DWORD type, size = sizeof(*guid);
|
||||
|
@ -333,7 +341,7 @@ static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
|
|||
key_name[0] = '0';
|
||||
key_name[1] = ',';
|
||||
|
||||
sprintfW(key_name + 2, key_fmt, device);
|
||||
sprintfW(key_name + 2, key_fmt, device_id);
|
||||
|
||||
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){
|
||||
|
@ -359,164 +367,61 @@ static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
|
|||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids,
|
||||
GUID **guids, UINT *num, UINT *def_index)
|
||||
HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out,
|
||||
GUID **guids_out, UINT *num, UINT *def_index)
|
||||
{
|
||||
UInt32 devsize, size;
|
||||
AudioDeviceID *devices;
|
||||
AudioDeviceID default_id;
|
||||
AudioObjectPropertyAddress addr;
|
||||
OSStatus sc;
|
||||
int i, ndevices;
|
||||
struct get_endpoint_ids_params params;
|
||||
unsigned int i;
|
||||
GUID *guids;
|
||||
WCHAR **ids;
|
||||
|
||||
TRACE("%d %p %p %p\n", flow, ids, num, def_index);
|
||||
TRACE("%d %p %p %p\n", flow, ids_out, num, def_index);
|
||||
|
||||
addr.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
addr.mElement = kAudioObjectPropertyElementMaster;
|
||||
if(flow == eRender)
|
||||
addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||
else if(flow == eCapture)
|
||||
addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
params.flow = flow;
|
||||
params.size = 1000;
|
||||
params.endpoints = NULL;
|
||||
do{
|
||||
heap_free(params.endpoints);
|
||||
params.endpoints = heap_alloc(params.size);
|
||||
UNIX_CALL(get_endpoint_ids, ¶ms);
|
||||
}while(params.result == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
|
||||
|
||||
size = sizeof(default_id);
|
||||
sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0,
|
||||
NULL, &size, &default_id);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _DefaultInputDevice property failed: %x\n", (int)sc);
|
||||
default_id = -1;
|
||||
if(FAILED(params.result)) goto end;
|
||||
|
||||
ids = heap_alloc_zero(params.num * sizeof(*ids));
|
||||
guids = heap_alloc(params.num * sizeof(*guids));
|
||||
if(!ids || !guids){
|
||||
params.result = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
addr.mSelector = kAudioHardwarePropertyDevices;
|
||||
sc = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0,
|
||||
NULL, &devsize);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _Devices property size failed: %x\n", (int)sc);
|
||||
return osstatus_to_hresult(sc);
|
||||
for(i = 0; i < params.num; i++){
|
||||
int size = (strlenW(params.endpoints[i].name) + 1) * sizeof(WCHAR);
|
||||
ids[i] = heap_alloc(size);
|
||||
if(!ids[i]){
|
||||
params.result = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
memcpy(ids[i], params.endpoints[i].name, size);
|
||||
get_device_guid(flow, params.endpoints[i].id, guids + i);
|
||||
}
|
||||
*def_index = params.default_idx;
|
||||
|
||||
end:
|
||||
heap_free(params.endpoints);
|
||||
if(FAILED(params.result)){
|
||||
heap_free(guids);
|
||||
if(ids){
|
||||
for(i = 0; i < params.num; i++) heap_free(ids[i]);
|
||||
heap_free(ids);
|
||||
}
|
||||
}else{
|
||||
*ids_out = ids;
|
||||
*guids_out = guids;
|
||||
*num = params.num;
|
||||
}
|
||||
|
||||
devices = HeapAlloc(GetProcessHeap(), 0, devsize);
|
||||
if(!devices)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL,
|
||||
&devsize, devices);
|
||||
if(sc != noErr){
|
||||
WARN("Getting _Devices property failed: %x\n", (int)sc);
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
return osstatus_to_hresult(sc);
|
||||
}
|
||||
|
||||
ndevices = devsize / sizeof(AudioDeviceID);
|
||||
|
||||
*ids = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(WCHAR *));
|
||||
if(!*ids){
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*guids = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(GUID));
|
||||
if(!*guids){
|
||||
HeapFree(GetProcessHeap(), 0, *ids);
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*num = 0;
|
||||
*def_index = (UINT)-1;
|
||||
for(i = 0; i < ndevices; ++i){
|
||||
AudioBufferList *buffers;
|
||||
CFStringRef name;
|
||||
SIZE_T len;
|
||||
int j;
|
||||
|
||||
addr.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||
if(flow == eRender)
|
||||
addr.mScope = kAudioDevicePropertyScopeOutput;
|
||||
else
|
||||
addr.mScope = kAudioDevicePropertyScopeInput;
|
||||
addr.mElement = 0;
|
||||
sc = AudioObjectGetPropertyDataSize(devices[i], &addr, 0, NULL, &size);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _StreamConfiguration property size for "
|
||||
"device %u: %x\n", (unsigned int)devices[i], (int)sc);
|
||||
continue;
|
||||
}
|
||||
|
||||
buffers = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if(!buffers){
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
for(j = 0; j < *num; ++j)
|
||||
HeapFree(GetProcessHeap(), 0, (*ids)[j]);
|
||||
HeapFree(GetProcessHeap(), 0, *guids);
|
||||
HeapFree(GetProcessHeap(), 0, *ids);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
|
||||
&size, buffers);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _StreamConfiguration property for "
|
||||
"device %u: %x\n", (unsigned int)devices[i], (int)sc);
|
||||
HeapFree(GetProcessHeap(), 0, buffers);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check that there's at least one channel in this device before
|
||||
* we claim it as usable */
|
||||
for(j = 0; j < buffers->mNumberBuffers; ++j)
|
||||
if(buffers->mBuffers[j].mNumberChannels > 0)
|
||||
break;
|
||||
if(j >= buffers->mNumberBuffers){
|
||||
HeapFree(GetProcessHeap(), 0, buffers);
|
||||
continue;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, buffers);
|
||||
|
||||
size = sizeof(name);
|
||||
addr.mSelector = kAudioObjectPropertyName;
|
||||
sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
|
||||
&size, &name);
|
||||
if(sc != noErr){
|
||||
WARN("Unable to get _Name property for device %u: %x\n",
|
||||
(unsigned int)devices[i], (int)sc);
|
||||
continue;
|
||||
}
|
||||
|
||||
len = CFStringGetLength(name) + 1;
|
||||
(*ids)[*num] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
if(!(*ids)[*num]){
|
||||
CFRelease(name);
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
for(j = 0; j < *num; ++j)
|
||||
HeapFree(GetProcessHeap(), 0, (*ids)[j]);
|
||||
HeapFree(GetProcessHeap(), 0, *ids);
|
||||
HeapFree(GetProcessHeap(), 0, *guids);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
CFStringGetCharacters(name, CFRangeMake(0, len - 1), (UniChar*)(*ids)[*num]);
|
||||
((*ids)[*num])[len - 1] = 0;
|
||||
CFRelease(name);
|
||||
|
||||
get_device_guid(flow, devices[i], &(*guids)[*num]);
|
||||
|
||||
if(*def_index == (UINT)-1 && devices[i] == default_id)
|
||||
*def_index = *num;
|
||||
|
||||
TRACE("device %u: id %s key %u%s\n", *num, debugstr_w((*ids)[*num]),
|
||||
(unsigned int)devices[i], (*def_index == *num) ? " (default)" : "");
|
||||
|
||||
(*num)++;
|
||||
}
|
||||
|
||||
if(*def_index == (UINT)-1)
|
||||
*def_index = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, devices);
|
||||
|
||||
return S_OK;
|
||||
return params.result;
|
||||
}
|
||||
|
||||
static BOOL get_deviceid_by_guid(GUID *guid, AudioDeviceID *id, EDataFlow *flow)
|
||||
|
|
44
dlls/winecoreaudio.drv/unixlib.h
Normal file
44
dlls/winecoreaudio.drv/unixlib.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Unixlib header file for winecoreaudio driver.
|
||||
*
|
||||
* Copyright 2021 Huw Davies
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
struct endpoint
|
||||
{
|
||||
WCHAR *name;
|
||||
DWORD id;
|
||||
};
|
||||
|
||||
struct get_endpoint_ids_params
|
||||
{
|
||||
EDataFlow flow;
|
||||
struct endpoint *endpoints;
|
||||
unsigned int size;
|
||||
HRESULT result;
|
||||
unsigned int num;
|
||||
unsigned int default_idx;
|
||||
};
|
||||
|
||||
enum unix_funcs
|
||||
{
|
||||
unix_get_endpoint_ids,
|
||||
};
|
||||
|
||||
extern unixlib_handle_t coreaudio_handle;
|
||||
|
||||
#define UNIX_CALL( func, params ) __wine_unix_call( coreaudio_handle, unix_ ## func, params )
|
Loading…
Reference in a new issue