push(f) 25359c458b329fe03f66bef506b8062c200b9eb4
[wine/hacks.git] / dlls / winealsa.drv / waveinit.c
blob450c2cac794861fdb067810a3d9d3f3656de911d
1 /*
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
27 #include "config.h"
29 #ifdef HAVE_ALSA
31 #include "wine/port.h"
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <string.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #include <errno.h>
41 #include <limits.h>
42 #include <fcntl.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 # include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_SYS_MMAN_H
47 # include <sys/mman.h>
48 #endif
49 #include "windef.h"
50 #include "winbase.h"
51 #include "wingdi.h"
52 #include "winerror.h"
53 #include "winuser.h"
54 #include "winnls.h"
55 #include "winreg.h"
56 #include "mmddk.h"
58 /* ksmedia.h defines KSDATAFORMAT_SUBTYPE_PCM and KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
59 * However either all files that use it will define it, or no files will
60 * The only way to solve this is by adding initguid.h here, and include the guid that way
62 #include "initguid.h"
63 #include "alsa.h"
65 #include "wine/library.h"
66 #include "wine/unicode.h"
67 #include "wine/debug.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(wave);
71 /*----------------------------------------------------------------------------
72 ** ALSA_TestDeviceForWine
74 ** Test to see if a given device is sufficient for Wine.
76 static int ALSA_TestDeviceForWine(int card, int device, snd_pcm_stream_t streamtype)
78 snd_pcm_t *pcm = NULL;
79 char pcmname[256];
80 int retcode;
81 snd_pcm_hw_params_t *hwparams;
82 const char *reason = NULL;
83 unsigned int rrate;
85 hwparams = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
87 /* Note that the plug: device masks out a lot of info, we want to avoid that */
88 sprintf(pcmname, "hw:%d,%d", card, device);
89 retcode = snd_pcm_open(&pcm, pcmname, streamtype, SND_PCM_NONBLOCK);
90 if (retcode < 0)
92 /* Note that a busy device isn't automatically disqualified */
93 if (retcode == (-1 * EBUSY))
94 retcode = 0;
95 goto exit;
98 retcode = snd_pcm_hw_params_any(pcm, hwparams);
99 if (retcode < 0)
101 reason = "Could not retrieve hw_params";
102 goto exit;
105 /* set the count of channels */
106 retcode = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
107 if (retcode < 0)
109 reason = "Could not set channels";
110 goto exit;
113 rrate = 44100;
114 retcode = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rrate, 0);
115 if (retcode < 0)
117 reason = "Could not set rate";
118 goto exit;
121 if (rrate == 0)
123 reason = "Rate came back as 0";
124 goto exit;
127 /* write the parameters to device */
128 retcode = snd_pcm_hw_params(pcm, hwparams);
129 if (retcode < 0)
131 reason = "Could not set hwparams";
132 goto exit;
135 retcode = 0;
137 exit:
138 if (pcm)
139 snd_pcm_close(pcm);
140 HeapFree( GetProcessHeap(), 0, hwparams );
142 if (retcode != 0 && retcode != (-1 * ENOENT))
143 TRACE("Discarding card %d/device %d: %s [%d(%s)]\n", card, device, reason, retcode, snd_strerror(retcode));
145 return retcode;
148 /*----------------------------------------------------------------------------
149 ** ALSA_RegGetString
150 ** Retrieve a string from a registry key
152 static int ALSA_RegGetString(HKEY key, const char *value, char **bufp)
154 DWORD rc;
155 DWORD type;
156 DWORD bufsize;
158 *bufp = NULL;
159 rc = RegQueryValueExA(key, value, NULL, &type, NULL, &bufsize);
160 if (rc != ERROR_SUCCESS)
161 return(rc);
163 if (type != REG_SZ)
164 return 1;
166 *bufp = HeapAlloc(GetProcessHeap(), 0, bufsize);
167 if (! *bufp)
168 return 1;
170 rc = RegQueryValueExA(key, value, NULL, NULL, (LPBYTE)*bufp, &bufsize);
171 return rc;
174 /*----------------------------------------------------------------------------
175 ** ALSA_RegGetBoolean
176 ** Get a string and interpret it as a boolean
179 /* Possible truths:
180 Y(es), T(rue), 1, E(nabled) */
182 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1' || (ch) == 'e' || (ch) == 'E')
183 static int ALSA_RegGetBoolean(HKEY key, const char *value, BOOL *answer)
185 DWORD rc;
186 char *buf = NULL;
188 rc = ALSA_RegGetString(key, value, &buf);
189 if (buf)
191 *answer = FALSE;
192 if (IS_OPTION_TRUE(*buf))
193 *answer = TRUE;
195 HeapFree(GetProcessHeap(), 0, buf);
198 return rc;
201 /*----------------------------------------------------------------------------
202 ** ALSA_RegGetInt
203 ** Get a string and interpret it as a DWORD
205 static int ALSA_RegGetInt(HKEY key, const char *value, DWORD *answer)
207 DWORD rc;
208 char *buf = NULL;
210 rc = ALSA_RegGetString(key, value, &buf);
211 if (buf)
213 *answer = atoi(buf);
214 HeapFree(GetProcessHeap(), 0, buf);
217 return rc;
220 /* return a string duplicated on the win32 process heap, free with HeapFree */
221 static char* ALSA_strdup(const char *s) {
222 char *result = HeapAlloc(GetProcessHeap(), 0, strlen(s)+1);
223 if (!result)
224 return NULL;
225 strcpy(result, s);
226 return result;
229 #define ALSA_RETURN_ONFAIL(mycall) \
231 int rc; \
232 {rc = mycall;} \
233 if ((rc) < 0) \
235 ERR("%s failed: %s(%d)\n", #mycall, snd_strerror(rc), rc); \
236 return(rc); \
240 /*----------------------------------------------------------------------------
241 ** ALSA_ComputeCaps
243 ** Given an ALSA PCM, figure out our HW CAPS structure info.
244 ** ctl can be null, pcm is required, as is all output parms.
247 static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm,
248 WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports)
250 snd_pcm_hw_params_t *hw_params;
251 snd_pcm_format_mask_t *fmask;
252 snd_pcm_access_mask_t *acmask;
253 unsigned int ratemin = 0;
254 unsigned int ratemax = 0;
255 unsigned int chmin = 0;
256 unsigned int chmax = 0;
257 int rc, dir = 0;
259 hw_params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
260 fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof() );
261 acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof() );
263 if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done;
265 snd_pcm_hw_params_get_format_mask(hw_params, fmask);
267 if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done;
269 if ((rc = snd_pcm_hw_params_get_rate_min(hw_params, &ratemin, &dir)) < 0) goto done;
270 if ((rc = snd_pcm_hw_params_get_rate_max(hw_params, &ratemax, &dir)) < 0) goto done;
271 if ((rc = snd_pcm_hw_params_get_channels_min(hw_params, &chmin)) < 0) goto done;
272 if ((rc = snd_pcm_hw_params_get_channels_max(hw_params, &chmax)) < 0) goto done;
274 #define X(r,v) \
275 if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
277 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
279 if (chmin <= 1 && 1 <= chmax) \
280 *formats |= WAVE_FORMAT_##v##M08; \
281 if (chmin <= 2 && 2 <= chmax) \
282 *formats |= WAVE_FORMAT_##v##S08; \
284 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
286 if (chmin <= 1 && 1 <= chmax) \
287 *formats |= WAVE_FORMAT_##v##M16; \
288 if (chmin <= 2 && 2 <= chmax) \
289 *formats |= WAVE_FORMAT_##v##S16; \
292 X(11025,1);
293 X(22050,2);
294 X(44100,4);
295 X(48000,48);
296 X(96000,96);
297 #undef X
299 if (chmin > 1)
300 FIXME("Device has a minimum of %d channels\n", chmin);
301 *channels = chmax;
303 /* FIXME: is sample accurate always true ?
304 ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
305 *supports |= WAVECAPS_SAMPLEACCURATE;
307 /* FIXME: NONITERLEAVED and COMPLEX are not supported right now */
308 if ( snd_pcm_access_mask_test( acmask, SND_PCM_ACCESS_MMAP_INTERLEAVED ) )
309 *supports |= WAVECAPS_DIRECTSOUND;
311 /* check for volume control support */
312 if (ctl) {
313 if (snd_ctl_name(ctl))
315 snd_hctl_t *hctl;
316 if (snd_hctl_open(&hctl, snd_ctl_name(ctl), 0) >= 0)
318 snd_hctl_load(hctl);
319 if (!ALSA_CheckSetVolume( hctl, NULL, NULL, NULL, NULL, NULL, NULL, NULL ))
321 *supports |= WAVECAPS_VOLUME;
322 if (chmin <= 2 && 2 <= chmax)
323 *supports |= WAVECAPS_LRVOLUME;
325 snd_hctl_free(hctl);
326 snd_hctl_close(hctl);
331 *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE;
332 *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
333 *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
335 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
336 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
337 WAVE_FORMAT_96M08 | WAVE_FORMAT_1M16 |
338 WAVE_FORMAT_2M16 | WAVE_FORMAT_4M16 |
339 WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16) )
340 *flags |= DSCAPS_PRIMARYMONO;
342 if (*formats & (WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 |
343 WAVE_FORMAT_4S08 | WAVE_FORMAT_48S08 |
344 WAVE_FORMAT_96S08 | WAVE_FORMAT_1S16 |
345 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
346 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
347 *flags |= DSCAPS_PRIMARYSTEREO;
349 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
350 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
351 WAVE_FORMAT_96M08 | WAVE_FORMAT_1S08 |
352 WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 |
353 WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08) )
354 *flags |= DSCAPS_PRIMARY8BIT;
356 if (*formats & (WAVE_FORMAT_1M16 | WAVE_FORMAT_2M16 |
357 WAVE_FORMAT_4M16 | WAVE_FORMAT_48M16 |
358 WAVE_FORMAT_96M16 | WAVE_FORMAT_1S16 |
359 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
360 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
361 *flags |= DSCAPS_PRIMARY16BIT;
363 rc = 0;
365 done:
366 if (rc < 0) ERR("failed: %s(%d)\n", snd_strerror(rc), rc);
367 HeapFree( GetProcessHeap(), 0, hw_params );
368 HeapFree( GetProcessHeap(), 0, fmask );
369 HeapFree( GetProcessHeap(), 0, acmask );
370 return rc;
373 /*----------------------------------------------------------------------------
374 ** ALSA_AddCommonDevice
376 ** Perform Alsa initialization common to both capture and playback
378 ** Side Effect: ww->pcname and ww->ctlname may need to be freed.
380 ** Note: this was originally coded by using snd_pcm_name(pcm), until
381 ** I discovered that with at least one version of alsa lib,
382 ** the use of a pcm named default:0 would cause snd_pcm_name() to fail.
383 ** So passing the name in is logically extraneous. Sigh.
385 static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww)
387 snd_pcm_info_t *infop;
388 int rc;
390 infop = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_info_sizeof() );
391 if ((rc = snd_pcm_info(pcm, infop)) < 0)
393 HeapFree( GetProcessHeap(), 0, infop );
394 return rc;
397 if (pcm && pcmname)
398 ww->pcmname = ALSA_strdup(pcmname);
399 else
401 HeapFree( GetProcessHeap(), 0, infop );
402 return -1;
405 if (ctl && snd_ctl_name(ctl))
406 ww->ctlname = ALSA_strdup(snd_ctl_name(ctl));
408 strcpy(ww->interface_name, "winealsa: ");
409 memcpy(ww->interface_name + strlen(ww->interface_name),
410 ww->pcmname,
411 min(strlen(ww->pcmname), sizeof(ww->interface_name) - strlen("winealsa: ")));
413 strcpy(ww->ds_desc.szDrvname, "winealsa.drv");
415 memcpy(ww->ds_desc.szDesc, snd_pcm_info_get_name(infop),
416 min( (sizeof(ww->ds_desc.szDesc) - 1), strlen(snd_pcm_info_get_name(infop))) );
418 ww->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
419 ww->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
420 ww->ds_caps.dwPrimaryBuffers = 1;
422 HeapFree( GetProcessHeap(), 0, infop );
423 return 0;
426 /*----------------------------------------------------------------------------
427 ** ALSA_FreeDevice
429 static void ALSA_FreeDevice(WINE_WAVEDEV *ww)
431 HeapFree(GetProcessHeap(), 0, ww->pcmname);
432 ww->pcmname = NULL;
434 HeapFree(GetProcessHeap(), 0, ww->ctlname);
435 ww->ctlname = NULL;
438 /*----------------------------------------------------------------------------
439 ** ALSA_AddDeviceToArray
441 ** Dynamically size one of the wavein or waveout arrays of devices,
442 ** and add a fully configured device node to the array.
445 static int ALSA_AddDeviceToArray(WINE_WAVEDEV *ww, WINE_WAVEDEV **array,
446 DWORD *count, DWORD *alloced, int isdefault)
448 int i = *count;
450 if (*count >= *alloced)
452 (*alloced) += WAVEDEV_ALLOC_EXTENT_SIZE;
453 if (! (*array))
454 *array = HeapAlloc(GetProcessHeap(), 0, sizeof(*ww) * (*alloced));
455 else
456 *array = HeapReAlloc(GetProcessHeap(), 0, *array, sizeof(*ww) * (*alloced));
458 if (!*array)
460 return -1;
464 /* If this is the default, arrange for it to be the first element */
465 if (isdefault && i > 0)
467 (*array)[*count] = (*array)[0];
468 i = 0;
471 (*array)[i] = *ww;
473 (*count)++;
474 return 0;
477 /*----------------------------------------------------------------------------
478 ** ALSA_AddPlaybackDevice
480 ** Add a given Alsa device to Wine's internal list of Playback
481 ** devices.
483 static int ALSA_AddPlaybackDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
485 WINE_WAVEDEV wwo;
486 int rc;
488 memset(&wwo, '\0', sizeof(wwo));
490 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwo);
491 if (rc)
492 return(rc);
494 MultiByteToWideChar(CP_UNIXCP, 0, wwo.ds_desc.szDesc, -1,
495 wwo.outcaps.szPname, sizeof(wwo.outcaps.szPname)/sizeof(WCHAR));
496 wwo.outcaps.szPname[sizeof(wwo.outcaps.szPname)/sizeof(WCHAR) - 1] = '\0';
498 wwo.outcaps.wMid = MM_CREATIVE;
499 wwo.outcaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
500 wwo.outcaps.vDriverVersion = 0x0100;
502 rc = ALSA_ComputeCaps(ctl, pcm, &wwo.outcaps.wChannels, &wwo.ds_caps.dwFlags,
503 &wwo.outcaps.dwFormats, &wwo.outcaps.dwSupport);
504 if (rc)
506 WARN("Error calculating device caps for pcm [%s]\n", wwo.pcmname);
507 ALSA_FreeDevice(&wwo);
508 return(rc);
511 rc = ALSA_AddDeviceToArray(&wwo, &WOutDev, &ALSA_WodNumDevs, &ALSA_WodNumMallocedDevs, isdefault);
512 if (rc)
513 ALSA_FreeDevice(&wwo);
514 return (rc);
517 /*----------------------------------------------------------------------------
518 ** ALSA_AddCaptureDevice
520 ** Add a given Alsa device to Wine's internal list of Capture
521 ** devices.
523 static int ALSA_AddCaptureDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
525 WINE_WAVEDEV wwi;
526 int rc;
528 memset(&wwi, '\0', sizeof(wwi));
530 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwi);
531 if (rc)
532 return(rc);
534 MultiByteToWideChar(CP_UNIXCP, 0, wwi.ds_desc.szDesc, -1,
535 wwi.incaps.szPname, sizeof(wwi.incaps.szPname) / sizeof(WCHAR));
536 wwi.incaps.szPname[sizeof(wwi.incaps.szPname)/sizeof(WCHAR) - 1] = '\0';
538 wwi.incaps.wMid = MM_CREATIVE;
539 wwi.incaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
540 wwi.incaps.vDriverVersion = 0x0100;
542 rc = ALSA_ComputeCaps(ctl, pcm, &wwi.incaps.wChannels, &wwi.ds_caps.dwFlags,
543 &wwi.incaps.dwFormats, &wwi.dwSupport);
544 if (rc)
546 WARN("Error calculating device caps for pcm [%s]\n", wwi.pcmname);
547 ALSA_FreeDevice(&wwi);
548 return(rc);
551 rc = ALSA_AddDeviceToArray(&wwi, &WInDev, &ALSA_WidNumDevs, &ALSA_WidNumMallocedDevs, isdefault);
552 if (rc)
553 ALSA_FreeDevice(&wwi);
554 return(rc);
557 /*----------------------------------------------------------------------------
558 ** ALSA_CheckEnvironment
560 ** Given an Alsa style configuration node, scan its subitems
561 ** for environment variable names, and use them to find an override,
562 ** if appropriate.
563 ** This is essentially a long and convoluted way of doing:
564 ** getenv("ALSA_CARD")
565 ** getenv("ALSA_CTL_CARD")
566 ** getenv("ALSA_PCM_CARD")
567 ** getenv("ALSA_PCM_DEVICE")
569 ** The output value is set with the atoi() of the first environment
570 ** variable found to be set, if any; otherwise, it is left alone
572 static void ALSA_CheckEnvironment(snd_config_t *node, int *outvalue)
574 snd_config_iterator_t iter;
576 for (iter = snd_config_iterator_first(node);
577 iter != snd_config_iterator_end(node);
578 iter = snd_config_iterator_next(iter))
580 snd_config_t *leaf = snd_config_iterator_entry(iter);
581 if (snd_config_get_type(leaf) == SND_CONFIG_TYPE_STRING)
583 const char *value;
584 if (snd_config_get_string(leaf, &value) >= 0)
586 char *p = getenv(value);
587 if (p)
589 *outvalue = atoi(p);
590 return;
597 /*----------------------------------------------------------------------------
598 ** ALSA_DefaultDevices
600 ** Jump through Alsa style hoops to (hopefully) properly determine
601 ** Alsa defaults for CTL Card #, as well as for PCM Card + Device #.
602 ** We'll also find out if the user has set any of the environment
603 ** variables that specify we're to use a specific card or device.
605 ** Parameters:
606 ** directhw Whether to use a direct hardware device or not;
607 ** essentially switches the pcm device name from
608 ** one of 'default:X' or 'plughw:X' to "hw:X"
609 ** defctlcard If !NULL, will hold the ctl card number given
610 ** by the ALSA config as the default
611 ** defpcmcard If !NULL, default pcm card #
612 ** defpcmdev If !NULL, default pcm device #
613 ** fixedctlcard If !NULL, and the user set the appropriate
614 ** environment variable, we'll set to the
615 ** card the user specified.
616 ** fixedpcmcard If !NULL, and the user set the appropriate
617 ** environment variable, we'll set to the
618 ** card the user specified.
619 ** fixedpcmdev If !NULL, and the user set the appropriate
620 ** environment variable, we'll set to the
621 ** device the user specified.
623 ** Returns: 0 on success, < 0 on failure
625 static int ALSA_DefaultDevices(int directhw,
626 long *defctlcard,
627 long *defpcmcard, long *defpcmdev,
628 int *fixedctlcard,
629 int *fixedpcmcard, int *fixedpcmdev)
631 snd_config_t *configp;
632 char pcmsearch[256];
634 ALSA_RETURN_ONFAIL(snd_config_update());
636 if (defctlcard)
637 if (snd_config_search(snd_config, "defaults.ctl.card", &configp) >= 0)
638 snd_config_get_integer(configp, defctlcard);
640 if (defpcmcard)
641 if (snd_config_search(snd_config, "defaults.pcm.card", &configp) >= 0)
642 snd_config_get_integer(configp, defpcmcard);
644 if (defpcmdev)
645 if (snd_config_search(snd_config, "defaults.pcm.device", &configp) >= 0)
646 snd_config_get_integer(configp, defpcmdev);
649 if (fixedctlcard)
651 if (snd_config_search(snd_config, "ctl.hw.@args.CARD.default.vars", &configp) >= 0)
652 ALSA_CheckEnvironment(configp, fixedctlcard);
655 if (fixedpcmcard)
657 sprintf(pcmsearch, "pcm.%s.@args.CARD.default.vars", directhw ? "hw" : "plughw");
658 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
659 ALSA_CheckEnvironment(configp, fixedpcmcard);
662 if (fixedpcmdev)
664 sprintf(pcmsearch, "pcm.%s.@args.DEV.default.vars", directhw ? "hw" : "plughw");
665 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
666 ALSA_CheckEnvironment(configp, fixedpcmdev);
669 return 0;
673 /*----------------------------------------------------------------------------
674 ** ALSA_ScanDevices
676 ** Iterate through all discoverable ALSA cards, searching
677 ** for usable PCM devices.
679 ** Parameters:
680 ** directhw Whether to use a direct hardware device or not;
681 ** essentially switches the pcm device name from
682 ** one of 'default:X' or 'plughw:X' to "hw:X"
683 ** defctlcard Alsa's notion of the default ctl card.
684 ** defpcmcard . pcm card
685 ** defpcmdev . pcm device
686 ** fixedctlcard If not -1, then gives the value of ALSA_CTL_CARD
687 ** or equivalent environment variable
688 ** fixedpcmcard If not -1, then gives the value of ALSA_PCM_CARD
689 ** or equivalent environment variable
690 ** fixedpcmdev If not -1, then gives the value of ALSA_PCM_DEVICE
691 ** or equivalent environment variable
693 ** Returns: 0 on success, < 0 on failure
695 static int ALSA_ScanDevices(int directhw,
696 long defctlcard, long defpcmcard, long defpcmdev,
697 int fixedctlcard, int fixedpcmcard, int fixedpcmdev)
699 int card = fixedpcmcard;
700 int scan_devices = (fixedpcmdev == -1);
702 /*------------------------------------------------------------------------
703 ** Loop through all available cards
704 **----------------------------------------------------------------------*/
705 if (card == -1)
706 snd_card_next(&card);
708 for (; card != -1; snd_card_next(&card))
710 char ctlname[256];
711 snd_ctl_t *ctl;
712 int rc;
713 int device;
715 /*--------------------------------------------------------------------
716 ** Try to open a ctl handle; Wine doesn't absolutely require one,
717 ** but it does allow for volume control and for device scanning
718 **------------------------------------------------------------------*/
719 sprintf(ctlname, "hw:%d", fixedctlcard == -1 ? card : fixedctlcard);
720 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
721 if (rc < 0)
723 ctl = NULL;
724 WARN("Unable to open an alsa ctl for [%s] (pcm card %d): %s; not scanning devices\n",
725 ctlname, card, snd_strerror(rc));
726 if (fixedpcmdev == -1)
727 fixedpcmdev = 0;
730 /*--------------------------------------------------------------------
731 ** Loop through all available devices on this card
732 **------------------------------------------------------------------*/
733 device = fixedpcmdev;
734 if (device == -1)
735 snd_ctl_pcm_next_device(ctl, &device);
737 for (; device != -1; snd_ctl_pcm_next_device(ctl, &device))
739 char defaultpcmname[256];
740 char plugpcmname[256];
741 char hwpcmname[256];
742 char *pcmname = NULL;
743 snd_pcm_t *pcm;
745 sprintf(defaultpcmname, "default");
746 sprintf(plugpcmname, "plughw:%d,%d", card, device);
747 sprintf(hwpcmname, "hw:%d,%d", card, device);
749 /*----------------------------------------------------------------
750 ** See if it's a valid playback device
751 **--------------------------------------------------------------*/
752 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_PLAYBACK) == 0)
754 /* If we can, try the default:X device name first */
755 if (! scan_devices && ! directhw)
757 pcmname = defaultpcmname;
758 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
760 else
761 rc = -1;
763 if (rc < 0)
765 pcmname = directhw ? hwpcmname : plugpcmname;
766 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
769 if (rc >= 0)
771 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
772 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, TRUE);
773 else
774 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
775 snd_pcm_close(pcm);
777 else
779 TRACE("Device [%s/%s] failed to open for playback: %s\n",
780 directhw || scan_devices ? "(N/A)" : defaultpcmname,
781 directhw ? hwpcmname : plugpcmname,
782 snd_strerror(rc));
786 /*----------------------------------------------------------------
787 ** See if it's a valid capture device
788 **--------------------------------------------------------------*/
789 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_CAPTURE) == 0)
791 /* If we can, try the default:X device name first */
792 if (! scan_devices && ! directhw)
794 pcmname = defaultpcmname;
795 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
797 else
798 rc = -1;
800 if (rc < 0)
802 pcmname = directhw ? hwpcmname : plugpcmname;
803 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
806 if (rc >= 0)
808 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
809 ALSA_AddCaptureDevice(ctl, pcm, pcmname, TRUE);
810 else
811 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
813 snd_pcm_close(pcm);
815 else
817 TRACE("Device [%s/%s] failed to open for capture: %s\n",
818 directhw || scan_devices ? "(N/A)" : defaultpcmname,
819 directhw ? hwpcmname : plugpcmname,
820 snd_strerror(rc));
824 if (! scan_devices)
825 break;
828 if (ctl)
829 snd_ctl_close(ctl);
831 /*--------------------------------------------------------------------
832 ** If the user has set env variables such that we're pegged to
833 ** a specific card, then break after we've examined it
834 **------------------------------------------------------------------*/
835 if (fixedpcmcard != -1)
836 break;
839 return 0;
843 /*----------------------------------------------------------------------------
844 ** ALSA_PerformDefaultScan
845 ** Perform the basic default scanning for devices within ALSA.
846 ** The hope is that this routine implements a 'correct'
847 ** scanning algorithm from the Alsalib point of view.
849 ** Note that Wine, overall, has other mechanisms to
850 ** override and specify exact CTL and PCM device names,
851 ** but this routine is imagined as the default that
852 ** 99% of users will use.
854 ** The basic algorithm is simple:
855 ** Use snd_card_next to iterate cards; within cards, use
856 ** snd_ctl_pcm_next_device to iterate through devices.
858 ** We add a little complexity by taking into consideration
859 ** environment variables such as ALSA_CARD (et all), and by
860 ** detecting when a given device matches the default specified
861 ** by Alsa.
863 ** Parameters:
864 ** directhw If !0, indicates we should use the hw:X
865 ** PCM interface, rather than first try
866 ** the 'default' device followed by the plughw
867 ** device. (default and plughw do fancy mixing
868 ** and audio scaling, if they are available).
869 ** devscan If TRUE, we should scan all devices, not
870 ** juse use device 0 on each card
872 ** Returns:
873 ** 0 on success
875 ** Effects:
876 ** Invokes the ALSA_AddXXXDevice functions on valid
877 ** looking devices
879 static int ALSA_PerformDefaultScan(int directhw, BOOL devscan)
881 long defctlcard = -1, defpcmcard = -1, defpcmdev = -1;
882 int fixedctlcard = -1, fixedpcmcard = -1, fixedpcmdev = -1;
883 int rc;
885 /* FIXME: We should dlsym the new snd_names_list/snd_names_list_free 1.0.9 apis,
886 ** and use them instead of this scan mechanism if they are present */
888 rc = ALSA_DefaultDevices(directhw, &defctlcard, &defpcmcard, &defpcmdev,
889 &fixedctlcard, &fixedpcmcard, &fixedpcmdev);
890 if (rc)
891 return(rc);
893 if (fixedpcmdev == -1 && ! devscan)
894 fixedpcmdev = 0;
896 return(ALSA_ScanDevices(directhw, defctlcard, defpcmcard, defpcmdev, fixedctlcard, fixedpcmcard, fixedpcmdev));
900 /*----------------------------------------------------------------------------
901 ** ALSA_AddUserSpecifiedDevice
902 ** Add a device given from the registry
904 static int ALSA_AddUserSpecifiedDevice(const char *ctlname, const char *pcmname)
906 int rc;
907 int okay = 0;
908 snd_ctl_t *ctl = NULL;
909 snd_pcm_t *pcm = NULL;
911 if (ctlname)
913 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
914 if (rc < 0)
915 ctl = NULL;
918 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
919 if (rc >= 0)
921 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
922 okay++;
923 snd_pcm_close(pcm);
926 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
927 if (rc >= 0)
929 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
930 okay++;
931 snd_pcm_close(pcm);
934 if (ctl)
935 snd_ctl_close(ctl);
937 return (okay == 0);
941 /*----------------------------------------------------------------------------
942 ** ALSA_WaveInit
943 ** Initialize the Wine Alsa sub system.
944 ** The main task is to probe for and store a list of all appropriate playback
945 ** and capture devices.
946 ** Key control points are from the registry key:
947 ** [Software\Wine\Alsa Driver]
948 ** AutoScanCards Whether or not to scan all known sound cards
949 ** and add them to Wine's list (default yes)
950 ** AutoScanDevices Whether or not to scan all known PCM devices
951 ** on each card (default no)
952 ** UseDirectHW Whether or not to use the hw:X device,
953 ** instead of the fancy default:X or plughw:X device.
954 ** The hw:X device goes straight to the hardware
955 ** without any fancy mixing or audio scaling in between.
956 ** DeviceCount If present, specifies the number of hard coded
957 ** Alsa devices to add to Wine's list; default 0
958 ** DevicePCMn Specifies the Alsa PCM devices to open for
959 ** Device n (where n goes from 1 to DeviceCount)
960 ** DeviceCTLn Specifies the Alsa control devices to open for
961 ** Device n (where n goes from 1 to DeviceCount)
963 ** Using AutoScanCards no, and then Devicexxx info
964 ** is a way to exactly specify the devices used by Wine.
967 LONG ALSA_WaveInit(void)
969 DWORD rc;
970 BOOL AutoScanCards = TRUE;
971 BOOL AutoScanDevices = FALSE;
972 BOOL UseDirectHW = FALSE;
973 DWORD DeviceCount = 0;
974 HKEY key = 0;
975 int i;
977 if (!wine_dlopen("libasound.so.2", RTLD_LAZY|RTLD_GLOBAL, NULL, 0))
979 ERR("Error: ALSA lib needs to be loaded with flags RTLD_LAZY and RTLD_GLOBAL.\n");
980 return -1;
983 /* @@ Wine registry key: HKCU\Software\Wine\Alsa Driver */
984 rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Alsa Driver", 0, KEY_QUERY_VALUE, &key);
985 if (rc == ERROR_SUCCESS)
987 ALSA_RegGetBoolean(key, "AutoScanCards", &AutoScanCards);
988 ALSA_RegGetBoolean(key, "AutoScanDevices", &AutoScanDevices);
989 ALSA_RegGetBoolean(key, "UseDirectHW", &UseDirectHW);
990 ALSA_RegGetInt(key, "DeviceCount", &DeviceCount);
993 if (AutoScanCards)
994 rc = ALSA_PerformDefaultScan(UseDirectHW, AutoScanDevices);
996 for (i = 0; i < DeviceCount; i++)
998 char *ctl_name = NULL;
999 char *pcm_name = NULL;
1000 char value[30];
1002 sprintf(value, "DevicePCM%d", i + 1);
1003 if (ALSA_RegGetString(key, value, &pcm_name) == ERROR_SUCCESS)
1005 sprintf(value, "DeviceCTL%d", i + 1);
1006 ALSA_RegGetString(key, value, &ctl_name);
1007 ALSA_AddUserSpecifiedDevice(ctl_name, pcm_name);
1010 HeapFree(GetProcessHeap(), 0, ctl_name);
1011 HeapFree(GetProcessHeap(), 0, pcm_name);
1014 if (key)
1015 RegCloseKey(key);
1017 return (rc);
1020 #endif /* HAVE_ALSA */