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