This patch fixes bug #12706 and creates a mixer for snd-usb-audio cards,
which have only a single Mic control and nothing else. Subsequent
patches may be needed to make this useful depending on configuration.
I am including this here for commentary before I submit to wine-patches.
This is my first patchset to WINE, so please forgive and correct me if I
am "doing it wrong".
Thanks
Jeff
---
dlls/winealsa.drv/mixer.c | 58
++++++++++++++++++++++++++++++++++-----------
1 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/dlls/winealsa.drv/mixer.c b/dlls/winealsa.drv/mixer.c
index cfdf95f..6ab6840 100644
--- a/dlls/winealsa.drv/mixer.c
+++ b/dlls/winealsa.drv/mixer.c
@@ -245,6 +245,10 @@ static void fillcontrols(mixer *mmixer)
for (id = 0; id < mmixer->chans; ++id)
{
line *mline = &mmixer->lines[id];
+ if (!mline->elem)
+ {
+ break;
+ }
int ofs = CONTROLSPERLINE * id;
int x;
long min, max;
@@ -332,17 +336,21 @@ static void filllines(mixer *mmixer, snd_mixer_elem_t *mastelem, snd_mixer_elem_
snd_mixer_elem_t *elem;
line *mline = mmixer->lines;
- /* Master control */
- MultiByteToWideChar(CP_UNIXCP, 0, snd_mixer_selem_get_name(mastelem), -1, mline->name, sizeof(mline->name)/sizeof(WCHAR));
- mline->component = getcomponenttype(snd_mixer_selem_get_name(mastelem));
- mline->dst = 0;
- mline->capt = 0;
- mline->elem = mastelem;
- mline->chans = chans(mmixer, mastelem, 0);
-
- snd_mixer_elem_set_callback(mastelem, &elem_callback);
- snd_mixer_elem_set_callback_private(mastelem, mmixer);
-
+ if (mastelem) {
+ /* Master control */
+ MultiByteToWideChar(CP_UNIXCP, 0, snd_mixer_selem_get_name(mastelem), -1, mline->name, sizeof(mline->name)/sizeof(WCHAR));
+ mline->component = getcomponenttype(snd_mixer_selem_get_name(mastelem));
+ mline->dst = 0;
+ mline->capt = 0;
+ mline->elem = mastelem;
+ mline->chans = chans(mmixer, mastelem, 0);
+
+ snd_mixer_elem_set_callback(mastelem, &elem_callback);
+ snd_mixer_elem_set_callback_private(mastelem, mmixer);
+ } else {
+ MultiByteToWideChar(CP_UNIXCP, 0, "Empty Master Element", -1, mline->name, sizeof(mline->name)/sizeof(WCHAR));
+ }
+
/* Capture control
* Note: since mmixer->dests = 1, it means only playback control is visible
* This makes sense, because if there are no capture sources capture control
@@ -395,6 +403,22 @@ static void filllines(mixer *mmixer, snd_mixer_elem_t *mastelem, snd_mixer_elem_
}
}
+static void filllines_no_master(mixer *mmixer, snd_mixer_elem_t *captelem, int capt)
+{
+ snd_mixer_elem_t *elem;
+ line *mline = mmixer->lines;
+
+ MultiByteToWideChar(CP_UNIXCP, 0, snd_mixer_selem_get_name(captelem), -1, mline->name, sizeof(mline->name)/sizeof(WCHAR));
+ mline->component = getcomponenttype(snd_mixer_selem_get_name(captelem));
+ mline->dst = 0;
+ mline->capt = 1;
+ mline->elem = captelem;
+ mline->chans = chans(mmixer, captelem, 1);
+
+ snd_mixer_elem_set_callback(captelem, &elem_callback);
+ snd_mixer_elem_set_callback_private(captelem, mmixer);
+}
+
/* Windows api wants to have a 'master' device to which all slaves are attached
* There are 2 ones in this code:
* - 'Master', fall back to 'Headphone' if unavailable, and if that's not available 'PCM'
@@ -414,7 +438,7 @@ static void ALSA_MixerInit(void)
char cardind[6], cardname[10];
snd_ctl_t *ctl;
- snd_mixer_elem_t *elem, *mastelem = NULL, *headelem = NULL, *captelem = NULL, *pcmelem = NULL;
+ snd_mixer_elem_t *elem, *mastelem = NULL, *headelem = NULL, *captelem = NULL, *pcmelem = NULL, *micelem = NULL;
memset(info, 0, snd_ctl_card_info_sizeof());
memset(&mixdev[mixnum], 0, sizeof(*mixdev));
@@ -470,6 +494,9 @@ static void ALSA_MixerInit(void)
mastelem = elem;
else if (!strcasecmp(snd_mixer_selem_get_name(elem), "Capture") && !captelem)
captelem = elem;
+ else if (!strcasecmp(snd_mixer_selem_get_name(elem), "Mic") && !micelem && !mastelem)
+ // this is what snd-usb-audio mics look like; just a Mic control and that's it.
+ micelem = elem;
else if (!blacklisted(elem))
{
DWORD comp = getcomponenttype(snd_mixer_selem_get_name(elem));
@@ -519,7 +546,7 @@ static void ALSA_MixerInit(void)
mastelem = pcmelem;
capcontrols -= !!snd_mixer_selem_has_capture_switch(mastelem);
}
- else if (!mastelem)
+ else if (!mastelem && !captelem && !micelem)
{
/* If there is nothing sensible that can act as 'Master' control, something is wrong */
FIXME("No master control found on %s, disabling mixer\n", snd_ctl_card_info_get_name(info));
@@ -549,7 +576,10 @@ static void ALSA_MixerInit(void)
if (!mixdev[mixnum].lines || !mixdev[mixnum].controls)
goto close;
- filllines(&mixdev[mixnum], mastelem, captelem, capcontrols);
+ if (mastelem)
+ filllines(&mixdev[mixnum], mastelem, captelem, capcontrols);
+ else
+ filllines_no_master(&mixdev[mixnum], micelem, 1);
fillcontrols(&mixdev[mixnum]);
TRACE("%s: Amount of controls: %i/%i, name: %s\n", cardname, mixdev[mixnum].dests, mixdev[mixnum].chans, debugstr_w(mixdev[mixnum].mixername));