comctl32: Update the version in the created version to the highest current version...
[wine] / dlls / winealsa.drv / waveinit.c
CommitLineData
2d2feb07
ML
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
66WINE_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*/
75static 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
9fce052c
AJ
84 hwparams = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
85
2d2feb07
ML
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
2d2feb07
ML
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
136exit:
137 if (pcm)
138 snd_pcm_close(pcm);
9fce052c 139 HeapFree( GetProcessHeap(), 0, hwparams );
2d2feb07
ML
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*/
151static 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')
182static 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_RegGetBoolean
202** Get a string and interpret it as a DWORD
203*/
204static 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 */
220static 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*/
246static 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;
9fce052c
AJ
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() );
2d2feb07 261
9fce052c 262 if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done;
2d2feb07 263
2d2feb07
ML
264 snd_pcm_hw_params_get_format_mask(hw_params, fmask);
265
9fce052c 266 if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done;
2d2feb07 267
9fce052c
AJ
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;
2d2feb07
ML
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) {
edff5338
AJ
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 }
2d2feb07
ML
328 }
329
a083c241
ML
330 *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE;
331 *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
332 *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
333
2d2feb07
ML
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
9fce052c
AJ
362 rc = 0;
363
364done:
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;
2d2feb07
ML
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*/
384static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww)
385{
386 snd_pcm_info_t *infop;
9fce052c 387 int rc;
2d2feb07 388
9fce052c
AJ
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 }
2d2feb07
ML
395
396 if (pcm && pcmname)
397 ww->pcmname = ALSA_strdup(pcmname);
398 else
9fce052c
AJ
399 {
400 HeapFree( GetProcessHeap(), 0, infop );
2d2feb07 401 return -1;
9fce052c 402 }
2d2feb07
ML
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
9fce052c 421 HeapFree( GetProcessHeap(), 0, infop );
2d2feb07
ML
422 return 0;
423}
424
425/*----------------------------------------------------------------------------
426** ALSA_FreeDevice
427*/
428static 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*/
444static 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*/
482static 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*/
522static 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*/
571static 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*/
624static 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*/
694static 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 **------------------------------------------------------------------*/
1ae9a9d6 718 sprintf(ctlname, "hw:%d", fixedctlcard == -1 ? card : fixedctlcard);
2d2feb07
ML
719 rc = snd_ctl_open(&ctl, ctlname, SND_CTL_NONBLOCK);
720 if (rc < 0)
2d2feb07
ML
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*/
878static 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*/
903static 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*/
966LONG 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 */