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