mmdevapi/tests: Add tests for IAudioClient::GetCurrentPadding.
[wine] / dlls / winealsa.drv / waveinit.c
1 /*
2  * Sample Wine Driver for Advanced Linux Sound System (ALSA)
3  *      Based on version <final> of the ALSA API
4  *
5  * This file performs the initialisation and scanning of the sound subsystem.
6  *
7  * Copyright    2002 Eric Pouech
8  *              2002 Marco Pietrobono
9  *              2003 Christian Costa : WaveIn support
10  *              2006-2007 Maarten Lankhorst
11  *
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.
16  *
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.
21  *
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
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29
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"
54
55 #include "alsa.h"
56
57 #include "wine/library.h"
58 #include "wine/unicode.h"
59 #include "wine/debug.h"
60
61 WINE_DEFAULT_DEBUG_CHANNEL(wave);
62
63 /*----------------------------------------------------------------------------
64 **  ALSA_TestDeviceForWine
65 **
66 **      Test to see if a given device is sufficient for Wine.
67 */
68 static int ALSA_TestDeviceForWine(int card, int device,  snd_pcm_stream_t streamtype)
69 {
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;
76
77     hwparams = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
78
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)
83     {
84         /* Note that a busy device isn't automatically disqualified */
85         if (retcode == (-1 * EBUSY))
86             retcode = 0;
87         goto exit;
88     }
89
90     retcode = snd_pcm_hw_params_any(pcm, hwparams);
91     if (retcode < 0)
92     {
93         reason = "Could not retrieve hw_params";
94         goto exit;
95     }
96
97     /* set the count of channels */
98     retcode = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
99     if (retcode < 0)
100     {
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 */
102     }
103     if (retcode < 0)
104     {
105         reason = "Could not set channels";
106         goto exit;
107     }
108
109     rrate = 44100;
110     retcode = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rrate, 0);
111     if (retcode < 0)
112     {
113         reason = "Could not set rate";
114         goto exit;
115     }
116
117     if (rrate == 0)
118     {
119         reason = "Rate came back as 0";
120         goto exit;
121     }
122
123     /* write the parameters to device */
124     retcode = snd_pcm_hw_params(pcm, hwparams);
125     if (retcode < 0)
126     {
127         reason = "Could not set hwparams";
128         goto exit;
129     }
130
131     retcode = 0;
132
133 exit:
134     if (pcm)
135         snd_pcm_close(pcm);
136     HeapFree( GetProcessHeap(), 0, hwparams );
137
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));
140
141     return retcode;
142 }
143
144 /*----------------------------------------------------------------------------
145 ** ALSA_RegGetString
146 **  Retrieve a string from a registry key
147 */
148 static int ALSA_RegGetString(HKEY key, const char *value, char **bufp)
149 {
150     DWORD rc;
151     DWORD type;
152     DWORD bufsize;
153
154     *bufp = NULL;
155     rc = RegQueryValueExA(key, value, NULL, &type, NULL, &bufsize);
156     if (rc != ERROR_SUCCESS)
157         return(rc);
158
159     if (type != REG_SZ)
160         return 1;
161
162     *bufp = HeapAlloc(GetProcessHeap(), 0, bufsize);
163     if (! *bufp)
164         return 1;
165
166     rc = RegQueryValueExA(key, value, NULL, NULL, (LPBYTE)*bufp, &bufsize);
167     return rc;
168 }
169
170 /*----------------------------------------------------------------------------
171 ** ALSA_RegGetBoolean
172 **  Get a string and interpret it as a boolean
173 */
174
175 /* Possible truths:
176    Y(es), T(rue), 1, E(nabled) */
177
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)
180 {
181     DWORD rc;
182     char *buf = NULL;
183
184     rc = ALSA_RegGetString(key, value, &buf);
185     if (buf)
186     {
187         *answer = FALSE;
188         if (IS_OPTION_TRUE(*buf))
189             *answer = TRUE;
190
191         HeapFree(GetProcessHeap(), 0, buf);
192     }
193
194     return rc;
195 }
196
197 /*----------------------------------------------------------------------------
198 ** ALSA_RegGetInt
199 **  Get a string and interpret it as a DWORD
200 */
201 static int ALSA_RegGetInt(HKEY key, const char *value, DWORD *answer)
202 {
203     DWORD rc;
204     char *buf = NULL;
205
206     rc = ALSA_RegGetString(key, value, &buf);
207     if (buf)
208     {
209         *answer = atoi(buf);
210         HeapFree(GetProcessHeap(), 0, buf);
211     }
212
213     return rc;
214 }
215
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;
223 }
224
225 #define ALSA_RETURN_ONFAIL(mycall)                                      \
226 {                                                                       \
227     int rc;                                                             \
228     {rc = mycall;}                                                      \
229     if ((rc) < 0)                                                       \
230     {                                                                   \
231         ERR("%s failed:  %s(%d)\n", #mycall, snd_strerror(rc), rc);     \
232         return(rc);                                                     \
233     }                                                                   \
234 }
235
236 /*----------------------------------------------------------------------------
237 **  ALSA_ComputeCaps
238 **
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.
241 **
242 */
243 static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm,
244         WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports)
245 {
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;
254
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() );
258
259     if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done;
260
261     snd_pcm_hw_params_get_format_mask(hw_params, fmask);
262
263     if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done;
264
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;
269
270 #define X(r,v) \
271     if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
272     { \
273        if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
274        { \
275           if (chmin <= 1 && 1 <= chmax) \
276               *formats |= WAVE_FORMAT_##v##M08; \
277           if (chmin <= 2 && 2 <= chmax) \
278               *formats |= WAVE_FORMAT_##v##S08; \
279        } \
280        if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
281        { \
282           if (chmin <= 1 && 1 <= chmax) \
283               *formats |= WAVE_FORMAT_##v##M16; \
284           if (chmin <= 2 && 2 <= chmax) \
285               *formats |= WAVE_FORMAT_##v##S16; \
286        } \
287     }
288     X(11025,1);
289     X(22050,2);
290     X(44100,4);
291     X(48000,48);
292     X(96000,96);
293 #undef X
294
295     if (chmin > 1)
296         FIXME("Device has a minimum of %d channels\n", chmin);
297     *channels = chmax;
298
299     /* FIXME: is sample accurate always true ?
300     ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
301     *supports |= WAVECAPS_SAMPLEACCURATE;
302
303     *supports |= WAVECAPS_DIRECTSOUND;
304
305     /* check for volume control support */
306     if (ctl) {
307         if (snd_ctl_name(ctl))
308         {
309             snd_hctl_t *hctl;
310             if (snd_hctl_open(&hctl, snd_ctl_name(ctl), 0) >= 0)
311             {
312                 snd_hctl_load(hctl);
313                 if (!ALSA_CheckSetVolume( hctl, NULL, NULL, NULL, NULL, NULL, NULL, NULL ))
314                 {
315                     *supports |= WAVECAPS_VOLUME;
316                     if (chmin <= 2 && 2 <= chmax)
317                         *supports |= WAVECAPS_LRVOLUME;
318                 }
319                 snd_hctl_free(hctl);
320                 snd_hctl_close(hctl);
321             }
322         }
323     }
324
325     *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE;
326     *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
327     *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
328
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;
335
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;
342
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;
349
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;
356
357     rc = 0;
358
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;
365 }
366
367 /*----------------------------------------------------------------------------
368 **  ALSA_AddCommonDevice
369 **
370 **      Perform Alsa initialization common to both capture and playback
371 **
372 **  Side Effect:  ww->pcname and ww->ctlname may need to be freed.
373 **
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.
378 */
379 static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww)
380 {
381     snd_pcm_info_t *infop;
382     int rc;
383
384     infop = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_info_sizeof() );
385     if ((rc = snd_pcm_info(pcm, infop)) < 0)
386     {
387         HeapFree( GetProcessHeap(), 0, infop );
388         return rc;
389     }
390
391     if (pcm && pcmname)
392         ww->pcmname = ALSA_strdup(pcmname);
393     else
394     {
395         HeapFree( GetProcessHeap(), 0, infop );
396         return -1;
397     }
398
399     if (ctl && snd_ctl_name(ctl))
400         ww->ctlname = ALSA_strdup(snd_ctl_name(ctl));
401
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:   ")));
406
407     strcpy(ww->ds_desc.szDrvname, "winealsa.drv");
408
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))) );
411
412     ww->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
413     ww->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
414     ww->ds_caps.dwPrimaryBuffers = 1;
415
416     HeapFree( GetProcessHeap(), 0, infop );
417     return 0;
418 }
419
420 /*----------------------------------------------------------------------------
421 ** ALSA_FreeDevice
422 */
423 static void ALSA_FreeDevice(WINE_WAVEDEV *ww)
424 {
425     HeapFree(GetProcessHeap(), 0, ww->pcmname);
426     ww->pcmname = NULL;
427
428     HeapFree(GetProcessHeap(), 0, ww->ctlname);
429     ww->ctlname = NULL;
430 }
431
432 /*----------------------------------------------------------------------------
433 **  ALSA_AddDeviceToArray
434 **
435 **      Dynamically size one of the wavein or waveout arrays of devices,
436 **  and add a fully configured device node to the array.
437 **
438 */
439 static int ALSA_AddDeviceToArray(WINE_WAVEDEV *ww, WINE_WAVEDEV **array,
440         DWORD *count, DWORD *alloced, int isdefault)
441 {
442     int i = *count;
443
444     if (*count >= *alloced)
445     {
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));
451
452         if (!*array)
453         {
454             return -1;
455         }
456     }
457
458     /* If this is the default, arrange for it to be the first element */
459     if (isdefault && i > 0)
460     {
461         (*array)[*count] = (*array)[0];
462         i = 0;
463     }
464
465     (*array)[i] = *ww;
466
467     (*count)++;
468     return 0;
469 }
470
471 /*----------------------------------------------------------------------------
472 **  ALSA_AddPlaybackDevice
473 **
474 **      Add a given Alsa device to Wine's internal list of Playback
475 **  devices.
476 */
477 static int ALSA_AddPlaybackDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
478 {
479     WINE_WAVEDEV    wwo;
480     int rc;
481
482     memset(&wwo, '\0', sizeof(wwo));
483
484     rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwo);
485     if (rc)
486         return(rc);
487
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';
491
492     wwo.outcaps.wMid = MM_CREATIVE;
493     wwo.outcaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
494     wwo.outcaps.vDriverVersion = 0x0100;
495
496     rc = ALSA_ComputeCaps(ctl, pcm, &wwo.outcaps.wChannels, &wwo.ds_caps.dwFlags,
497             &wwo.outcaps.dwFormats, &wwo.outcaps.dwSupport);
498     if (rc)
499     {
500         WARN("Error calculating device caps for pcm [%s]\n", wwo.pcmname);
501         ALSA_FreeDevice(&wwo);
502         return(rc);
503     }
504
505     rc = ALSA_AddDeviceToArray(&wwo, &WOutDev, &ALSA_WodNumDevs, &ALSA_WodNumMallocedDevs, isdefault);
506     if (rc)
507         ALSA_FreeDevice(&wwo);
508     return (rc);
509 }
510
511 /*----------------------------------------------------------------------------
512 **  ALSA_AddCaptureDevice
513 **
514 **      Add a given Alsa device to Wine's internal list of Capture
515 **  devices.
516 */
517 static int ALSA_AddCaptureDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault)
518 {
519     WINE_WAVEDEV    wwi;
520     int rc;
521
522     memset(&wwi, '\0', sizeof(wwi));
523
524     rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwi);
525     if (rc)
526         return(rc);
527
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';
531
532     wwi.incaps.wMid = MM_CREATIVE;
533     wwi.incaps.wPid = MM_CREATIVE_SBP16_WAVEOUT;
534     wwi.incaps.vDriverVersion = 0x0100;
535
536     rc = ALSA_ComputeCaps(ctl, pcm, &wwi.incaps.wChannels, &wwi.ds_caps.dwFlags,
537             &wwi.incaps.dwFormats, &wwi.dwSupport);
538     if (rc)
539     {
540         WARN("Error calculating device caps for pcm [%s]\n", wwi.pcmname);
541         ALSA_FreeDevice(&wwi);
542         return(rc);
543     }
544
545     rc = ALSA_AddDeviceToArray(&wwi, &WInDev, &ALSA_WidNumDevs, &ALSA_WidNumMallocedDevs, isdefault);
546     if (rc)
547         ALSA_FreeDevice(&wwi);
548     return(rc);
549 }
550
551 /*----------------------------------------------------------------------------
552 **  ALSA_CheckEnvironment
553 **
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")
562 **
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
565 */
566 static void ALSA_CheckEnvironment(snd_config_t *node, int *outvalue)
567 {
568     snd_config_iterator_t iter;
569
570     for (iter = snd_config_iterator_first(node);
571          iter != snd_config_iterator_end(node);
572          iter = snd_config_iterator_next(iter))
573     {
574         snd_config_t *leaf = snd_config_iterator_entry(iter);
575         if (snd_config_get_type(leaf) == SND_CONFIG_TYPE_STRING)
576         {
577             const char *value;
578             if (snd_config_get_string(leaf, &value) >= 0)
579             {
580                 char *p = getenv(value);
581                 if (p)
582                 {
583                     *outvalue = atoi(p);
584                     return;
585                 }
586             }
587         }
588     }
589 }
590
591 /*----------------------------------------------------------------------------
592 **  ALSA_DefaultDevices
593 **
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.
598 **
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.
616 **
617 **  Returns:  0 on success, < 0 on failure
618 */
619 static int ALSA_DefaultDevices(int directhw,
620             long *defctlcard,
621             long *defpcmcard, long *defpcmdev,
622             int *fixedctlcard,
623             int *fixedpcmcard, int *fixedpcmdev)
624 {
625     snd_config_t   *configp;
626     char pcmsearch[256];
627
628     ALSA_RETURN_ONFAIL(snd_config_update());
629
630     if (defctlcard)
631         if (snd_config_search(snd_config, "defaults.ctl.card", &configp) >= 0)
632             snd_config_get_integer(configp, defctlcard);
633
634     if (defpcmcard)
635         if (snd_config_search(snd_config, "defaults.pcm.card", &configp) >= 0)
636             snd_config_get_integer(configp, defpcmcard);
637
638     if (defpcmdev)
639         if (snd_config_search(snd_config, "defaults.pcm.device", &configp) >= 0)
640             snd_config_get_integer(configp, defpcmdev);
641
642
643     if (fixedctlcard)
644     {
645         if (snd_config_search(snd_config, "ctl.hw.@args.CARD.default.vars", &configp) >= 0)
646             ALSA_CheckEnvironment(configp, fixedctlcard);
647     }
648
649     if (fixedpcmcard)
650     {
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);
654     }
655
656     if (fixedpcmdev)
657     {
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);
661     }
662
663     return 0;
664 }
665
666
667 /*----------------------------------------------------------------------------
668 **  ALSA_ScanDevices
669 **
670 **      Iterate through all discoverable ALSA cards, searching
671 **  for usable PCM devices.
672 **
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
686 **
687 **  Returns:  0 on success, < 0 on failure
688 */
689 static int ALSA_ScanDevices(int directhw,
690         long defctlcard, long defpcmcard, long defpcmdev,
691         int fixedctlcard, int fixedpcmcard, int fixedpcmdev)
692 {
693     int card = fixedpcmcard;
694     int scan_devices = (fixedpcmdev == -1);
695
696     /*------------------------------------------------------------------------
697     ** Loop through all available cards
698     **----------------------------------------------------------------------*/
699     if (card == -1)
700         snd_card_next(&card);
701
702     for (; card != -1; snd_card_next(&card))
703     {
704         char ctlname[256];
705         snd_ctl_t *ctl;
706         int rc;
707         int device;
708
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)
716         {
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;
722         }
723
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);
730
731         for (; device != -1; snd_ctl_pcm_next_device(ctl, &device))
732         {
733             char defaultpcmname[256];
734             char plugpcmname[256];
735             char hwpcmname[256];
736             char *pcmname = NULL;
737             snd_pcm_t *pcm;
738
739             sprintf(defaultpcmname, "default");
740             sprintf(plugpcmname,    "plughw:%d,%d", card, device);
741             sprintf(hwpcmname,      "hw:%d,%d", card, device);
742
743             /*----------------------------------------------------------------
744             ** See if it's a valid playback device
745             **--------------------------------------------------------------*/
746             if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_PLAYBACK) == 0)
747             {
748                 /* If we can, try the default:X device name first */
749                 if (! scan_devices && ! directhw)
750                 {
751                     pcmname = defaultpcmname;
752                     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
753                 }
754                 else
755                     rc = -1;
756
757                 if (rc < 0)
758                 {
759                     pcmname = directhw ? hwpcmname : plugpcmname;
760                     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
761                 }
762
763                 if (rc >= 0)
764                 {
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);
770                 }
771                 else
772                 {
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));
777                 }
778             }
779
780             /*----------------------------------------------------------------
781             ** See if it's a valid capture device
782             **--------------------------------------------------------------*/
783             if (ALSA_TestDeviceForWine(card, device, SND_PCM_STREAM_CAPTURE) == 0)
784             {
785                 /* If we can, try the default:X device name first */
786                 if (! scan_devices && ! directhw)
787                 {
788                     pcmname = defaultpcmname;
789                     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
790                 }
791                 else
792                     rc = -1;
793
794                 if (rc < 0)
795                 {
796                     pcmname = directhw ? hwpcmname : plugpcmname;
797                     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
798                 }
799
800                 if (rc >= 0)
801                 {
802                     if (defctlcard == card && defpcmcard == card && defpcmdev == device)
803                         ALSA_AddCaptureDevice(ctl, pcm, pcmname, TRUE);
804                     else
805                         ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
806
807                     snd_pcm_close(pcm);
808                 }
809                 else
810                 {
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));
815                 }
816             }
817
818             if (! scan_devices)
819                 break;
820         }
821
822         if (ctl)
823             snd_ctl_close(ctl);
824
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;
831     }
832
833     return 0;
834
835 }
836
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.
842 **
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.
847 **
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.
851 **
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.
856 **
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
865 **
866 **  Returns:
867 **      0   on success
868 **
869 **  Effects:
870 **      Invokes the ALSA_AddXXXDevice functions on valid
871 **  looking devices
872 */
873 static int ALSA_PerformDefaultScan(int directhw, BOOL devscan)
874 {
875     long defctlcard = -1, defpcmcard = -1, defpcmdev = -1;
876     int fixedctlcard = -1, fixedpcmcard = -1, fixedpcmdev = -1;
877     int rc;
878
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         */
881
882     rc = ALSA_DefaultDevices(directhw, &defctlcard, &defpcmcard, &defpcmdev,
883             &fixedctlcard, &fixedpcmcard, &fixedpcmdev);
884     if (rc)
885         return(rc);
886
887     if (fixedpcmdev == -1 && ! devscan)
888         fixedpcmdev = 0;
889
890     return(ALSA_ScanDevices(directhw, defctlcard, defpcmcard, defpcmdev, fixedctlcard, fixedpcmcard, fixedpcmdev));
891 }
892
893
894 /*----------------------------------------------------------------------------
895 ** ALSA_AddUserSpecifiedDevice
896 **  Add a device given from the registry
897 */
898 static int ALSA_AddUserSpecifiedDevice(const char *ctlname, const char *pcmname)
899 {
900     int rc;
901     int okay = 0;
902     snd_ctl_t *ctl = NULL;
903     snd_pcm_t *pcm = NULL;
904
905     if (ctlname)
906     {
907         rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
908         if (rc < 0)
909             ctl = NULL;
910     }
911
912     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
913     if (rc >= 0)
914     {
915         ALSA_AddPlaybackDevice(ctl, pcm, pcmname, FALSE);
916         okay++;
917         snd_pcm_close(pcm);
918     }
919
920     rc = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
921     if (rc >= 0)
922     {
923         ALSA_AddCaptureDevice(ctl, pcm, pcmname, FALSE);
924         okay++;
925         snd_pcm_close(pcm);
926     }
927
928     if (ctl)
929         snd_ctl_close(ctl);
930
931     return (okay == 0);
932 }
933
934
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)
956 **
957 **                          Using AutoScanCards no, and then Devicexxx info
958 **                          is a way to exactly specify the devices used by Wine.
959 **
960 */
961 void ALSA_WaveInit(void)
962 {
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;
971
972     if (loaded++)
973         return;
974
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)
978     {
979         ALSA_RegGetBoolean(key, "AutoScanCards", &AutoScanCards);
980         ALSA_RegGetBoolean(key, "AutoScanDevices", &AutoScanDevices);
981         ALSA_RegGetBoolean(key, "UseDirectHW", &UseDirectHW);
982         ALSA_RegGetInt(key, "DeviceCount", &DeviceCount);
983     }
984
985     if (AutoScanCards)
986         ALSA_PerformDefaultScan(UseDirectHW, AutoScanDevices);
987
988     for (i = 0; i < DeviceCount; i++)
989     {
990         char *ctl_name = NULL;
991         char *pcm_name = NULL;
992         char value[30];
993
994         sprintf(value, "DevicePCM%d", i + 1);
995         if (ALSA_RegGetString(key, value, &pcm_name) == ERROR_SUCCESS)
996         {
997             sprintf(value, "DeviceCTL%d", i + 1);
998             ALSA_RegGetString(key, value, &ctl_name);
999             ALSA_AddUserSpecifiedDevice(ctl_name, pcm_name);
1000         }
1001
1002         HeapFree(GetProcessHeap(), 0, ctl_name);
1003         HeapFree(GetProcessHeap(), 0, pcm_name);
1004     }
1005
1006     if (key)
1007         RegCloseKey(key);
1008 }