From e5d60d9f04c284e286dc0774e192bc7ccce1830f Mon Sep 17 00:00:00 2001 From: Les De Ridder Date: Mon, 16 Jan 2017 02:27:49 +0100 Subject: [PATCH] Use ALSA device hints instead of enumerating normally --- dlls/winealsa.drv/mmdevdrv.c | 172 +++++++++++++------------------------------ 1 file changed, 52 insertions(+), 120 deletions(-) diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 2ecb111..6a090ea 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -160,9 +160,6 @@ static CRITICAL_SECTION_DEBUG g_sessions_lock_debug = static CRITICAL_SECTION g_sessions_lock = { &g_sessions_lock_debug, -1, 0, 0, 0, 0 }; static struct list g_sessions = LIST_INIT(g_sessions); -static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; -static const char defname[] = "default"; - static const WCHAR drv_keyW[] = {'S','o','f','t','w','a','r','e','\\', 'W','i','n','e','\\','D','r','i','v','e','r','s','\\', 'w','i','n','e','a','l','s','a','.','d','r','v',0}; @@ -407,72 +404,6 @@ static WCHAR *construct_device_id(EDataFlow flow, const WCHAR *chunk1, const cha return ret; } -static HRESULT alsa_get_card_devices(EDataFlow flow, snd_pcm_stream_t stream, - WCHAR ***ids, GUID **guids, UINT *num, snd_ctl_t *ctl, int card, - const WCHAR *cardnameW) -{ - int err, device; - snd_pcm_info_t *info; - - info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_info_sizeof()); - if(!info) - return E_OUTOFMEMORY; - - snd_pcm_info_set_subdevice(info, 0); - snd_pcm_info_set_stream(info, stream); - - device = -1; - for(err = snd_ctl_pcm_next_device(ctl, &device); device != -1 && err >= 0; - err = snd_ctl_pcm_next_device(ctl, &device)){ - const char *devname; - char devnode[32]; - - snd_pcm_info_set_device(info, device); - - if((err = snd_ctl_pcm_info(ctl, info)) < 0){ - if(err == -ENOENT) - /* This device doesn't have the right stream direction */ - continue; - - WARN("Failed to get info for card %d, device %d: %d (%s)\n", - card, device, err, snd_strerror(err)); - continue; - } - - sprintf(devnode, "plughw:%d,%d", card, device); - if(!alsa_try_open(devnode, stream)) - continue; - - if(*num){ - *ids = HeapReAlloc(GetProcessHeap(), 0, *ids, sizeof(WCHAR *) * (*num + 1)); - *guids = HeapReAlloc(GetProcessHeap(), 0, *guids, sizeof(GUID) * (*num + 1)); - }else{ - *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *)); - *guids = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID)); - } - - devname = snd_pcm_info_get_name(info); - if(!devname){ - WARN("Unable to get device name for card %d, device %d\n", card, - device); - continue; - } - - (*ids)[*num] = construct_device_id(flow, cardnameW, devname); - get_device_guid(flow, devnode, &(*guids)[*num]); - - ++(*num); - } - - HeapFree(GetProcessHeap(), 0, info); - - if(err != 0) - WARN("Got a failure during device enumeration on card %d: %d (%s)\n", - card, err, snd_strerror(err)); - - return S_OK; -} - static void get_reg_devices(EDataFlow flow, snd_pcm_stream_t stream, WCHAR ***ids, GUID **guids, UINT *num) { @@ -521,71 +452,72 @@ static void get_reg_devices(EDataFlow flow, snd_pcm_stream_t stream, WCHAR ***id } } -static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR ***ids, GUID **guids, - UINT *num) +static void get_hint_devices(EDataFlow flow, snd_pcm_stream_t stream, WCHAR ***ids, + GUID **guids, UINT *num) { - snd_pcm_stream_t stream = (flow == eRender ? SND_PCM_STREAM_PLAYBACK : - SND_PCM_STREAM_CAPTURE); - int err, card; + void** hints; + int i; - card = -1; - *num = 0; + const char* ioType = (stream == SND_PCM_STREAM_PLAYBACK) ? "Output" : "Input"; - if(alsa_try_open(defname, stream)){ - *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *)); - (*ids)[0] = construct_device_id(flow, defaultW, NULL); - *guids = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID)); - get_device_guid(flow, defname, &(*guids)[0]); - ++*num; - } + if(snd_device_name_hint(-1, "pcm", &hints) < 0) { + ERR("Could not get a set of ALSA device hints\n"); + return; + } - get_reg_devices(flow, stream, ids, guids, num); + for(i = 0; hints[i] != NULL; i++) { + DWORD len; + WCHAR* descriptionW; + char *name, *description, *ioId; - for(err = snd_card_next(&card); card != -1 && err >= 0; - err = snd_card_next(&card)){ - char cardpath[64]; - char *cardname; - WCHAR *cardnameW; - snd_ctl_t *ctl; - DWORD len; + name = snd_device_name_get_hint(hints[i], "NAME"); + description = snd_device_name_get_hint(hints[i], "DESC"); + ioId = snd_device_name_get_hint(hints[i], "IOID"); - sprintf(cardpath, "hw:%u", card); + if(ioId != NULL && strcmp(ioId, ioType) != 0) { + continue; + } - if((err = snd_ctl_open(&ctl, cardpath, 0)) < 0){ - WARN("Unable to open ctl for ALSA device %s: %d (%s)\n", cardpath, - err, snd_strerror(err)); - continue; + len = MultiByteToWideChar(CP_UNIXCP, 0, description, -1, NULL, 0); + descriptionW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_UNIXCP, 0, description, -1, descriptionW, len); + + if(alsa_try_open(name, stream)) { + if(*num) { + *ids = HeapReAlloc(GetProcessHeap(), 0, *ids, sizeof(WCHAR *) * (*num + 1)); + *guids = HeapReAlloc(GetProcessHeap(), 0, *guids, sizeof(GUID) * (*num + 1)); + } else { + *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *)); + *guids = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID)); + } + + (*ids)[*num] = construct_device_id(flow, descriptionW /* cardNameW */, NULL /* devNameW */); + get_device_guid(flow, name, &(*guids)[*num]); + + ++(*num); } - if(snd_card_get_name(card, &cardname) < 0) { - /* FIXME: Should be localized */ - static const WCHAR nameW[] = {'U','n','k','n','o','w','n',' ','s','o','u','n','d','c','a','r','d',0}; - WARN("Unable to get card name for ALSA device %s: %d (%s)\n", - cardpath, err, snd_strerror(err)); - alsa_get_card_devices(flow, stream, ids, guids, num, ctl, card, nameW); - }else{ - len = MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, NULL, 0); - cardnameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + free(name); + free(description); + free(ioId); + } - if(!cardnameW){ - free(cardname); - snd_ctl_close(ctl); - return E_OUTOFMEMORY; - } - MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, cardnameW, len); + if(snd_device_name_free_hint(hints) < 0) { + ERR("Could not free list of ALSA device hints\n"); + } +} - alsa_get_card_devices(flow, stream, ids, guids, num, ctl, card, cardnameW); +static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR ***ids, GUID **guids, + UINT *num) +{ + snd_pcm_stream_t stream = (flow == eRender ? SND_PCM_STREAM_PLAYBACK : + SND_PCM_STREAM_CAPTURE); - HeapFree(GetProcessHeap(), 0, cardnameW); - free(cardname); - } + *num = 0; - snd_ctl_close(ctl); - } + get_reg_devices(flow, stream, ids, guids, num); - if(err != 0) - WARN("Got a failure during card enumeration: %d (%s)\n", - err, snd_strerror(err)); + get_hint_devices(flow, stream, ids, guids, num); return S_OK; } -- 2.10.0.478.g3ef7618