advpack: Mark internal symbols as hidden.
[wine/multimedia.git] / dlls / winealsa.drv / waveinit.c
blobe218197bd365be9a0e2748727232b0e49e469c47
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"
28 #include "wine/port.h"
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <errno.h>
38 #include <limits.h>
39 #include <fcntl.h>
40 #ifdef HAVE_SYS_IOCTL_H
41 # include <sys/ioctl.h>
42 #endif
43 #ifdef HAVE_SYS_MMAN_H
44 # include <sys/mman.h>
45 #endif
46 #include "windef.h"
47 #include "winbase.h"
48 #include "wingdi.h"
49 #include "winerror.h"
50 #include "winuser.h"
51 #include "winnls.h"
52 #include "winreg.h"
53 #include "mmddk.h"
55 #include "alsa.h"
57 #include "wine/library.h"
58 #include "wine/unicode.h"
59 #include "wine/debug.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(wave);
63 /*----------------------------------------------------------------------------
64 ** ALSA_TestDeviceForWine
66 ** Test to see if a given device is sufficient for Wine.
68 static int ALSA_TestDeviceForWine(int card, int device, snd_pcm_stream_t streamtype)
70 snd_pcm_t *pcm = NULL;
71 char pcmname[256];
72 int retcode;
73 snd_pcm_hw_params_t *hwparams;
74 const char *reason = NULL;
75 unsigned int rrate;
77 hwparams = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
79 /* Note that the plug: device masks out a lot of info, we want to avoid that */
80 sprintf(pcmname, "hw:%d,%d", card, device);
81 retcode = snd_pcm_open(&pcm, pcmname, streamtype, SND_PCM_NONBLOCK);
82 if (retcode < 0)
84 /* Note that a busy device isn't automatically disqualified */
85 if (retcode == (-1 * EBUSY))
86 retcode = 0;
87 goto exit;
90 retcode = snd_pcm_hw_params_any(pcm, hwparams);
91 if (retcode < 0)
93 reason = "Could not retrieve hw_params";
94 goto exit;
97 /* set the count of channels */
98 retcode = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
99 if (retcode < 0)
101 retcode = snd_pcm_hw_params_set_channels(pcm, hwparams, 1); /* If we can't open stereo, try mono; this is vital for snd_usb_audio microphones */
103 if (retcode < 0)
105 reason = "Could not set channels";
106 goto exit;
109 rrate = 44100;
110 retcode = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rrate, 0);
111 if (retcode < 0)
113 reason = "Could not set rate";
114 goto exit;
117 if (rrate == 0)
119 reason = "Rate came back as 0";
120 goto exit;
123 /* write the parameters to device */
124 retcode = snd_pcm_hw_params(pcm, hwparams);
125 if (retcode < 0)
127 reason = "Could not set hwparams";
128 goto exit;
131 retcode = 0;
133 exit:
134 if (pcm)
135 snd_pcm_close(pcm);
136 HeapFree( GetProcessHeap(), 0, hwparams );
138 if (retcode != 0 && retcode != (-1 * ENOENT))
139 TRACE("Discarding card %d/device %d: %s [%d(%s)]\n", card, device, reason, retcode, snd_strerror(retcode));
141 return retcode;
144 /*----------------------------------------------------------------------------
145 ** ALSA_RegGetString
146 ** Retrieve a string from a registry key
148 static int ALSA_RegGetString(HKEY key, const char *value, char **bufp)
150 DWORD rc;
151 DWORD type;
152 DWORD bufsize;
154 *bufp = NULL;
155 rc = RegQueryValueExA(key, value, NULL, &type, NULL, &bufsize);
156 if (rc != ERROR_SUCCESS)
157 return(rc);
159 if (type != REG_SZ)
160 return 1;
162 *bufp = HeapAlloc(GetProcessHeap(), 0, bufsize);
163 if (! *bufp)
164 return 1;
166 rc = RegQueryValueExA(key, value, NULL, NULL, (LPBYTE)*bufp, &bufsize);
167 return rc;
170 /*----------------------------------------------------------------------------
171 ** ALSA_RegGetBoolean
172 ** Get a string and interpret it as a boolean
175 /* Possible truths:
176 Y(es), T(rue), 1, E(nabled) */
178 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1' || (ch) == 'e' || (ch) == 'E')
179 static int ALSA_RegGetBoolean(HKEY key, const char *value, BOOL *answer)
181 DWORD rc;
182 char *buf = NULL;
184 rc = ALSA_RegGetString(key, value, &buf);
185 if (buf)
187 *answer = FALSE;
188 if (IS_OPTION_TRUE(*buf))
189 *answer = TRUE;
191 HeapFree(GetProcessHeap(), 0, buf);
194 return rc;
197 /*----------------------------------------------------------------------------
198 ** ALSA_RegGetInt
199 ** Get a string and interpret it as a DWORD
201 static int ALSA_RegGetInt(HKEY key, const char *value, DWORD *answer)
203 DWORD rc;
204 char *buf = NULL;
206 rc = ALSA_RegGetString(key, value, &buf);
207 if (buf)
209 *answer = atoi(buf);
210 HeapFree(GetProcessHeap(), 0, buf);
213 return rc;
216 /* return a string duplicated on the win32 process heap, free with HeapFree */
217 static char* ALSA_strdup(const char *s) {
218 char *result = HeapAlloc(GetProcessHeap(), 0, strlen(s)+1);
219 if (!result)
220 return NULL;
221 strcpy(result, s);
222 return result;
225 #define ALSA_RETURN_ONFAIL(mycall) \
227 int rc; \
228 {rc = mycall;} \
229 if ((rc) < 0) \
231 ERR("%s failed: %s(%d)\n", #mycall, snd_strerror(rc), rc); \
232 return(rc); \
236 /*----------------------------------------------------------------------------
237 ** ALSA_ComputeCaps
239 ** Given an ALSA PCM, figure out our HW CAPS structure info.
240 ** ctl can be null, pcm is required, as is all output parms.
243 static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm,
244 WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports)
246 snd_pcm_hw_params_t *hw_params;
247 snd_pcm_format_mask_t *fmask;
248 snd_pcm_access_mask_t *acmask;
249 unsigned int ratemin = 0;
250 unsigned int ratemax = 0;
251 unsigned int chmin = 0;
252 unsigned int chmax = 0;
253 int rc, dir = 0;
255 hw_params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
256 fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof() );
257 acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof() );
259 if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done;
261 snd_pcm_hw_params_get_format_mask(hw_params, fmask);
263 if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done;
265 if ((rc = snd_pcm_hw_params_get_rate_min(hw_params, &ratemin, &dir)) < 0) goto done;
266 if ((rc = snd_pcm_hw_params_get_rate_max(hw_params, &ratemax, &dir)) < 0) goto done;
267 if ((rc = snd_pcm_hw_params_get_channels_min(hw_params, &chmin)) < 0) goto done;
268 if ((rc = snd_pcm_hw_params_get_channels_max(hw_params, &chmax)) < 0) goto done;
270 #define X(r,v) \
271 if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
273 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
275 if (chmin <= 1 && 1 <= chmax) \
276 *formats |= WAVE_FORMAT_##v##M08; \
277 if (chmin <= 2 && 2 <= chmax) \
278 *formats |= WAVE_FORMAT_##v##S08; \
280 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
282 if (chmin <= 1 && 1 <= chmax) \
283 *formats |= WAVE_FORMAT_##v##M16; \
284 if (chmin <= 2 && 2 <= chmax) \
285 *formats |= WAVE_FORMAT_##v##S16; \
288 X(11025,1);
289 X(22050,2);
290 X(44100,4);
291 X(48000,48);
292 X(96000,96);
293 #undef X
295 if (chmin > 1)
296 FIXME("Device has a minimum of %d channels\n", chmin);
297 *channels = chmax;
299 /* FIXME: is sample accurate always true ?
300 ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
301 *supports |= WAVECAPS_SAMPLEACCURATE;
303 *supports |= WAVECAPS_DIRECTSOUND;
305 /* check for volume control support */
306 if (ctl) {
307 if (snd_ctl_name(ctl))
309 snd_hctl_t *hctl;
310 if (snd_hctl_open(&hctl, snd_ctl_name(ctl), 0) >= 0)
312 snd_hctl_load(hctl);
313 if (!ALSA_CheckSetVolume( hctl, NULL, NULL, NULL, NULL, NULL, NULL, NULL ))
315 *supports |= WAVECAPS_VOLUME;
316 if (chmin <= 2 && 2 <= chmax)
317 *supports |= WAVECAPS_LRVOLUME;
319 snd_hctl_free(hctl);
320 snd_hctl_close(hctl);
325 *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE;
326 *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
327 *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
329 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
330 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
331 WAVE_FORMAT_96M08 | WAVE_FORMAT_1M16 |
332 WAVE_FORMAT_2M16 | WAVE_FORMAT_4M16 |
333 WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16) )
334 *flags |= DSCAPS_PRIMARYMONO;
336 if (*formats & (WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 |
337 WAVE_FORMAT_4S08 | WAVE_FORMAT_48S08 |
338 WAVE_FORMAT_96S08 | WAVE_FORMAT_1S16 |
339 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
340 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
341 *flags |= DSCAPS_PRIMARYSTEREO;
343 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
344 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
345 WAVE_FORMAT_96M08 | WAVE_FORMAT_1S08 |
346 WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 |
347 WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08) )
348 *flags |= DSCAPS_PRIMARY8BIT;
350 if (*formats & (WAVE_FORMAT_1M16 | WAVE_FORMAT_2M16 |
351 WAVE_FORMAT_4M16 | WAVE_FORMAT_48M16 |
352 WAVE_FORMAT_96M16 | WAVE_FORMAT_1S16 |
353 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
354 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
355 *flags |= DSCAPS_PRIMARY16BIT;
357 rc = 0;
359 done:
360 if (rc < 0) ERR("failed: %s(%d)\n", snd_strerror(rc), rc);
361 HeapFree( GetProcessHeap(), 0, hw_params );
362 HeapFree( GetProcessHeap(), 0, fmask );
363 HeapFree( GetProcessHeap(), 0, acmask );
364 return rc;
367 /*----------------------------------------------------------------------------
368 ** ALSA_AddCommonDevice
370 ** Perform Alsa initialization common to both capture and playback
372 ** Side Effect: ww->pcname and ww->ctlname may need to be freed.
374 ** Note: this was originally coded by using snd_pcm_name(pcm), until
375 ** I discovered that with at least one version of alsa lib,
376 ** the use of a pcm named default:0 would cause snd_pcm_name() to fail.
377 ** So passing the name in is logically extraneous. Sigh.
379 static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww)
381 snd_pcm_info_t *infop;
382 int rc;
384 infop = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_info_sizeof() );
385 if ((rc = snd_pcm_info(pcm, infop)) < 0)
387 HeapFree( GetProcessHeap(), 0, infop );
388 return rc;
391 if (pcm && pcmname)
392 ww->pcmname = ALSA_strdup(pcmname);
393 else
395 HeapFree( GetProcessHeap(), 0, infop );
396 return -1;
399 if (ctl && snd_ctl_name(ctl))
400 ww->ctlname = ALSA_strdup(snd_ctl_name(ctl));
402 strcpy(ww->interface_name, "winealsa: ");
403 memcpy(ww->interface_name + strlen(ww->interface_name),
404 ww->pcmname,
405 min(strlen(ww->pcmname), sizeof(ww->interface_name) - strlen("winealsa: ")));
407 strcpy(ww->ds_desc.szDrvname, "winealsa.drv");
409 memcpy(ww->ds_desc.szDesc, snd_pcm_info_get_name(infop),
410 min( (sizeof(ww->ds_desc.szDesc) - 1), strlen(snd_pcm_info_get_name(infop))) );
412 ww->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
413 ww->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
414 ww->ds_caps.dwPrimaryBuffers = 1;
416 HeapFree( GetProcessHeap(), 0, infop );
417 return 0;
420 /*----------------------------------------------------------------------------
421 ** ALSA_FreeDevice
423 static void ALSA_FreeDevice(WINE_WAVEDEV *ww)
425 HeapFree(GetProcessHeap(), 0, ww->pcmname);
426 ww->pcmname = NULL;
428 HeapFree(GetProcessHeap(), 0, ww->ctlname);
429 ww->ctlname = NULL;
432 /*----------------------------------------------------------------------------
433 ** ALSA_AddDeviceToArray
435 ** Dynamically size one of the wavein or waveout arrays of devices,
436 ** and add a fully configured device node to the array.
439 static int ALSA_AddDeviceToArray(WINE_WAVEDEV *ww, WINE_WAVEDEV **array,
440 DWORD *count, DWORD *alloced, int isdefault)
442 int i = *count;
444 if (*count >= *alloced)
446 (*alloced) += WAVEDEV_ALLOC_EXTENT_SIZE;
447 if (! (*array))
448 *array = HeapAlloc(GetProcessHeap(), 0, sizeof(*ww) * (*alloced));
449 else
450 *array = HeapReAlloc(GetProcessHeap(), 0, *array, sizeof(*ww) * (*alloced));
452 if (!*array)
454 return -1;
458 /* If this is the default, arrange for it to be the first element */
459 if (isdefault && i > 0)
461 (*array)[*count] = (*array)[0];
462 i = 0;
465 (*array)[i] = *ww;
467 (*count)++;
468 return 0;
471 /*----------------------------------------------------------------------------
472 ** ALSA_AddPlaybackDevice
474 ** Add a given Alsa device to Wine's internal list of Playback
475 ** devices.
477 static int ALSA_AddPlaybackDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
479 WINE_WAVEDEV wwo;
480 int rc;
482 memset(&wwo, '\0', sizeof(wwo));
484 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwo);
485 if (rc)
486 return(rc);
488 MultiByteToWideChar(CP_UNIXCP, 0, wwo.ds_desc.szDesc, -1,
489 wwo.outcaps.szPname, sizeof(wwo.outcaps.szPname)/sizeof(WCHAR));
490 wwo.outcaps.szPname[sizeof(wwo.outcaps.szPname)/sizeof(WCHAR) - 1] = '\0';
492 wwo.outcaps.wMid = MM_CREATIVE;
493 wwo.outcaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
494 wwo.outcaps.vDriverVersion = 0x0100;
496 rc = ALSA_ComputeCaps(ctl, pcm, &wwo.outcaps.wChannels, &wwo.ds_caps.dwFlags,
497 &wwo.outcaps.dwFormats, &wwo.outcaps.dwSupport);
498 if (rc)
500 WARN("Error calculating device caps for pcm [%s]\n", wwo.pcmname);
501 ALSA_FreeDevice(&wwo);
502 return(rc);
505 rc = ALSA_AddDeviceToArray(&wwo, &WOutDev, &ALSA_WodNumDevs, &ALSA_WodNumMallocedDevs, isdefault);
506 if (rc)
507 ALSA_FreeDevice(&wwo);
508 return (rc);
511 /*----------------------------------------------------------------------------
512 ** ALSA_AddCaptureDevice
514 ** Add a given Alsa device to Wine's internal list of Capture
515 ** devices.
517 static int ALSA_AddCaptureDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
519 WINE_WAVEDEV wwi;
520 int rc;
522 memset(&wwi, '\0', sizeof(wwi));
524 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwi);
525 if (rc)
526 return(rc);
528 MultiByteToWideChar(CP_UNIXCP, 0, wwi.ds_desc.szDesc, -1,
529 wwi.incaps.szPname, sizeof(wwi.incaps.szPname) / sizeof(WCHAR));
530 wwi.incaps.szPname[sizeof(wwi.incaps.szPname)/sizeof(WCHAR) - 1] = '\0';
532 wwi.incaps.wMid = MM_CREATIVE;
533 wwi.incaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
534 wwi.incaps.vDriverVersion = 0x0100;
536 rc = ALSA_ComputeCaps(ctl, pcm, &wwi.incaps.wChannels, &wwi.ds_caps.dwFlags,
537 &wwi.incaps.dwFormats, &wwi.dwSupport);
538 if (rc)
540 WARN("Error calculating device caps for pcm [%s]\n", wwi.pcmname);
541 ALSA_FreeDevice(&wwi);
542 return(rc);
545 rc = ALSA_AddDeviceToArray(&wwi, &WInDev, &ALSA_WidNumDevs, &ALSA_WidNumMallocedDevs, isdefault);
546 if (rc)
547 ALSA_FreeDevice(&wwi);
548 return(rc);
551 /*----------------------------------------------------------------------------
552 ** ALSA_CheckEnvironment
554 ** Given an Alsa style configuration node, scan its subitems
555 ** for environment variable names, and use them to find an override,
556 ** if appropriate.
557 ** This is essentially a long and convoluted way of doing:
558 ** getenv("ALSA_CARD")
559 ** getenv("ALSA_CTL_CARD")
560 ** getenv("ALSA_PCM_CARD")
561 ** getenv("ALSA_PCM_DEVICE")
563 ** The output value is set with the atoi() of the first environment
564 ** variable found to be set, if any; otherwise, it is left alone
566 static void ALSA_CheckEnvironment(snd_config_t *node, int *outvalue)
568 snd_config_iterator_t iter;
570 for (iter = snd_config_iterator_first(node);
571 iter != snd_config_iterator_end(node);
572 iter = snd_config_iterator_next(iter))
574 snd_config_t *leaf = snd_config_iterator_entry(iter);
575 if (snd_config_get_type(leaf) == SND_CONFIG_TYPE_STRING)
577 const char *value;
578 if (snd_config_get_string(leaf, &value) >= 0)
580 char *p = getenv(value);
581 if (p)
583 *outvalue = atoi(p);
584 return;
591 /*----------------------------------------------------------------------------
592 ** ALSA_DefaultDevices
594 ** Jump through Alsa style hoops to (hopefully) properly determine
595 ** Alsa defaults for CTL Card #, as well as for PCM Card + Device #.
596 ** We'll also find out if the user has set any of the environment
597 ** variables that specify we're to use a specific card or device.
599 ** Parameters:
600 ** directhw Whether to use a direct hardware device or not;
601 ** essentially switches the pcm device name from
602 ** one of 'default:X' or 'plughw:X' to "hw:X"
603 ** defctlcard If !NULL, will hold the ctl card number given
604 ** by the ALSA config as the default
605 ** defpcmcard If !NULL, default pcm card #
606 ** defpcmdev If !NULL, default pcm device #
607 ** fixedctlcard If !NULL, and the user set the appropriate
608 ** environment variable, we'll set to the
609 ** card the user specified.
610 ** fixedpcmcard If !NULL, and the user set the appropriate
611 ** environment variable, we'll set to the
612 ** card the user specified.
613 ** fixedpcmdev If !NULL, and the user set the appropriate
614 ** environment variable, we'll set to the
615 ** device the user specified.
617 ** Returns: 0 on success, < 0 on failure
619 static int ALSA_DefaultDevices(int directhw,
620 long *defctlcard,
621 long *defpcmcard, long *defpcmdev,
622 int *fixedctlcard,
623 int *fixedpcmcard, int *fixedpcmdev)
625 snd_config_t *configp;
626 char pcmsearch[256];
628 ALSA_RETURN_ONFAIL(snd_config_update());
630 if (defctlcard)
631 if (snd_config_search(snd_config, "defaults.ctl.card", &configp) >= 0)
632 snd_config_get_integer(configp, defctlcard);
634 if (defpcmcard)
635 if (snd_config_search(snd_config, "defaults.pcm.card", &configp) >= 0)
636 snd_config_get_integer(configp, defpcmcard);
638 if (defpcmdev)
639 if (snd_config_search(snd_config, "defaults.pcm.device", &configp) >= 0)
640 snd_config_get_integer(configp, defpcmdev);
643 if (fixedctlcard)
645 if (snd_config_search(snd_config, "ctl.hw.@args.CARD.default.vars", &configp) >= 0)
646 ALSA_CheckEnvironment(configp, fixedctlcard);
649 if (fixedpcmcard)
651 sprintf(pcmsearch, "pcm.%s.@args.CARD.default.vars", directhw ? "hw" : "plughw");
652 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
653 ALSA_CheckEnvironment(configp, fixedpcmcard);
656 if (fixedpcmdev)
658 sprintf(pcmsearch, "pcm.%s.@args.DEV.default.vars", directhw ? "hw" : "plughw");
659 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
660 ALSA_CheckEnvironment(configp, fixedpcmdev);
663 return 0;
667 /*----------------------------------------------------------------------------
668 ** ALSA_ScanDevices
670 ** Iterate through all discoverable ALSA cards, searching
671 ** for usable PCM devices.
673 ** Parameters:
674 ** directhw Whether to use a direct hardware device or not;
675 ** essentially switches the pcm device name from
676 ** one of 'default:X' or 'plughw:X' to "hw:X"
677 ** defctlcard Alsa's notion of the default ctl card.
678 ** defpcmcard . pcm card
679 ** defpcmdev . pcm device
680 ** fixedctlcard If not -1, then gives the value of ALSA_CTL_CARD
681 ** or equivalent environment variable
682 ** fixedpcmcard If not -1, then gives the value of ALSA_PCM_CARD
683 ** or equivalent environment variable
684 ** fixedpcmdev If not -1, then gives the value of ALSA_PCM_DEVICE
685 ** or equivalent environment variable
687 ** Returns: 0 on success, < 0 on failure
689 static int ALSA_ScanDevices(int directhw,
690 long defctlcard, long defpcmcard, long defpcmdev,
691 int fixedctlcard, int fixedpcmcard, int fixedpcmdev)
693 int card = fixedpcmcard;
694 int scan_devices = (fixedpcmdev == -1);
696 /*------------------------------------------------------------------------
697 ** Loop through all available cards
698 **----------------------------------------------------------------------*/
699 if (card == -1)
700 snd_card_next(&card);
702 for (; card != -1; snd_card_next(&card))
704 char ctlname[256];
705 snd_ctl_t *ctl;
706 int rc;
707 int device;
709 /*--------------------------------------------------------------------
710 ** Try to open a ctl handle; Wine doesn't absolutely require one,
711 ** but it does allow for volume control and for device scanning
712 **------------------------------------------------------------------*/
713 sprintf(ctlname, "hw:%d", fixedctlcard == -1 ? card : fixedctlcard);
714 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
715 if (rc < 0)
717 ctl = NULL;
718 WARN("Unable to open an alsa ctl for [%s] (pcm card %d): %s; not scanning devices\n",
719 ctlname, card, snd_strerror(rc));
720 if (fixedpcmdev == -1)
721 fixedpcmdev = 0;
724 /*--------------------------------------------------------------------
725 ** Loop through all available devices on this card
726 **------------------------------------------------------------------*/
727 device = fixedpcmdev;
728 if (device == -1)
729 snd_ctl_pcm_next_device(ctl, &device);
731 for (; device != -1; snd_ctl_pcm_next_device(ctl, &device))
733 char defaultpcmname[256];
734 char plugpcmname[256];
735 char hwpcmname[256];
736 char *pcmname = NULL;
737 snd_pcm_t *pcm;
739 sprintf(defaultpcmname, "default");
740 sprintf(plugpcmname, "plughw:%d,%d", card, device);
741 sprintf(hwpcmname, "hw:%d,%d", card, device);
743 /*----------------------------------------------------------------
744 ** See if it's a valid playback device
745 **--------------------------------------------------------------*/
746 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_PLAYBACK) == 0)
748 /* If we can, try the default:X device name first */
749 if (! scan_devices && ! directhw)
751 pcmname = defaultpcmname;
752 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
754 else
755 rc = -1;
757 if (rc < 0)
759 pcmname = directhw ? hwpcmname : plugpcmname;
760 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
763 if (rc >= 0)
765 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
766 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, TRUE);
767 else
768 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
769 snd_pcm_close(pcm);
771 else
773 TRACE("Device [%s/%s] failed to open for playback: %s\n",
774 directhw || scan_devices ? "(N/A)" : defaultpcmname,
775 directhw ? hwpcmname : plugpcmname,
776 snd_strerror(rc));
780 /*----------------------------------------------------------------
781 ** See if it's a valid capture device
782 **--------------------------------------------------------------*/
783 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_CAPTURE) == 0)
785 /* If we can, try the default:X device name first */
786 if (! scan_devices && ! directhw)
788 pcmname = defaultpcmname;
789 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
791 else
792 rc = -1;
794 if (rc < 0)
796 pcmname = directhw ? hwpcmname : plugpcmname;
797 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
800 if (rc >= 0)
802 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
803 ALSA_AddCaptureDevice(ctl, pcm, pcmname, TRUE);
804 else
805 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
807 snd_pcm_close(pcm);
809 else
811 TRACE("Device [%s/%s] failed to open for capture: %s\n",
812 directhw || scan_devices ? "(N/A)" : defaultpcmname,
813 directhw ? hwpcmname : plugpcmname,
814 snd_strerror(rc));
818 if (! scan_devices)
819 break;
822 if (ctl)
823 snd_ctl_close(ctl);
825 /*--------------------------------------------------------------------
826 ** If the user has set env variables such that we're pegged to
827 ** a specific card, then break after we've examined it
828 **------------------------------------------------------------------*/
829 if (fixedpcmcard != -1)
830 break;
833 return 0;
837 /*----------------------------------------------------------------------------
838 ** ALSA_PerformDefaultScan
839 ** Perform the basic default scanning for devices within ALSA.
840 ** The hope is that this routine implements a 'correct'
841 ** scanning algorithm from the Alsalib point of view.
843 ** Note that Wine, overall, has other mechanisms to
844 ** override and specify exact CTL and PCM device names,
845 ** but this routine is imagined as the default that
846 ** 99% of users will use.
848 ** The basic algorithm is simple:
849 ** Use snd_card_next to iterate cards; within cards, use
850 ** snd_ctl_pcm_next_device to iterate through devices.
852 ** We add a little complexity by taking into consideration
853 ** environment variables such as ALSA_CARD (et all), and by
854 ** detecting when a given device matches the default specified
855 ** by Alsa.
857 ** Parameters:
858 ** directhw If !0, indicates we should use the hw:X
859 ** PCM interface, rather than first try
860 ** the 'default' device followed by the plughw
861 ** device. (default and plughw do fancy mixing
862 ** and audio scaling, if they are available).
863 ** devscan If TRUE, we should scan all devices, not
864 ** juse use device 0 on each card
866 ** Returns:
867 ** 0 on success
869 ** Effects:
870 ** Invokes the ALSA_AddXXXDevice functions on valid
871 ** looking devices
873 static int ALSA_PerformDefaultScan(int directhw, BOOL devscan)
875 long defctlcard = -1, defpcmcard = -1, defpcmdev = -1;
876 int fixedctlcard = -1, fixedpcmcard = -1, fixedpcmdev = -1;
877 int rc;
879 /* FIXME: We should dlsym the new snd_names_list/snd_names_list_free 1.0.9 apis,
880 ** and use them instead of this scan mechanism if they are present */
882 rc = ALSA_DefaultDevices(directhw, &defctlcard, &defpcmcard, &defpcmdev,
883 &fixedctlcard, &fixedpcmcard, &fixedpcmdev);
884 if (rc)
885 return(rc);
887 if (fixedpcmdev == -1 && ! devscan)
888 fixedpcmdev = 0;
890 return(ALSA_ScanDevices(directhw, defctlcard, defpcmcard, defpcmdev, fixedctlcard, fixedpcmcard, fixedpcmdev));
894 /*----------------------------------------------------------------------------
895 ** ALSA_AddUserSpecifiedDevice
896 ** Add a device given from the registry
898 static int ALSA_AddUserSpecifiedDevice(const char *ctlname, const char *pcmname)
900 int rc;
901 int okay = 0;
902 snd_ctl_t *ctl = NULL;
903 snd_pcm_t *pcm = NULL;
905 if (ctlname)
907 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
908 if (rc < 0)
909 ctl = NULL;
912 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
913 if (rc >= 0)
915 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
916 okay++;
917 snd_pcm_close(pcm);
920 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
921 if (rc >= 0)
923 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
924 okay++;
925 snd_pcm_close(pcm);
928 if (ctl)
929 snd_ctl_close(ctl);
931 return (okay == 0);
935 /*----------------------------------------------------------------------------
936 ** ALSA_WaveInit
937 ** Initialize the Wine Alsa sub system.
938 ** The main task is to probe for and store a list of all appropriate playback
939 ** and capture devices.
940 ** Key control points are from the registry key:
941 ** [Software\Wine\Alsa Driver]
942 ** AutoScanCards Whether or not to scan all known sound cards
943 ** and add them to Wine's list (default yes)
944 ** AutoScanDevices Whether or not to scan all known PCM devices
945 ** on each card (default no)
946 ** UseDirectHW Whether or not to use the hw:X device,
947 ** instead of the fancy default:X or plughw:X device.
948 ** The hw:X device goes straight to the hardware
949 ** without any fancy mixing or audio scaling in between.
950 ** DeviceCount If present, specifies the number of hard coded
951 ** Alsa devices to add to Wine's list; default 0
952 ** DevicePCMn Specifies the Alsa PCM devices to open for
953 ** Device n (where n goes from 1 to DeviceCount)
954 ** DeviceCTLn Specifies the Alsa control devices to open for
955 ** Device n (where n goes from 1 to DeviceCount)
957 ** Using AutoScanCards no, and then Devicexxx info
958 ** is a way to exactly specify the devices used by Wine.
961 void ALSA_WaveInit(void)
963 DWORD rc;
964 BOOL AutoScanCards = TRUE;
965 BOOL AutoScanDevices = FALSE;
966 BOOL UseDirectHW = FALSE;
967 DWORD DeviceCount = 0;
968 HKEY key = 0;
969 int i;
970 static int loaded;
972 if (loaded++)
973 return;
975 /* @@ Wine registry key: HKCU\Software\Wine\Alsa Driver */
976 rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Alsa Driver", 0, KEY_QUERY_VALUE, &key);
977 if (rc == ERROR_SUCCESS)
979 ALSA_RegGetBoolean(key, "AutoScanCards", &AutoScanCards);
980 ALSA_RegGetBoolean(key, "AutoScanDevices", &AutoScanDevices);
981 ALSA_RegGetBoolean(key, "UseDirectHW", &UseDirectHW);
982 ALSA_RegGetInt(key, "DeviceCount", &DeviceCount);
985 if (AutoScanCards)
986 ALSA_PerformDefaultScan(UseDirectHW, AutoScanDevices);
988 for (i = 0; i < DeviceCount; i++)
990 char *ctl_name = NULL;
991 char *pcm_name = NULL;
992 char value[30];
994 sprintf(value, "DevicePCM%d", i + 1);
995 if (ALSA_RegGetString(key, value, &pcm_name) == ERROR_SUCCESS)
997 sprintf(value, "DeviceCTL%d", i + 1);
998 ALSA_RegGetString(key, value, &ctl_name);
999 ALSA_AddUserSpecifiedDevice(ctl_name, pcm_name);
1002 HeapFree(GetProcessHeap(), 0, ctl_name);
1003 HeapFree(GetProcessHeap(), 0, pcm_name);
1006 if (key)
1007 RegCloseKey(key);