Commit 0625d439 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

winealsa.drv: Only report endpoints for "default" if they can be opened.

The default device may for example be a set of USB speakers or an USB microphone, in which case you'd have just an output or just an input respectively.
parent e7728c41
...@@ -237,15 +237,28 @@ int WINAPI AUDDRV_GetPriority(void) ...@@ -237,15 +237,28 @@ int WINAPI AUDDRV_GetPriority(void)
return Priority_Neutral; return Priority_Neutral;
} }
static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys, static BOOL alsa_try_open(const char *devnode, snd_pcm_stream_t stream)
{
snd_pcm_t *handle;
int err;
if((err = snd_pcm_open(&handle, devnode, stream, SND_PCM_NONBLOCK)) < 0){
WARN("The device \"%s\" failed to open: %d (%s).\n",
devnode, err, snd_strerror(err));
return FALSE;
}
snd_pcm_close(handle);
return TRUE;
}
static HRESULT alsa_get_card_devices(snd_pcm_stream_t stream, WCHAR **ids, char **keys,
UINT *num, snd_ctl_t *ctl, int card, const WCHAR *cardnameW, UINT *num, snd_ctl_t *ctl, int card, const WCHAR *cardnameW,
BOOL count_failed) BOOL count_failed)
{ {
static const WCHAR dashW[] = {' ','-',' ',0}; static const WCHAR dashW[] = {' ','-',' ',0};
int err, device; int err, device;
snd_pcm_info_t *info; snd_pcm_info_t *info;
snd_pcm_stream_t stream = (flow == eRender ? SND_PCM_STREAM_PLAYBACK :
SND_PCM_STREAM_CAPTURE);
info = HeapAlloc(GetProcessHeap(), 0, snd_pcm_info_sizeof()); info = HeapAlloc(GetProcessHeap(), 0, snd_pcm_info_sizeof());
if(!info) if(!info)
...@@ -259,7 +272,6 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys, ...@@ -259,7 +272,6 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys,
err = snd_ctl_pcm_next_device(ctl, &device)){ err = snd_ctl_pcm_next_device(ctl, &device)){
const char *devname; const char *devname;
char devnode[32]; char devnode[32];
snd_pcm_t *handle;
snd_pcm_info_set_device(info, device); snd_pcm_info_set_device(info, device);
...@@ -274,16 +286,12 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys, ...@@ -274,16 +286,12 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys,
} }
sprintf(devnode, "hw:%d,%d", card, device); sprintf(devnode, "hw:%d,%d", card, device);
if((err = snd_pcm_open(&handle, devnode, stream, SND_PCM_NONBLOCK)) < 0){ if(!alsa_try_open(devnode, stream)){
WARN("The device \"%s\" failed to open, pretending it doesn't exist: %d (%s)\n",
devnode, err, snd_strerror(err));
if(count_failed) if(count_failed)
++(*num); ++(*num);
continue; continue;
} }
snd_pcm_close(handle);
if(ids && keys){ if(ids && keys){
DWORD len, cardlen; DWORD len, cardlen;
...@@ -333,10 +341,24 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys, ...@@ -333,10 +341,24 @@ static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys,
static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR **ids, char **keys, static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR **ids, char **keys,
UINT *num, BOOL count_failed) UINT *num, BOOL count_failed)
{ {
snd_pcm_stream_t stream = (flow == eRender ? SND_PCM_STREAM_PLAYBACK :
SND_PCM_STREAM_CAPTURE);
int err, card; int err, card;
card = -1; card = -1;
*num = 0; *num = 0;
if(alsa_try_open(defname, stream)){
if(ids && keys){
*ids = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
memcpy(*ids, defaultW, sizeof(defaultW));
*keys = HeapAlloc(GetProcessHeap(), 0, sizeof(defname));
memcpy(*keys, defname, sizeof(defname));
}
++*num;
}else if(count_failed)
++*num;
for(err = snd_card_next(&card); card != -1 && err >= 0; for(err = snd_card_next(&card); card != -1 && err >= 0;
err = snd_card_next(&card)){ err = snd_card_next(&card)){
char cardpath[64]; char cardpath[64];
...@@ -368,7 +390,7 @@ static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR **ids, char **keys, ...@@ -368,7 +390,7 @@ static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR **ids, char **keys,
} }
MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, cardnameW, len); MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, cardnameW, len);
alsa_get_card_devices(flow, ids, keys, num, ctl, card, cardnameW, alsa_get_card_devices(stream, ids, keys, num, ctl, card, cardnameW,
count_failed); count_failed);
HeapFree(GetProcessHeap(), 0, cardnameW); HeapFree(GetProcessHeap(), 0, cardnameW);
...@@ -401,21 +423,17 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, char ***keys, ...@@ -401,21 +423,17 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, char ***keys,
return S_OK; return S_OK;
} }
*ids = HeapAlloc(GetProcessHeap(), 0, (*num + 1) * sizeof(WCHAR *)); *ids = HeapAlloc(GetProcessHeap(), 0, *num * sizeof(WCHAR *));
*keys = HeapAlloc(GetProcessHeap(), 0, (*num + 1) * sizeof(char *)); *keys = HeapAlloc(GetProcessHeap(), 0, *num * sizeof(char *));
if(!*ids || !*keys){ if(!*ids || !*keys){
HeapFree(GetProcessHeap(), 0, *ids); HeapFree(GetProcessHeap(), 0, *ids);
HeapFree(GetProcessHeap(), 0, *keys); HeapFree(GetProcessHeap(), 0, *keys);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
(*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
memcpy((*ids)[0], defaultW, sizeof(defaultW));
(*keys)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defname));
memcpy((*keys)[0], defname, sizeof(defname));
*def_index = 0; *def_index = 0;
hr = alsa_enum_devices(flow, (*ids) + 1, (*keys) + 1, num, FALSE); hr = alsa_enum_devices(flow, *ids, *keys, num, FALSE);
if(FAILED(hr)){ if(FAILED(hr)){
int i; int i;
for(i = 0; i < *num; ++i){ for(i = 0; i < *num; ++i){
...@@ -427,8 +445,6 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, char ***keys, ...@@ -427,8 +445,6 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, char ***keys,
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
++(*num); /* for default device */
return S_OK; return S_OK;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment