Use a vector for mmdevapi device lists
This commit is contained in:
parent
83970369e0
commit
28e9f0db8c
@ -80,11 +80,24 @@ typedef struct {
|
||||
al_string name;
|
||||
WCHAR *devid;
|
||||
} DevMap;
|
||||
DECL_VECTOR(DevMap)
|
||||
|
||||
static DevMap *PlaybackDeviceList;
|
||||
static ALuint NumPlaybackDevices;
|
||||
static DevMap *CaptureDeviceList;
|
||||
static ALuint NumCaptureDevices;
|
||||
static void clear_devlist(vector_DevMap *list)
|
||||
{
|
||||
DevMap *iter, *end;
|
||||
|
||||
iter = VECTOR_ITER_BEGIN(*list);
|
||||
end = VECTOR_ITER_END(*list);
|
||||
for(;iter != end;iter++)
|
||||
{
|
||||
AL_STRING_DEINIT(iter->name);
|
||||
free(iter->devid);
|
||||
}
|
||||
VECTOR_RESIZE(*list, 0);
|
||||
}
|
||||
|
||||
static vector_DevMap PlaybackDevices;
|
||||
static vector_DevMap CaptureDevices;
|
||||
|
||||
|
||||
static HANDLE ThreadHdl;
|
||||
@ -144,58 +157,58 @@ static void get_device_name(IMMDevice *device, al_string *name)
|
||||
IPropertyStore_Release(ps);
|
||||
}
|
||||
|
||||
static void add_device(IMMDevice *device, DevMap *devmap)
|
||||
static void add_device(IMMDevice *device, vector_DevMap *list)
|
||||
{
|
||||
LPWSTR devid;
|
||||
HRESULT hr;
|
||||
|
||||
AL_STRING_INIT(devmap->name);
|
||||
|
||||
hr = IMMDevice_GetId(device, &devid);
|
||||
if(FAILED(hr))
|
||||
devmap->devid = calloc(sizeof(WCHAR), 1);
|
||||
else
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
devmap->devid = strdupW(devid);
|
||||
get_device_name(device, &devmap->name);
|
||||
TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(devmap->name), devmap->devid);
|
||||
DevMap entry;
|
||||
AL_STRING_INIT(entry.name);
|
||||
|
||||
entry.devid = strdupW(devid);
|
||||
get_device_name(device, &entry.name);
|
||||
|
||||
CoTaskMemFree(devid);
|
||||
|
||||
TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid);
|
||||
VECTOR_PUSH_BACK(*list, entry);
|
||||
}
|
||||
}
|
||||
|
||||
static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs)
|
||||
static HRESULT ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
|
||||
{
|
||||
IMMDeviceCollection *coll;
|
||||
IMMDevice *defdev = NULL;
|
||||
DevMap *devlist = NULL;
|
||||
HRESULT hr;
|
||||
UINT count;
|
||||
UINT idx;
|
||||
UINT i;
|
||||
|
||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr);
|
||||
return NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
idx = count = 0;
|
||||
count = 0;
|
||||
hr = IMMDeviceCollection_GetCount(coll, &count);
|
||||
if(SUCCEEDED(hr) && count > 0)
|
||||
{
|
||||
devlist = calloc(count+1, sizeof(*devlist));
|
||||
if(!devlist)
|
||||
clear_devlist(list);
|
||||
if(!VECTOR_RESERVE(*list, count+1))
|
||||
{
|
||||
IMMDeviceCollection_Release(coll);
|
||||
return NULL;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir,
|
||||
eMultimedia, &defdev);
|
||||
}
|
||||
if(SUCCEEDED(hr) && defdev != NULL)
|
||||
add_device(defdev, &devlist[idx++]);
|
||||
add_device(defdev, list);
|
||||
|
||||
for(i = 0;i < count;++i)
|
||||
{
|
||||
@ -205,7 +218,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu
|
||||
continue;
|
||||
|
||||
if(device != defdev)
|
||||
add_device(device, &devlist[idx++]);
|
||||
add_device(device, list);
|
||||
|
||||
IMMDevice_Release(device);
|
||||
}
|
||||
@ -213,8 +226,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu
|
||||
if(defdev) IMMDevice_Release(defdev);
|
||||
IMMDeviceCollection_Release(coll);
|
||||
|
||||
*numdevs = idx;
|
||||
return devlist;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -623,8 +635,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
||||
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
||||
|
||||
TRACE("Message thread initialization complete\n");
|
||||
req->result = S_OK;
|
||||
SetEvent(req->FinishedEvt);
|
||||
ReturnMsgResponse(req, S_OK);
|
||||
|
||||
TRACE("Starting message loop\n");
|
||||
while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last))
|
||||
@ -759,35 +770,12 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
||||
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
EDataFlow flowdir;
|
||||
DevMap **devlist;
|
||||
ALuint *numdevs;
|
||||
ALuint i;
|
||||
|
||||
Enumerator = ptr;
|
||||
if(msg.lParam == CAPTURE_DEVICE_PROBE)
|
||||
{
|
||||
flowdir = eCapture;
|
||||
devlist = &CaptureDeviceList;
|
||||
numdevs = &NumCaptureDevices;
|
||||
}
|
||||
else
|
||||
{
|
||||
flowdir = eRender;
|
||||
devlist = &PlaybackDeviceList;
|
||||
numdevs = &NumPlaybackDevices;
|
||||
}
|
||||
|
||||
for(i = 0;i < *numdevs;i++)
|
||||
{
|
||||
AL_STRING_DEINIT((*devlist)[i].name);
|
||||
free((*devlist)[i].devid);
|
||||
}
|
||||
free(*devlist);
|
||||
*devlist = NULL;
|
||||
*numdevs = 0;
|
||||
|
||||
*devlist = ProbeDevices(Enumerator, flowdir, numdevs);
|
||||
if(msg.lParam == ALL_DEVICE_PROBE)
|
||||
hr = ProbeDevices(Enumerator, eRender, &PlaybackDevices);
|
||||
else if(msg.lParam == CAPTURE_DEVICE_PROBE)
|
||||
hr = ProbeDevices(Enumerator, eCapture, &CaptureDevices);
|
||||
|
||||
IMMDeviceEnumerator_Release(Enumerator);
|
||||
Enumerator = NULL;
|
||||
@ -796,7 +784,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
||||
if(--deviceCount == 0 && SUCCEEDED(cohr))
|
||||
CoUninitialize();
|
||||
|
||||
ReturnMsgResponse(req, S_OK);
|
||||
ReturnMsgResponse(req, hr);
|
||||
continue;
|
||||
|
||||
default:
|
||||
@ -857,9 +845,9 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
|
||||
{
|
||||
if(deviceName)
|
||||
{
|
||||
ALuint i;
|
||||
const DevMap *iter, *end;
|
||||
|
||||
if(!PlaybackDeviceList)
|
||||
if(VECTOR_SIZE(PlaybackDevices) == 0)
|
||||
{
|
||||
ThreadRequest req = { data->MsgEvent, 0 };
|
||||
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
|
||||
@ -867,11 +855,13 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
|
||||
}
|
||||
|
||||
hr = E_FAIL;
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
iter = VECTOR_ITER_BEGIN(PlaybackDevices);
|
||||
end = VECTOR_ITER_END(PlaybackDevices);
|
||||
for(;iter != end;iter++)
|
||||
{
|
||||
if(al_string_cmp_cstr(PlaybackDeviceList[i].name, deviceName) == 0)
|
||||
if(al_string_cmp_cstr(iter->name, deviceName) == 0)
|
||||
{
|
||||
data->devid = strdupW(PlaybackDeviceList[i].devid);
|
||||
data->devid = strdupW(iter->devid);
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
@ -995,6 +985,9 @@ static const BackendFuncs MMDevApiFuncs = {
|
||||
|
||||
ALCboolean alcMMDevApiInit(BackendFuncs *FuncList)
|
||||
{
|
||||
VECTOR_INIT(PlaybackDevices);
|
||||
VECTOR_INIT(CaptureDevices);
|
||||
|
||||
if(!MMDevApiLoad())
|
||||
return ALC_FALSE;
|
||||
*FuncList = MMDevApiFuncs;
|
||||
@ -1003,25 +996,11 @@ ALCboolean alcMMDevApiInit(BackendFuncs *FuncList)
|
||||
|
||||
void alcMMDevApiDeinit(void)
|
||||
{
|
||||
ALuint i;
|
||||
clear_devlist(&PlaybackDevices);
|
||||
VECTOR_DEINIT(PlaybackDevices);
|
||||
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
AL_STRING_DEINIT(PlaybackDeviceList[i].name);
|
||||
free(PlaybackDeviceList[i].devid);
|
||||
}
|
||||
free(PlaybackDeviceList);
|
||||
PlaybackDeviceList = NULL;
|
||||
NumPlaybackDevices = 0;
|
||||
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
AL_STRING_DEINIT(CaptureDeviceList[i].name);
|
||||
free(CaptureDeviceList[i].devid);
|
||||
}
|
||||
free(CaptureDeviceList);
|
||||
CaptureDeviceList = NULL;
|
||||
NumCaptureDevices = 0;
|
||||
clear_devlist(&CaptureDevices);
|
||||
VECTOR_DEINIT(CaptureDevices);
|
||||
|
||||
if(ThreadHdl)
|
||||
{
|
||||
@ -1035,28 +1014,33 @@ void alcMMDevApiDeinit(void)
|
||||
void alcMMDevApiProbe(enum DevProbe type)
|
||||
{
|
||||
ThreadRequest req = { NULL, 0 };
|
||||
const DevMap *iter, *end;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
switch(type)
|
||||
req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(req.FinishedEvt == NULL)
|
||||
ERR("Failed to create event: %lu\n", GetLastError());
|
||||
else
|
||||
{
|
||||
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
|
||||
hr = WaitForResponse(&req);
|
||||
if(SUCCEEDED(hr)) switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(req.FinishedEvt == NULL)
|
||||
ERR("Failed to create event: %lu\n", GetLastError());
|
||||
else if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
|
||||
hr = WaitForResponse(&req);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
ALuint i;
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
AppendAllDevicesList(al_string_get_cstr(PlaybackDeviceList[i].name));
|
||||
}
|
||||
iter = VECTOR_ITER_BEGIN(PlaybackDevices);
|
||||
end = VECTOR_ITER_END(PlaybackDevices);
|
||||
for(;iter != end;iter++)
|
||||
AppendAllDevicesList(al_string_get_cstr(iter->name));
|
||||
break;
|
||||
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
iter = VECTOR_ITER_BEGIN(CaptureDevices);
|
||||
end = VECTOR_ITER_END(CaptureDevices);
|
||||
for(;iter != end;iter++)
|
||||
AppendCaptureDeviceList(al_string_get_cstr(iter->name));
|
||||
break;
|
||||
}
|
||||
if(req.FinishedEvt != NULL)
|
||||
}
|
||||
CloseHandle(req.FinishedEvt);
|
||||
req.FinishedEvt = NULL;
|
||||
req.FinishedEvt = NULL;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user