2 * Sample Wine Driver for Advanced Linux Sound System (ALSA)
3 * Based on version <final> of the ALSA API
5 * This file performs the initialisation and scanning of the sound subsystem.
7 * Copyright 2002 Eric Pouech
8 * 2002 Marco Pietrobono
9 * 2003 Christian Costa : WaveIn support
10 * 2006-2007 Maarten Lankhorst
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/port.h"
40 #ifdef HAVE_SYS_IOCTL_H
41 # include <sys/ioctl.h>
43 #ifdef HAVE_SYS_MMAN_H
44 # include <sys/mman.h>
55 /* ksmedia.h defines KSDATAFORMAT_SUBTYPE_PCM and KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
56 * However either all files that use it will define it, or no files will
57 * The only way to solve this is by adding initguid.h here, and include the guid that way
62 #include "wine/library.h"
63 #include "wine/unicode.h"
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(wave
);
70 /*----------------------------------------------------------------------------
71 ** ALSA_TestDeviceForWine
73 ** Test to see if a given device is sufficient for Wine.
75 static int ALSA_TestDeviceForWine(int card
, int device
, snd_pcm_stream_t streamtype
)
77 snd_pcm_t
*pcm
= NULL
;
80 snd_pcm_hw_params_t
*hwparams
;
81 const char *reason
= NULL
;
84 hwparams
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, snd_pcm_hw_params_sizeof() );
86 /* Note that the plug: device masks out a lot of info, we want to avoid that */
87 sprintf(pcmname
, "hw:%d,%d", card
, device
);
88 retcode
= snd_pcm_open(&pcm
, pcmname
, streamtype
, SND_PCM_NONBLOCK
);
91 /* Note that a busy device isn't automatically disqualified */
92 if (retcode
== (-1 * EBUSY
))
97 retcode
= snd_pcm_hw_params_any(pcm
, hwparams
);
100 reason
= "Could not retrieve hw_params";
104 /* set the count of channels */
105 retcode
= snd_pcm_hw_params_set_channels(pcm
, hwparams
, 2);
108 reason
= "Could not set channels";
113 retcode
= snd_pcm_hw_params_set_rate_near(pcm
, hwparams
, &rrate
, 0);
116 reason
= "Could not set rate";
122 reason
= "Rate came back as 0";
126 /* write the parameters to device */
127 retcode
= snd_pcm_hw_params(pcm
, hwparams
);
130 reason
= "Could not set hwparams";
139 HeapFree( GetProcessHeap(), 0, hwparams
);
141 if (retcode
!= 0 && retcode
!= (-1 * ENOENT
))
142 TRACE("Discarding card %d/device %d: %s [%d(%s)]\n", card
, device
, reason
, retcode
, snd_strerror(retcode
));
147 /*----------------------------------------------------------------------------
149 ** Retrieve a string from a registry key
151 static int ALSA_RegGetString(HKEY key
, const char *value
, char **bufp
)
158 rc
= RegQueryValueExA(key
, value
, NULL
, &type
, NULL
, &bufsize
);
159 if (rc
!= ERROR_SUCCESS
)
165 *bufp
= HeapAlloc(GetProcessHeap(), 0, bufsize
);
169 rc
= RegQueryValueExA(key
, value
, NULL
, NULL
, (LPBYTE
)*bufp
, &bufsize
);
173 /*----------------------------------------------------------------------------
174 ** ALSA_RegGetBoolean
175 ** Get a string and interpret it as a boolean
179 Y(es), T(rue), 1, E(nabled) */
181 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1' || (ch) == 'e' || (ch) == 'E')
182 static int ALSA_RegGetBoolean(HKEY key
, const char *value
, BOOL
*answer
)
187 rc
= ALSA_RegGetString(key
, value
, &buf
);
191 if (IS_OPTION_TRUE(*buf
))
194 HeapFree(GetProcessHeap(), 0, buf
);
200 /*----------------------------------------------------------------------------
202 ** Get a string and interpret it as a DWORD
204 static int ALSA_RegGetInt(HKEY key
, const char *value
, DWORD
*answer
)
209 rc
= ALSA_RegGetString(key
, value
, &buf
);
213 HeapFree(GetProcessHeap(), 0, buf
);
219 /* return a string duplicated on the win32 process heap, free with HeapFree */
220 static char* ALSA_strdup(const char *s
) {
221 char *result
= HeapAlloc(GetProcessHeap(), 0, strlen(s
)+1);
228 #define ALSA_RETURN_ONFAIL(mycall) \
234 ERR("%s failed: %s(%d)\n", #mycall, snd_strerror(rc), rc); \
239 /*----------------------------------------------------------------------------
242 ** Given an ALSA PCM, figure out our HW CAPS structure info.
243 ** ctl can be null, pcm is required, as is all output parms.
246 static int ALSA_ComputeCaps(snd_ctl_t
*ctl
, snd_pcm_t
*pcm
,
247 WORD
*channels
, DWORD
*flags
, DWORD
*formats
, DWORD
*supports
)
249 snd_pcm_hw_params_t
*hw_params
;
250 snd_pcm_format_mask_t
*fmask
;
251 snd_pcm_access_mask_t
*acmask
;
252 unsigned int ratemin
= 0;
253 unsigned int ratemax
= 0;
254 unsigned int chmin
= 0;
255 unsigned int chmax
= 0;
258 hw_params
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, snd_pcm_hw_params_sizeof() );
259 fmask
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, snd_pcm_format_mask_sizeof() );
260 acmask
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, snd_pcm_access_mask_sizeof() );
262 if ((rc
= snd_pcm_hw_params_any(pcm
, hw_params
)) < 0) goto done
;
264 snd_pcm_hw_params_get_format_mask(hw_params
, fmask
);
266 if ((rc
= snd_pcm_hw_params_get_access_mask(hw_params
, acmask
)) < 0) goto done
;
268 if ((rc
= snd_pcm_hw_params_get_rate_min(hw_params
, &ratemin
, &dir
)) < 0) goto done
;
269 if ((rc
= snd_pcm_hw_params_get_rate_max(hw_params
, &ratemax
, &dir
)) < 0) goto done
;
270 if ((rc
= snd_pcm_hw_params_get_channels_min(hw_params
, &chmin
)) < 0) goto done
;
271 if ((rc
= snd_pcm_hw_params_get_channels_max(hw_params
, &chmax
)) < 0) goto done
;
274 if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
276 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
278 if (chmin <= 1 && 1 <= chmax) \
279 *formats |= WAVE_FORMAT_##v##M08; \
280 if (chmin <= 2 && 2 <= chmax) \
281 *formats |= WAVE_FORMAT_##v##S08; \
283 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
285 if (chmin <= 1 && 1 <= chmax) \
286 *formats |= WAVE_FORMAT_##v##M16; \
287 if (chmin <= 2 && 2 <= chmax) \
288 *formats |= WAVE_FORMAT_##v##S16; \
299 FIXME("Device has a minimum of %d channels\n", chmin
);
302 /* FIXME: is sample accurate always true ?
303 ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
304 *supports
|= WAVECAPS_SAMPLEACCURATE
;
306 /* FIXME: NONITERLEAVED and COMPLEX are not supported right now */
307 if ( snd_pcm_access_mask_test( acmask
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) )
308 *supports
|= WAVECAPS_DIRECTSOUND
;
310 /* check for volume control support */
312 if (snd_ctl_name(ctl
))
315 if (snd_hctl_open(&hctl
, snd_ctl_name(ctl
), 0) >= 0)
318 if (!ALSA_CheckSetVolume( hctl
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
))
320 *supports
|= WAVECAPS_VOLUME
;
321 if (chmin
<= 2 && 2 <= chmax
)
322 *supports
|= WAVECAPS_LRVOLUME
;
325 snd_hctl_close(hctl
);
330 *flags
= DSCAPS_CERTIFIED
| DSCAPS_CONTINUOUSRATE
;
331 *flags
|= DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
332 *flags
|= DSCAPS_SECONDARY8BIT
| DSCAPS_SECONDARY16BIT
;
334 if (*formats
& (WAVE_FORMAT_1M08
| WAVE_FORMAT_2M08
|
335 WAVE_FORMAT_4M08
| WAVE_FORMAT_48M08
|
336 WAVE_FORMAT_96M08
| WAVE_FORMAT_1M16
|
337 WAVE_FORMAT_2M16
| WAVE_FORMAT_4M16
|
338 WAVE_FORMAT_48M16
| WAVE_FORMAT_96M16
) )
339 *flags
|= DSCAPS_PRIMARYMONO
;
341 if (*formats
& (WAVE_FORMAT_1S08
| WAVE_FORMAT_2S08
|
342 WAVE_FORMAT_4S08
| WAVE_FORMAT_48S08
|
343 WAVE_FORMAT_96S08
| WAVE_FORMAT_1S16
|
344 WAVE_FORMAT_2S16
| WAVE_FORMAT_4S16
|
345 WAVE_FORMAT_48S16
| WAVE_FORMAT_96S16
) )
346 *flags
|= DSCAPS_PRIMARYSTEREO
;
348 if (*formats
& (WAVE_FORMAT_1M08
| WAVE_FORMAT_2M08
|
349 WAVE_FORMAT_4M08
| WAVE_FORMAT_48M08
|
350 WAVE_FORMAT_96M08
| WAVE_FORMAT_1S08
|
351 WAVE_FORMAT_2S08
| WAVE_FORMAT_4S08
|
352 WAVE_FORMAT_48S08
| WAVE_FORMAT_96S08
) )
353 *flags
|= DSCAPS_PRIMARY8BIT
;
355 if (*formats
& (WAVE_FORMAT_1M16
| WAVE_FORMAT_2M16
|
356 WAVE_FORMAT_4M16
| WAVE_FORMAT_48M16
|
357 WAVE_FORMAT_96M16
| WAVE_FORMAT_1S16
|
358 WAVE_FORMAT_2S16
| WAVE_FORMAT_4S16
|
359 WAVE_FORMAT_48S16
| WAVE_FORMAT_96S16
) )
360 *flags
|= DSCAPS_PRIMARY16BIT
;
365 if (rc
< 0) ERR("failed: %s(%d)\n", snd_strerror(rc
), rc
);
366 HeapFree( GetProcessHeap(), 0, hw_params
);
367 HeapFree( GetProcessHeap(), 0, fmask
);
368 HeapFree( GetProcessHeap(), 0, acmask
);
372 /*----------------------------------------------------------------------------
373 ** ALSA_AddCommonDevice
375 ** Perform Alsa initialization common to both capture and playback
377 ** Side Effect: ww->pcname and ww->ctlname may need to be freed.
379 ** Note: this was originally coded by using snd_pcm_name(pcm), until
380 ** I discovered that with at least one version of alsa lib,
381 ** the use of a pcm named default:0 would cause snd_pcm_name() to fail.
382 ** So passing the name in is logically extraneous. Sigh.
384 static int ALSA_AddCommonDevice(snd_ctl_t
*ctl
, snd_pcm_t
*pcm
, const char *pcmname
, WINE_WAVEDEV
*ww
)
386 snd_pcm_info_t
*infop
;
389 infop
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, snd_pcm_info_sizeof() );
390 if ((rc
= snd_pcm_info(pcm
, infop
)) < 0)
392 HeapFree( GetProcessHeap(), 0, infop
);
397 ww
->pcmname
= ALSA_strdup(pcmname
);
400 HeapFree( GetProcessHeap(), 0, infop
);
404 if (ctl
&& snd_ctl_name(ctl
))
405 ww
->ctlname
= ALSA_strdup(snd_ctl_name(ctl
));
407 strcpy(ww
->interface_name
, "winealsa: ");
408 memcpy(ww
->interface_name
+ strlen(ww
->interface_name
),
410 min(strlen(ww
->pcmname
), sizeof(ww
->interface_name
) - strlen("winealsa: ")));
412 strcpy(ww
->ds_desc
.szDrvname
, "winealsa.drv");
414 memcpy(ww
->ds_desc
.szDesc
, snd_pcm_info_get_name(infop
),
415 min( (sizeof(ww
->ds_desc
.szDesc
) - 1), strlen(snd_pcm_info_get_name(infop
))) );
417 ww
->ds_caps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
418 ww
->ds_caps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
419 ww
->ds_caps
.dwPrimaryBuffers
= 1;
421 HeapFree( GetProcessHeap(), 0, infop
);
425 /*----------------------------------------------------------------------------
428 static void ALSA_FreeDevice(WINE_WAVEDEV
*ww
)
430 HeapFree(GetProcessHeap(), 0, ww
->pcmname
);
433 HeapFree(GetProcessHeap(), 0, ww
->ctlname
);
437 /*----------------------------------------------------------------------------
438 ** ALSA_AddDeviceToArray
440 ** Dynamically size one of the wavein or waveout arrays of devices,
441 ** and add a fully configured device node to the array.
444 static int ALSA_AddDeviceToArray(WINE_WAVEDEV
*ww
, WINE_WAVEDEV
**array
,
445 DWORD
*count
, DWORD
*alloced
, int isdefault
)
449 if (*count
>= *alloced
)
451 (*alloced
) += WAVEDEV_ALLOC_EXTENT_SIZE
;
453 *array
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ww
) * (*alloced
));
455 *array
= HeapReAlloc(GetProcessHeap(), 0, *array
, sizeof(*ww
) * (*alloced
));
463 /* If this is the default, arrange for it to be the first element */
464 if (isdefault
&& i
> 0)
466 (*array
)[*count
] = (*array
)[0];
476 /*----------------------------------------------------------------------------
477 ** ALSA_AddPlaybackDevice
479 ** Add a given Alsa device to Wine's internal list of Playback
482 static int ALSA_AddPlaybackDevice(snd_ctl_t
*ctl
, snd_pcm_t
*pcm
, const char *pcmname
, int isdefault
)
487 memset(&wwo
, '\0', sizeof(wwo
));
489 rc
= ALSA_AddCommonDevice(ctl
, pcm
, pcmname
, &wwo
);
493 MultiByteToWideChar(CP_UNIXCP
, 0, wwo
.ds_desc
.szDesc
, -1,
494 wwo
.outcaps
.szPname
, sizeof(wwo
.outcaps
.szPname
)/sizeof(WCHAR
));
495 wwo
.outcaps
.szPname
[sizeof(wwo
.outcaps
.szPname
)/sizeof(WCHAR
) - 1] = '\0';
497 wwo
.outcaps
.wMid
= MM_CREATIVE
;
498 wwo
.outcaps
.wPid
= MM_CREATIVE_SBP16_WAVEOUT
;
499 wwo
.outcaps
.vDriverVersion
= 0x0100;
501 rc
= ALSA_ComputeCaps(ctl
, pcm
, &wwo
.outcaps
.wChannels
, &wwo
.ds_caps
.dwFlags
,
502 &wwo
.outcaps
.dwFormats
, &wwo
.outcaps
.dwSupport
);
505 WARN("Error calculating device caps for pcm [%s]\n", wwo
.pcmname
);
506 ALSA_FreeDevice(&wwo
);
510 rc
= ALSA_AddDeviceToArray(&wwo
, &WOutDev
, &ALSA_WodNumDevs
, &ALSA_WodNumMallocedDevs
, isdefault
);
512 ALSA_FreeDevice(&wwo
);
516 /*----------------------------------------------------------------------------
517 ** ALSA_AddCaptureDevice
519 ** Add a given Alsa device to Wine's internal list of Capture
522 static int ALSA_AddCaptureDevice(snd_ctl_t
*ctl
, snd_pcm_t
*pcm
, const char *pcmname
, int isdefault
)
527 memset(&wwi
, '\0', sizeof(wwi
));
529 rc
= ALSA_AddCommonDevice(ctl
, pcm
, pcmname
, &wwi
);
533 MultiByteToWideChar(CP_UNIXCP
, 0, wwi
.ds_desc
.szDesc
, -1,
534 wwi
.incaps
.szPname
, sizeof(wwi
.incaps
.szPname
) / sizeof(WCHAR
));
535 wwi
.incaps
.szPname
[sizeof(wwi
.incaps
.szPname
)/sizeof(WCHAR
) - 1] = '\0';
537 wwi
.incaps
.wMid
= MM_CREATIVE
;
538 wwi
.incaps
.wPid
= MM_CREATIVE_SBP16_WAVEOUT
;
539 wwi
.incaps
.vDriverVersion
= 0x0100;
541 rc
= ALSA_ComputeCaps(ctl
, pcm
, &wwi
.incaps
.wChannels
, &wwi
.ds_caps
.dwFlags
,
542 &wwi
.incaps
.dwFormats
, &wwi
.dwSupport
);
545 WARN("Error calculating device caps for pcm [%s]\n", wwi
.pcmname
);
546 ALSA_FreeDevice(&wwi
);
550 rc
= ALSA_AddDeviceToArray(&wwi
, &WInDev
, &ALSA_WidNumDevs
, &ALSA_WidNumMallocedDevs
, isdefault
);
552 ALSA_FreeDevice(&wwi
);
556 /*----------------------------------------------------------------------------
557 ** ALSA_CheckEnvironment
559 ** Given an Alsa style configuration node, scan its subitems
560 ** for environment variable names, and use them to find an override,
562 ** This is essentially a long and convoluted way of doing:
563 ** getenv("ALSA_CARD")
564 ** getenv("ALSA_CTL_CARD")
565 ** getenv("ALSA_PCM_CARD")
566 ** getenv("ALSA_PCM_DEVICE")
568 ** The output value is set with the atoi() of the first environment
569 ** variable found to be set, if any; otherwise, it is left alone
571 static void ALSA_CheckEnvironment(snd_config_t
*node
, int *outvalue
)
573 snd_config_iterator_t iter
;
575 for (iter
= snd_config_iterator_first(node
);
576 iter
!= snd_config_iterator_end(node
);
577 iter
= snd_config_iterator_next(iter
))
579 snd_config_t
*leaf
= snd_config_iterator_entry(iter
);
580 if (snd_config_get_type(leaf
) == SND_CONFIG_TYPE_STRING
)
583 if (snd_config_get_string(leaf
, &value
) >= 0)
585 char *p
= getenv(value
);
596 /*----------------------------------------------------------------------------
597 ** ALSA_DefaultDevices
599 ** Jump through Alsa style hoops to (hopefully) properly determine
600 ** Alsa defaults for CTL Card #, as well as for PCM Card + Device #.
601 ** We'll also find out if the user has set any of the environment
602 ** variables that specify we're to use a specific card or device.
605 ** directhw Whether to use a direct hardware device or not;
606 ** essentially switches the pcm device name from
607 ** one of 'default:X' or 'plughw:X' to "hw:X"
608 ** defctlcard If !NULL, will hold the ctl card number given
609 ** by the ALSA config as the default
610 ** defpcmcard If !NULL, default pcm card #
611 ** defpcmdev If !NULL, default pcm device #
612 ** fixedctlcard If !NULL, and the user set the appropriate
613 ** environment variable, we'll set to the
614 ** card the user specified.
615 ** fixedpcmcard If !NULL, and the user set the appropriate
616 ** environment variable, we'll set to the
617 ** card the user specified.
618 ** fixedpcmdev If !NULL, and the user set the appropriate
619 ** environment variable, we'll set to the
620 ** device the user specified.
622 ** Returns: 0 on success, < 0 on failure
624 static int ALSA_DefaultDevices(int directhw
,
626 long *defpcmcard
, long *defpcmdev
,
628 int *fixedpcmcard
, int *fixedpcmdev
)
630 snd_config_t
*configp
;
633 ALSA_RETURN_ONFAIL(snd_config_update());
636 if (snd_config_search(snd_config
, "defaults.ctl.card", &configp
) >= 0)
637 snd_config_get_integer(configp
, defctlcard
);
640 if (snd_config_search(snd_config
, "defaults.pcm.card", &configp
) >= 0)
641 snd_config_get_integer(configp
, defpcmcard
);
644 if (snd_config_search(snd_config
, "defaults.pcm.device", &configp
) >= 0)
645 snd_config_get_integer(configp
, defpcmdev
);
650 if (snd_config_search(snd_config
, "ctl.hw.@args.CARD.default.vars", &configp
) >= 0)
651 ALSA_CheckEnvironment(configp
, fixedctlcard
);
656 sprintf(pcmsearch
, "pcm.%s.@args.CARD.default.vars", directhw
? "hw" : "plughw");
657 if (snd_config_search(snd_config
, pcmsearch
, &configp
) >= 0)
658 ALSA_CheckEnvironment(configp
, fixedpcmcard
);
663 sprintf(pcmsearch
, "pcm.%s.@args.DEV.default.vars", directhw
? "hw" : "plughw");
664 if (snd_config_search(snd_config
, pcmsearch
, &configp
) >= 0)
665 ALSA_CheckEnvironment(configp
, fixedpcmdev
);
672 /*----------------------------------------------------------------------------
675 ** Iterate through all discoverable ALSA cards, searching
676 ** for usable PCM devices.
679 ** directhw Whether to use a direct hardware device or not;
680 ** essentially switches the pcm device name from
681 ** one of 'default:X' or 'plughw:X' to "hw:X"
682 ** defctlcard Alsa's notion of the default ctl card.
683 ** defpcmcard . pcm card
684 ** defpcmdev . pcm device
685 ** fixedctlcard If not -1, then gives the value of ALSA_CTL_CARD
686 ** or equivalent environment variable
687 ** fixedpcmcard If not -1, then gives the value of ALSA_PCM_CARD
688 ** or equivalent environment variable
689 ** fixedpcmdev If not -1, then gives the value of ALSA_PCM_DEVICE
690 ** or equivalent environment variable
692 ** Returns: 0 on success, < 0 on failure
694 static int ALSA_ScanDevices(int directhw
,
695 long defctlcard
, long defpcmcard
, long defpcmdev
,
696 int fixedctlcard
, int fixedpcmcard
, int fixedpcmdev
)
698 int card
= fixedpcmcard
;
699 int scan_devices
= (fixedpcmdev
== -1);
701 /*------------------------------------------------------------------------
702 ** Loop through all available cards
703 **----------------------------------------------------------------------*/
705 snd_card_next(&card
);
707 for (; card
!= -1; snd_card_next(&card
))
714 /*--------------------------------------------------------------------
715 ** Try to open a ctl handle; Wine doesn't absolutely require one,
716 ** but it does allow for volume control and for device scanning
717 **------------------------------------------------------------------*/
718 sprintf(ctlname
, "hw:%d", fixedctlcard
== -1 ? card
: fixedctlcard
);
719 rc
= snd_ctl_open(&ctl
, ctlname
, SND_CTL_NONBLOCK
);
723 WARN("Unable to open an alsa ctl for [%s] (pcm card %d): %s; not scanning devices\n",
724 ctlname
, card
, snd_strerror(rc
));
725 if (fixedpcmdev
== -1)
729 /*--------------------------------------------------------------------
730 ** Loop through all available devices on this card
731 **------------------------------------------------------------------*/
732 device
= fixedpcmdev
;
734 snd_ctl_pcm_next_device(ctl
, &device
);
736 for (; device
!= -1; snd_ctl_pcm_next_device(ctl
, &device
))
738 char defaultpcmname
[256];
739 char plugpcmname
[256];
741 char *pcmname
= NULL
;
744 sprintf(defaultpcmname
, "default");
745 sprintf(plugpcmname
, "plughw:%d,%d", card
, device
);
746 sprintf(hwpcmname
, "hw:%d,%d", card
, device
);
748 /*----------------------------------------------------------------
749 ** See if it's a valid playback device
750 **--------------------------------------------------------------*/
751 if (ALSA_TestDeviceForWine(card
, device
, SND_PCM_STREAM_PLAYBACK
) == 0)
753 /* If we can, try the default:X device name first */
754 if (! scan_devices
&& ! directhw
)
756 pcmname
= defaultpcmname
;
757 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
);
764 pcmname
= directhw
? hwpcmname
: plugpcmname
;
765 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
);
770 if (defctlcard
== card
&& defpcmcard
== card
&& defpcmdev
== device
)
771 ALSA_AddPlaybackDevice(ctl
, pcm
, pcmname
, TRUE
);
773 ALSA_AddPlaybackDevice(ctl
, pcm
, pcmname
, FALSE
);
778 TRACE("Device [%s/%s] failed to open for playback: %s\n",
779 directhw
|| scan_devices
? "(N/A)" : defaultpcmname
,
780 directhw
? hwpcmname
: plugpcmname
,
785 /*----------------------------------------------------------------
786 ** See if it's a valid capture device
787 **--------------------------------------------------------------*/
788 if (ALSA_TestDeviceForWine(card
, device
, SND_PCM_STREAM_CAPTURE
) == 0)
790 /* If we can, try the default:X device name first */
791 if (! scan_devices
&& ! directhw
)
793 pcmname
= defaultpcmname
;
794 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_CAPTURE
, SND_PCM_NONBLOCK
);
801 pcmname
= directhw
? hwpcmname
: plugpcmname
;
802 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_CAPTURE
, SND_PCM_NONBLOCK
);
807 if (defctlcard
== card
&& defpcmcard
== card
&& defpcmdev
== device
)
808 ALSA_AddCaptureDevice(ctl
, pcm
, pcmname
, TRUE
);
810 ALSA_AddCaptureDevice(ctl
, pcm
, pcmname
, FALSE
);
816 TRACE("Device [%s/%s] failed to open for capture: %s\n",
817 directhw
|| scan_devices
? "(N/A)" : defaultpcmname
,
818 directhw
? hwpcmname
: plugpcmname
,
830 /*--------------------------------------------------------------------
831 ** If the user has set env variables such that we're pegged to
832 ** a specific card, then break after we've examined it
833 **------------------------------------------------------------------*/
834 if (fixedpcmcard
!= -1)
842 /*----------------------------------------------------------------------------
843 ** ALSA_PerformDefaultScan
844 ** Perform the basic default scanning for devices within ALSA.
845 ** The hope is that this routine implements a 'correct'
846 ** scanning algorithm from the Alsalib point of view.
848 ** Note that Wine, overall, has other mechanisms to
849 ** override and specify exact CTL and PCM device names,
850 ** but this routine is imagined as the default that
851 ** 99% of users will use.
853 ** The basic algorithm is simple:
854 ** Use snd_card_next to iterate cards; within cards, use
855 ** snd_ctl_pcm_next_device to iterate through devices.
857 ** We add a little complexity by taking into consideration
858 ** environment variables such as ALSA_CARD (et all), and by
859 ** detecting when a given device matches the default specified
863 ** directhw If !0, indicates we should use the hw:X
864 ** PCM interface, rather than first try
865 ** the 'default' device followed by the plughw
866 ** device. (default and plughw do fancy mixing
867 ** and audio scaling, if they are available).
868 ** devscan If TRUE, we should scan all devices, not
869 ** juse use device 0 on each card
875 ** Invokes the ALSA_AddXXXDevice functions on valid
878 static int ALSA_PerformDefaultScan(int directhw
, BOOL devscan
)
880 long defctlcard
= -1, defpcmcard
= -1, defpcmdev
= -1;
881 int fixedctlcard
= -1, fixedpcmcard
= -1, fixedpcmdev
= -1;
884 /* FIXME: We should dlsym the new snd_names_list/snd_names_list_free 1.0.9 apis,
885 ** and use them instead of this scan mechanism if they are present */
887 rc
= ALSA_DefaultDevices(directhw
, &defctlcard
, &defpcmcard
, &defpcmdev
,
888 &fixedctlcard
, &fixedpcmcard
, &fixedpcmdev
);
892 if (fixedpcmdev
== -1 && ! devscan
)
895 return(ALSA_ScanDevices(directhw
, defctlcard
, defpcmcard
, defpcmdev
, fixedctlcard
, fixedpcmcard
, fixedpcmdev
));
899 /*----------------------------------------------------------------------------
900 ** ALSA_AddUserSpecifiedDevice
901 ** Add a device given from the registry
903 static int ALSA_AddUserSpecifiedDevice(const char *ctlname
, const char *pcmname
)
907 snd_ctl_t
*ctl
= NULL
;
908 snd_pcm_t
*pcm
= NULL
;
912 rc
= snd_ctl_open(&ctl
, ctlname
, SND_CTL_NONBLOCK
);
917 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
);
920 ALSA_AddPlaybackDevice(ctl
, pcm
, pcmname
, FALSE
);
925 rc
= snd_pcm_open(&pcm
, pcmname
, SND_PCM_STREAM_CAPTURE
, SND_PCM_NONBLOCK
);
928 ALSA_AddCaptureDevice(ctl
, pcm
, pcmname
, FALSE
);
940 /*----------------------------------------------------------------------------
942 ** Initialize the Wine Alsa sub system.
943 ** The main task is to probe for and store a list of all appropriate playback
944 ** and capture devices.
945 ** Key control points are from the registry key:
946 ** [Software\Wine\Alsa Driver]
947 ** AutoScanCards Whether or not to scan all known sound cards
948 ** and add them to Wine's list (default yes)
949 ** AutoScanDevices Whether or not to scan all known PCM devices
950 ** on each card (default no)
951 ** UseDirectHW Whether or not to use the hw:X device,
952 ** instead of the fancy default:X or plughw:X device.
953 ** The hw:X device goes straight to the hardware
954 ** without any fancy mixing or audio scaling in between.
955 ** DeviceCount If present, specifies the number of hard coded
956 ** Alsa devices to add to Wine's list; default 0
957 ** DevicePCMn Specifies the Alsa PCM devices to open for
958 ** Device n (where n goes from 1 to DeviceCount)
959 ** DeviceCTLn Specifies the Alsa control devices to open for
960 ** Device n (where n goes from 1 to DeviceCount)
962 ** Using AutoScanCards no, and then Devicexxx info
963 ** is a way to exactly specify the devices used by Wine.
966 LONG
ALSA_WaveInit(void)
969 BOOL AutoScanCards
= TRUE
;
970 BOOL AutoScanDevices
= FALSE
;
971 BOOL UseDirectHW
= FALSE
;
972 DWORD DeviceCount
= 0;
976 if (!wine_dlopen("libasound.so.2", RTLD_LAZY
|RTLD_GLOBAL
, NULL
, 0))
978 ERR("Error: ALSA lib needs to be loaded with flags RTLD_LAZY and RTLD_GLOBAL.\n");
982 /* @@ Wine registry key: HKCU\Software\Wine\Alsa Driver */
983 rc
= RegOpenKeyExA(HKEY_CURRENT_USER
, "Software\\Wine\\Alsa Driver", 0, KEY_QUERY_VALUE
, &key
);
984 if (rc
== ERROR_SUCCESS
)
986 ALSA_RegGetBoolean(key
, "AutoScanCards", &AutoScanCards
);
987 ALSA_RegGetBoolean(key
, "AutoScanDevices", &AutoScanDevices
);
988 ALSA_RegGetBoolean(key
, "UseDirectHW", &UseDirectHW
);
989 ALSA_RegGetInt(key
, "DeviceCount", &DeviceCount
);
993 rc
= ALSA_PerformDefaultScan(UseDirectHW
, AutoScanDevices
);
995 for (i
= 0; i
< DeviceCount
; i
++)
997 char *ctl_name
= NULL
;
998 char *pcm_name
= NULL
;
1001 sprintf(value
, "DevicePCM%d", i
+ 1);
1002 if (ALSA_RegGetString(key
, value
, &pcm_name
) == ERROR_SUCCESS
)
1004 sprintf(value
, "DeviceCTL%d", i
+ 1);
1005 ALSA_RegGetString(key
, value
, &ctl_name
);
1006 ALSA_AddUserSpecifiedDevice(ctl_name
, pcm_name
);
1009 HeapFree(GetProcessHeap(), 0, ctl_name
);
1010 HeapFree(GetProcessHeap(), 0, pcm_name
);
1019 #endif /* HAVE_ALSA */