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