programs/start: use SEE_MASK_NO_CONSOLE flag as default.
[wine/dcerpc.git] / dlls / winealsa.drv / waveinit.c
blob11f8fdd2301967457d41d2752fdab602a97fa917
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 /* 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
59 #include "initguid.h"
60 #include "alsa.h"
62 #include "wine/library.h"
63 #include "wine/unicode.h"
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(wave);
68 #ifdef HAVE_ALSA
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;
78 char pcmname[256];
79 int retcode;
80 snd_pcm_hw_params_t *hwparams;
81 const char *reason = NULL;
82 unsigned int rrate;
84 /* Note that the plug: device masks out a lot of info, we want to avoid that */
85 sprintf(pcmname, "hw:%d,%d", card, device);
86 retcode = snd_pcm_open(&pcm, pcmname, streamtype, SND_PCM_NONBLOCK);
87 if (retcode < 0)
89 /* Note that a busy device isn't automatically disqualified */
90 if (retcode == (-1 * EBUSY))
91 retcode = 0;
92 goto exit;
95 snd_pcm_hw_params_alloca(&hwparams);
97 retcode = snd_pcm_hw_params_any(pcm, hwparams);
98 if (retcode < 0)
100 reason = "Could not retrieve hw_params";
101 goto exit;
104 /* set the count of channels */
105 retcode = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
106 if (retcode < 0)
108 reason = "Could not set channels";
109 goto exit;
112 rrate = 44100;
113 retcode = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rrate, 0);
114 if (retcode < 0)
116 reason = "Could not set rate";
117 goto exit;
120 if (rrate == 0)
122 reason = "Rate came back as 0";
123 goto exit;
126 /* write the parameters to device */
127 retcode = snd_pcm_hw_params(pcm, hwparams);
128 if (retcode < 0)
130 reason = "Could not set hwparams";
131 goto exit;
134 retcode = 0;
136 exit:
137 if (pcm)
138 snd_pcm_close(pcm);
140 if (retcode != 0 && retcode != (-1 * ENOENT))
141 TRACE("Discarding card %d/device %d: %s [%d(%s)]\n", card, device, reason, retcode, snd_strerror(retcode));
143 return retcode;
146 /*----------------------------------------------------------------------------
147 ** ALSA_RegGetString
148 ** Retrieve a string from a registry key
150 static int ALSA_RegGetString(HKEY key, const char *value, char **bufp)
152 DWORD rc;
153 DWORD type;
154 DWORD bufsize;
156 *bufp = NULL;
157 rc = RegQueryValueExA(key, value, NULL, &type, NULL, &bufsize);
158 if (rc != ERROR_SUCCESS)
159 return(rc);
161 if (type != REG_SZ)
162 return 1;
164 *bufp = HeapAlloc(GetProcessHeap(), 0, bufsize);
165 if (! *bufp)
166 return 1;
168 rc = RegQueryValueExA(key, value, NULL, NULL, (LPBYTE)*bufp, &bufsize);
169 return rc;
172 /*----------------------------------------------------------------------------
173 ** ALSA_RegGetBoolean
174 ** Get a string and interpret it as a boolean
177 /* Possible truths:
178 Y(es), T(rue), 1, E(nabled) */
180 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1' || (ch) == 'e' || (ch) == 'E')
181 static int ALSA_RegGetBoolean(HKEY key, const char *value, BOOL *answer)
183 DWORD rc;
184 char *buf = NULL;
186 rc = ALSA_RegGetString(key, value, &buf);
187 if (buf)
189 *answer = FALSE;
190 if (IS_OPTION_TRUE(*buf))
191 *answer = TRUE;
193 HeapFree(GetProcessHeap(), 0, buf);
196 return rc;
199 /*----------------------------------------------------------------------------
200 ** ALSA_RegGetBoolean
201 ** Get a string and interpret it as a DWORD
203 static int ALSA_RegGetInt(HKEY key, const char *value, DWORD *answer)
205 DWORD rc;
206 char *buf = NULL;
208 rc = ALSA_RegGetString(key, value, &buf);
209 if (buf)
211 *answer = atoi(buf);
212 HeapFree(GetProcessHeap(), 0, buf);
215 return rc;
218 /* return a string duplicated on the win32 process heap, free with HeapFree */
219 static char* ALSA_strdup(const char *s) {
220 char *result = HeapAlloc(GetProcessHeap(), 0, strlen(s)+1);
221 if (!result)
222 return NULL;
223 strcpy(result, s);
224 return result;
227 #define ALSA_RETURN_ONFAIL(mycall) \
229 int rc; \
230 {rc = mycall;} \
231 if ((rc) < 0) \
233 ERR("%s failed: %s(%d)\n", #mycall, snd_strerror(rc), rc); \
234 return(rc); \
238 /*----------------------------------------------------------------------------
239 ** ALSA_ComputeCaps
241 ** Given an ALSA PCM, figure out our HW CAPS structure info.
242 ** ctl can be null, pcm is required, as is all output parms.
245 static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm,
246 WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports)
248 snd_pcm_hw_params_t *hw_params;
249 snd_pcm_format_mask_t *fmask;
250 snd_pcm_access_mask_t *acmask;
251 unsigned int ratemin = 0;
252 unsigned int ratemax = 0;
253 unsigned int chmin = 0;
254 unsigned int chmax = 0;
255 int dir = 0;
257 snd_pcm_hw_params_alloca(&hw_params);
258 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_any(pcm, hw_params));
260 snd_pcm_format_mask_alloca(&fmask);
261 snd_pcm_hw_params_get_format_mask(hw_params, fmask);
263 snd_pcm_access_mask_alloca(&acmask);
264 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_get_access_mask(hw_params, acmask));
266 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_get_rate_min(hw_params, &ratemin, &dir));
267 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_get_rate_max(hw_params, &ratemax, &dir));
268 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_get_channels_min(hw_params, &chmin));
269 ALSA_RETURN_ONFAIL(snd_pcm_hw_params_get_channels_max(hw_params, &chmax));
271 #define X(r,v) \
272 if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
274 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
276 if (chmin <= 1 && 1 <= chmax) \
277 *formats |= WAVE_FORMAT_##v##M08; \
278 if (chmin <= 2 && 2 <= chmax) \
279 *formats |= WAVE_FORMAT_##v##S08; \
281 if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
283 if (chmin <= 1 && 1 <= chmax) \
284 *formats |= WAVE_FORMAT_##v##M16; \
285 if (chmin <= 2 && 2 <= chmax) \
286 *formats |= WAVE_FORMAT_##v##S16; \
289 X(11025,1);
290 X(22050,2);
291 X(44100,4);
292 X(48000,48);
293 X(96000,96);
294 #undef X
296 if (chmin > 1)
297 FIXME("Device has a minimum of %d channels\n", chmin);
298 *channels = chmax;
300 /* FIXME: is sample accurate always true ?
301 ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
302 *supports |= WAVECAPS_SAMPLEACCURATE;
304 /* FIXME: NONITERLEAVED and COMPLEX are not supported right now */
305 if ( snd_pcm_access_mask_test( acmask, SND_PCM_ACCESS_MMAP_INTERLEAVED ) )
306 *supports |= WAVECAPS_DIRECTSOUND;
308 /* check for volume control support */
309 if (ctl) {
310 *supports |= WAVECAPS_VOLUME;
312 if (chmin <= 2 && 2 <= chmax)
313 *supports |= WAVECAPS_LRVOLUME;
316 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
317 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
318 WAVE_FORMAT_96M08 | WAVE_FORMAT_1M16 |
319 WAVE_FORMAT_2M16 | WAVE_FORMAT_4M16 |
320 WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16) )
321 *flags |= DSCAPS_PRIMARYMONO;
323 if (*formats & (WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 |
324 WAVE_FORMAT_4S08 | WAVE_FORMAT_48S08 |
325 WAVE_FORMAT_96S08 | WAVE_FORMAT_1S16 |
326 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
327 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
328 *flags |= DSCAPS_PRIMARYSTEREO;
330 if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 |
331 WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 |
332 WAVE_FORMAT_96M08 | WAVE_FORMAT_1S08 |
333 WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 |
334 WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08) )
335 *flags |= DSCAPS_PRIMARY8BIT;
337 if (*formats & (WAVE_FORMAT_1M16 | WAVE_FORMAT_2M16 |
338 WAVE_FORMAT_4M16 | WAVE_FORMAT_48M16 |
339 WAVE_FORMAT_96M16 | WAVE_FORMAT_1S16 |
340 WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 |
341 WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
342 *flags |= DSCAPS_PRIMARY16BIT;
344 return(0);
347 /*----------------------------------------------------------------------------
348 ** ALSA_AddCommonDevice
350 ** Perform Alsa initialization common to both capture and playback
352 ** Side Effect: ww->pcname and ww->ctlname may need to be freed.
354 ** Note: this was originally coded by using snd_pcm_name(pcm), until
355 ** I discovered that with at least one version of alsa lib,
356 ** the use of a pcm named default:0 would cause snd_pcm_name() to fail.
357 ** So passing the name in is logically extraneous. Sigh.
359 static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww)
361 snd_pcm_info_t *infop;
363 snd_pcm_info_alloca(&infop);
364 ALSA_RETURN_ONFAIL(snd_pcm_info(pcm, infop));
366 if (pcm && pcmname)
367 ww->pcmname = ALSA_strdup(pcmname);
368 else
369 return -1;
371 if (ctl && snd_ctl_name(ctl))
372 ww->ctlname = ALSA_strdup(snd_ctl_name(ctl));
374 strcpy(ww->interface_name, "winealsa: ");
375 memcpy(ww->interface_name + strlen(ww->interface_name),
376 ww->pcmname,
377 min(strlen(ww->pcmname), sizeof(ww->interface_name) - strlen("winealsa: ")));
379 strcpy(ww->ds_desc.szDrvname, "winealsa.drv");
381 memcpy(ww->ds_desc.szDesc, snd_pcm_info_get_name(infop),
382 min( (sizeof(ww->ds_desc.szDesc) - 1), strlen(snd_pcm_info_get_name(infop))) );
384 ww->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
385 ww->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
386 ww->ds_caps.dwPrimaryBuffers = 1;
388 return 0;
391 /*----------------------------------------------------------------------------
392 ** ALSA_FreeDevice
394 static void ALSA_FreeDevice(WINE_WAVEDEV *ww)
396 HeapFree(GetProcessHeap(), 0, ww->pcmname);
397 ww->pcmname = NULL;
399 HeapFree(GetProcessHeap(), 0, ww->ctlname);
400 ww->ctlname = NULL;
403 /*----------------------------------------------------------------------------
404 ** ALSA_AddDeviceToArray
406 ** Dynamically size one of the wavein or waveout arrays of devices,
407 ** and add a fully configured device node to the array.
410 static int ALSA_AddDeviceToArray(WINE_WAVEDEV *ww, WINE_WAVEDEV **array,
411 DWORD *count, DWORD *alloced, int isdefault)
413 int i = *count;
415 if (*count >= *alloced)
417 (*alloced) += WAVEDEV_ALLOC_EXTENT_SIZE;
418 if (! (*array))
419 *array = HeapAlloc(GetProcessHeap(), 0, sizeof(*ww) * (*alloced));
420 else
421 *array = HeapReAlloc(GetProcessHeap(), 0, *array, sizeof(*ww) * (*alloced));
423 if (!*array)
425 return -1;
429 /* If this is the default, arrange for it to be the first element */
430 if (isdefault && i > 0)
432 (*array)[*count] = (*array)[0];
433 i = 0;
436 (*array)[i] = *ww;
438 (*count)++;
439 return 0;
442 /*----------------------------------------------------------------------------
443 ** ALSA_AddPlaybackDevice
445 ** Add a given Alsa device to Wine's internal list of Playback
446 ** devices.
448 static int ALSA_AddPlaybackDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
450 WINE_WAVEDEV wwo;
451 int rc;
453 memset(&wwo, '\0', sizeof(wwo));
455 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwo);
456 if (rc)
457 return(rc);
459 MultiByteToWideChar(CP_ACP, 0, wwo.ds_desc.szDesc, -1,
460 wwo.outcaps.szPname, sizeof(wwo.outcaps.szPname)/sizeof(WCHAR));
461 wwo.outcaps.szPname[sizeof(wwo.outcaps.szPname)/sizeof(WCHAR) - 1] = '\0';
463 wwo.outcaps.wMid = MM_CREATIVE;
464 wwo.outcaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
465 wwo.outcaps.vDriverVersion = 0x0100;
467 rc = ALSA_ComputeCaps(ctl, pcm, &wwo.outcaps.wChannels, &wwo.ds_caps.dwFlags,
468 &wwo.outcaps.dwFormats, &wwo.outcaps.dwSupport);
469 if (rc)
471 WARN("Error calculating device caps for pcm [%s]\n", wwo.pcmname);
472 ALSA_FreeDevice(&wwo);
473 return(rc);
476 rc = ALSA_AddDeviceToArray(&wwo, &WOutDev, &ALSA_WodNumDevs, &ALSA_WodNumMallocedDevs, isdefault);
477 if (rc)
478 ALSA_FreeDevice(&wwo);
479 return (rc);
482 /*----------------------------------------------------------------------------
483 ** ALSA_AddCaptureDevice
485 ** Add a given Alsa device to Wine's internal list of Capture
486 ** devices.
488 static int ALSA_AddCaptureDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
490 WINE_WAVEDEV wwi;
491 int rc;
493 memset(&wwi, '\0', sizeof(wwi));
495 rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwi);
496 if (rc)
497 return(rc);
499 MultiByteToWideChar(CP_ACP, 0, wwi.ds_desc.szDesc, -1,
500 wwi.incaps.szPname, sizeof(wwi.incaps.szPname) / sizeof(WCHAR));
501 wwi.incaps.szPname[sizeof(wwi.incaps.szPname)/sizeof(WCHAR) - 1] = '\0';
503 wwi.incaps.wMid = MM_CREATIVE;
504 wwi.incaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
505 wwi.incaps.vDriverVersion = 0x0100;
507 rc = ALSA_ComputeCaps(ctl, pcm, &wwi.incaps.wChannels, &wwi.ds_caps.dwFlags,
508 &wwi.incaps.dwFormats, &wwi.dwSupport);
509 if (rc)
511 WARN("Error calculating device caps for pcm [%s]\n", wwi.pcmname);
512 ALSA_FreeDevice(&wwi);
513 return(rc);
516 if (wwi.dwSupport & WAVECAPS_DIRECTSOUND)
518 FIXME("Add support for DSCapture\n");
519 wwi.dwSupport &= ~WAVECAPS_DIRECTSOUND;
522 rc = ALSA_AddDeviceToArray(&wwi, &WInDev, &ALSA_WidNumDevs, &ALSA_WidNumMallocedDevs, isdefault);
523 if (rc)
524 ALSA_FreeDevice(&wwi);
525 return(rc);
528 /*----------------------------------------------------------------------------
529 ** ALSA_CheckEnvironment
531 ** Given an Alsa style configuration node, scan its subitems
532 ** for environment variable names, and use them to find an override,
533 ** if appropriate.
534 ** This is essentially a long and convolunted way of doing:
535 ** getenv("ALSA_CARD")
536 ** getenv("ALSA_CTL_CARD")
537 ** getenv("ALSA_PCM_CARD")
538 ** getenv("ALSA_PCM_DEVICE")
540 ** The output value is set with the atoi() of the first environment
541 ** variable found to be set, if any; otherwise, it is left alone
543 static void ALSA_CheckEnvironment(snd_config_t *node, int *outvalue)
545 snd_config_iterator_t iter;
547 for (iter = snd_config_iterator_first(node);
548 iter != snd_config_iterator_end(node);
549 iter = snd_config_iterator_next(iter))
551 snd_config_t *leaf = snd_config_iterator_entry(iter);
552 if (snd_config_get_type(leaf) == SND_CONFIG_TYPE_STRING)
554 const char *value;
555 if (snd_config_get_string(leaf, &value) >= 0)
557 char *p = getenv(value);
558 if (p)
560 *outvalue = atoi(p);
561 return;
568 /*----------------------------------------------------------------------------
569 ** ALSA_DefaultDevices
571 ** Jump through Alsa style hoops to (hopefully) properly determine
572 ** Alsa defaults for CTL Card #, as well as for PCM Card + Device #.
573 ** We'll also find out if the user has set any of the environment
574 ** variables that specify we're to use a specific card or device.
576 ** Parameters:
577 ** directhw Whether to use a direct hardware device or not;
578 ** essentially switches the pcm device name from
579 ** one of 'default:X' or 'plughw:X' to "hw:X"
580 ** defctlcard If !NULL, will hold the ctl card number given
581 ** by the ALSA config as the default
582 ** defpcmcard If !NULL, default pcm card #
583 ** defpcmdev If !NULL, default pcm device #
584 ** fixedctlcard If !NULL, and the user set the appropriate
585 ** environment variable, we'll set to the
586 ** card the user specified.
587 ** fixedpcmcard If !NULL, and the user set the appropriate
588 ** environment variable, we'll set to the
589 ** card the user specified.
590 ** fixedpcmdev If !NULL, and the user set the appropriate
591 ** environment variable, we'll set to the
592 ** device the user specified.
594 ** Returns: 0 on success, < 0 on failiure
596 static int ALSA_DefaultDevices(int directhw,
597 long *defctlcard,
598 long *defpcmcard, long *defpcmdev,
599 int *fixedctlcard,
600 int *fixedpcmcard, int *fixedpcmdev)
602 snd_config_t *configp;
603 char pcmsearch[256];
605 ALSA_RETURN_ONFAIL(snd_config_update());
607 if (defctlcard)
608 if (snd_config_search(snd_config, "defaults.ctl.card", &configp) >= 0)
609 snd_config_get_integer(configp, defctlcard);
611 if (defpcmcard)
612 if (snd_config_search(snd_config, "defaults.pcm.card", &configp) >= 0)
613 snd_config_get_integer(configp, defpcmcard);
615 if (defpcmdev)
616 if (snd_config_search(snd_config, "defaults.pcm.device", &configp) >= 0)
617 snd_config_get_integer(configp, defpcmdev);
620 if (fixedctlcard)
622 if (snd_config_search(snd_config, "ctl.hw.@args.CARD.default.vars", &configp) >= 0)
623 ALSA_CheckEnvironment(configp, fixedctlcard);
626 if (fixedpcmcard)
628 sprintf(pcmsearch, "pcm.%s.@args.CARD.default.vars", directhw ? "hw" : "plughw");
629 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
630 ALSA_CheckEnvironment(configp, fixedpcmcard);
633 if (fixedpcmdev)
635 sprintf(pcmsearch, "pcm.%s.@args.DEV.default.vars", directhw ? "hw" : "plughw");
636 if (snd_config_search(snd_config, pcmsearch, &configp) >= 0)
637 ALSA_CheckEnvironment(configp, fixedpcmdev);
640 return 0;
644 /*----------------------------------------------------------------------------
645 ** ALSA_ScanDevices
647 ** Iterate through all discoverable ALSA cards, searching
648 ** for usable PCM devices.
650 ** Parameters:
651 ** directhw Whether to use a direct hardware device or not;
652 ** essentially switches the pcm device name from
653 ** one of 'default:X' or 'plughw:X' to "hw:X"
654 ** defctlcard Alsa's notion of the default ctl card.
655 ** defpcmcard . pcm card
656 ** defpcmdev . pcm device
657 ** fixedctlcard If not -1, then gives the value of ALSA_CTL_CARD
658 ** or equivalent environment variable
659 ** fixedpcmcard If not -1, then gives the value of ALSA_PCM_CARD
660 ** or equivalent environment variable
661 ** fixedpcmdev If not -1, then gives the value of ALSA_PCM_DEVICE
662 ** or equivalent environment variable
664 ** Returns: 0 on success, < 0 on failiure
666 static int ALSA_ScanDevices(int directhw,
667 long defctlcard, long defpcmcard, long defpcmdev,
668 int fixedctlcard, int fixedpcmcard, int fixedpcmdev)
670 int card = fixedpcmcard;
671 int scan_devices = (fixedpcmdev == -1);
673 /*------------------------------------------------------------------------
674 ** Loop through all available cards
675 **----------------------------------------------------------------------*/
676 if (card == -1)
677 snd_card_next(&card);
679 for (; card != -1; snd_card_next(&card))
681 char ctlname[256];
682 snd_ctl_t *ctl;
683 int rc;
684 int device;
686 /*--------------------------------------------------------------------
687 ** Try to open a ctl handle; Wine doesn't absolutely require one,
688 ** but it does allow for volume control and for device scanning
689 **------------------------------------------------------------------*/
690 sprintf(ctlname, "default:%d", fixedctlcard == -1 ? card : fixedctlcard);
691 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
692 if (rc < 0)
694 sprintf(ctlname, "hw:%d", fixedctlcard == -1 ? card : fixedctlcard);
695 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
697 if (rc < 0)
699 ctl = NULL;
700 WARN("Unable to open an alsa ctl for [%s] (pcm card %d): %s; not scanning devices\n",
701 ctlname, card, snd_strerror(rc));
702 if (fixedpcmdev == -1)
703 fixedpcmdev = 0;
706 /*--------------------------------------------------------------------
707 ** Loop through all available devices on this card
708 **------------------------------------------------------------------*/
709 device = fixedpcmdev;
710 if (device == -1)
711 snd_ctl_pcm_next_device(ctl, &device);
713 for (; device != -1; snd_ctl_pcm_next_device(ctl, &device))
715 char defaultpcmname[256];
716 char plugpcmname[256];
717 char hwpcmname[256];
718 char *pcmname = NULL;
719 snd_pcm_t *pcm;
721 sprintf(defaultpcmname, "default:%d", card);
722 sprintf(plugpcmname, "plughw:%d,%d", card, device);
723 sprintf(hwpcmname, "hw:%d,%d", card, device);
725 /*----------------------------------------------------------------
726 ** See if it's a valid playback device
727 **--------------------------------------------------------------*/
728 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_PLAYBACK) == 0)
730 /* If we can, try the default:X device name first */
731 if (! scan_devices && ! directhw)
733 pcmname = defaultpcmname;
734 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
736 else
737 rc = -1;
739 if (rc < 0)
741 pcmname = directhw ? hwpcmname : plugpcmname;
742 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
745 if (rc >= 0)
747 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
748 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, TRUE);
749 else
750 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
751 snd_pcm_close(pcm);
753 else
755 TRACE("Device [%s/%s] failed to open for playback: %s\n",
756 directhw || scan_devices ? "(N/A)" : defaultpcmname,
757 directhw ? hwpcmname : plugpcmname,
758 snd_strerror(rc));
762 /*----------------------------------------------------------------
763 ** See if it's a valid capture device
764 **--------------------------------------------------------------*/
765 if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_CAPTURE) == 0)
767 /* If we can, try the default:X device name first */
768 if (! scan_devices && ! directhw)
770 pcmname = defaultpcmname;
771 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
773 else
774 rc = -1;
776 if (rc < 0)
778 pcmname = directhw ? hwpcmname : plugpcmname;
779 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
782 if (rc >= 0)
784 if (defctlcard == card && defpcmcard == card && defpcmdev == device)
785 ALSA_AddCaptureDevice(ctl, pcm, pcmname, TRUE);
786 else
787 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
789 snd_pcm_close(pcm);
791 else
793 TRACE("Device [%s/%s] failed to open for capture: %s\n",
794 directhw || scan_devices ? "(N/A)" : defaultpcmname,
795 directhw ? hwpcmname : plugpcmname,
796 snd_strerror(rc));
800 if (! scan_devices)
801 break;
804 if (ctl)
805 snd_ctl_close(ctl);
807 /*--------------------------------------------------------------------
808 ** If the user has set env variables such that we're pegged to
809 ** a specific card, then break after we've examined it
810 **------------------------------------------------------------------*/
811 if (fixedpcmcard != -1)
812 break;
815 return 0;
819 /*----------------------------------------------------------------------------
820 ** ALSA_PerformDefaultScan
821 ** Perform the basic default scanning for devices within ALSA.
822 ** The hope is that this routine implements a 'correct'
823 ** scanning algorithm from the Alsalib point of view.
825 ** Note that Wine, overall, has other mechanisms to
826 ** override and specify exact CTL and PCM device names,
827 ** but this routine is imagined as the default that
828 ** 99% of users will use.
830 ** The basic algorithm is simple:
831 ** Use snd_card_next to iterate cards; within cards, use
832 ** snd_ctl_pcm_next_device to iterate through devices.
834 ** We add a little complexity by taking into consideration
835 ** environment variables such as ALSA_CARD (et all), and by
836 ** detecting when a given device matches the default specified
837 ** by Alsa.
839 ** Parameters:
840 ** directhw If !0, indicates we should use the hw:X
841 ** PCM interface, rather than first try
842 ** the 'default' device followed by the plughw
843 ** device. (default and plughw do fancy mixing
844 ** and audio scaling, if they are available).
845 ** devscan If TRUE, we should scan all devices, not
846 ** juse use device 0 on each card
848 ** Returns:
849 ** 0 on success
851 ** Effects:
852 ** Invokes the ALSA_AddXXXDevice functions on valid
853 ** looking devices
855 static int ALSA_PerformDefaultScan(int directhw, BOOL devscan)
857 long defctlcard = -1, defpcmcard = -1, defpcmdev = -1;
858 int fixedctlcard = -1, fixedpcmcard = -1, fixedpcmdev = -1;
859 int rc;
861 /* FIXME: We should dlsym the new snd_names_list/snd_names_list_free 1.0.9 apis,
862 ** and use them instead of this scan mechanism if they are present */
864 rc = ALSA_DefaultDevices(directhw, &defctlcard, &defpcmcard, &defpcmdev,
865 &fixedctlcard, &fixedpcmcard, &fixedpcmdev);
866 if (rc)
867 return(rc);
869 if (fixedpcmdev == -1 && ! devscan)
870 fixedpcmdev = 0;
872 return(ALSA_ScanDevices(directhw, defctlcard, defpcmcard, defpcmdev, fixedctlcard, fixedpcmcard, fixedpcmdev));
876 /*----------------------------------------------------------------------------
877 ** ALSA_AddUserSpecifiedDevice
878 ** Add a device given from the registry
880 static int ALSA_AddUserSpecifiedDevice(const char *ctlname, const char *pcmname)
882 int rc;
883 int okay = 0;
884 snd_ctl_t *ctl = NULL;
885 snd_pcm_t *pcm = NULL;
887 if (ctlname)
889 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
890 if (rc < 0)
891 ctl = NULL;
894 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
895 if (rc >= 0)
897 ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
898 okay++;
899 snd_pcm_close(pcm);
902 rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
903 if (rc >= 0)
905 ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
906 okay++;
907 snd_pcm_close(pcm);
910 if (ctl)
911 snd_ctl_close(ctl);
913 return (okay == 0);
917 /*----------------------------------------------------------------------------
918 ** ALSA_WaveInit
919 ** Initialize the Wine Alsa sub system.
920 ** The main task is to probe for and store a list of all appropriate playback
921 ** and capture devices.
922 ** Key control points are from the registry key:
923 ** [Software\Wine\Alsa Driver]
924 ** AutoScanCards Whether or not to scan all known sound cards
925 ** and add them to Wine's list (default yes)
926 ** AutoScanDevices Whether or not to scan all known PCM devices
927 ** on each card (default no)
928 ** UseDirectHW Whether or not to use the hw:X device,
929 ** instead of the fancy default:X or plughw:X device.
930 ** The hw:X device goes straight to the hardware
931 ** without any fancy mixing or audio scaling in between.
932 ** DeviceCount If present, specifies the number of hard coded
933 ** Alsa devices to add to Wine's list; default 0
934 ** DevicePCMn Specifies the Alsa PCM devices to open for
935 ** Device n (where n goes from 1 to DeviceCount)
936 ** DeviceCTLn Specifies the Alsa control devices to open for
937 ** Device n (where n goes from 1 to DeviceCount)
939 ** Using AutoScanCards no, and then Devicexxx info
940 ** is a way to exactly specify the devices used by Wine.
943 LONG ALSA_WaveInit(void)
945 DWORD rc;
946 BOOL AutoScanCards = TRUE;
947 BOOL AutoScanDevices = FALSE;
948 BOOL UseDirectHW = FALSE;
949 DWORD DeviceCount = 0;
950 HKEY key = 0;
951 int i;
953 if (!wine_dlopen("libasound.so.2", RTLD_LAZY|RTLD_GLOBAL, NULL, 0))
955 ERR("Error: ALSA lib needs to be loaded with flags RTLD_LAZY and RTLD_GLOBAL.\n");
956 return -1;
959 /* @@ Wine registry key: HKCU\Software\Wine\Alsa Driver */
960 rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Alsa Driver", 0, KEY_QUERY_VALUE, &key);
961 if (rc == ERROR_SUCCESS)
963 ALSA_RegGetBoolean(key, "AutoScanCards", &AutoScanCards);
964 ALSA_RegGetBoolean(key, "AutoScanDevices", &AutoScanDevices);
965 ALSA_RegGetBoolean(key, "UseDirectHW", &UseDirectHW);
966 ALSA_RegGetInt(key, "DeviceCount", &DeviceCount);
969 if (AutoScanCards)
970 rc = ALSA_PerformDefaultScan(UseDirectHW, AutoScanDevices);
972 for (i = 0; i < DeviceCount; i++)
974 char *ctl_name = NULL;
975 char *pcm_name = NULL;
976 char value[30];
978 sprintf(value, "DevicePCM%d", i + 1);
979 if (ALSA_RegGetString(key, value, &pcm_name) == ERROR_SUCCESS)
981 sprintf(value, "DeviceCTL%d", i + 1);
982 ALSA_RegGetString(key, value, &ctl_name);
983 ALSA_AddUserSpecifiedDevice(ctl_name, pcm_name);
986 HeapFree(GetProcessHeap(), 0, ctl_name);
987 HeapFree(GetProcessHeap(), 0, pcm_name);
990 if (key)
991 RegCloseKey(key);
993 return (rc);
996 #endif /* HAVE_ALSA */