Andy Norris : winealsa: Add support for alsa cards without a PCM mixer ( only Line).
Alexandre Julliard
julliard at winehq.org
Tue Mar 8 11:03:52 CST 2011
Module: wine
Branch: master
Commit: 254b8f85b5f05e6fa6e688f453520f800086c2fd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=254b8f85b5f05e6fa6e688f453520f800086c2fd
Author: Andy Norris <bk-git at usrlocalsbin.com>
Date: Sat Mar 5 16:03:55 2011 -0500
winealsa: Add support for alsa cards without a PCM mixer (only Line).
---
dlls/winealsa.drv/alsa.c | 153 ++++++++++++++++++++++++---------------------
dlls/winealsa.drv/mixer.c | 10 +++-
2 files changed, 90 insertions(+), 73 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index b242cfa..0b244fa 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -421,6 +421,8 @@ int ALSA_CheckSetVolume(snd_hctl_t *hctl, int *out_left, int *out_right,
snd_ctl_elem_info_t * eleminfop = NULL;
snd_ctl_elem_value_t * elemvaluep = NULL;
snd_ctl_elem_id_t * elemidp = NULL;
+ const char *names[] = {"PCM Playback Volume", "Line Playback Volume", NULL};
+ const char **name;
#define EXIT_ON_ERROR(f,txt,exitcode) do \
@@ -447,81 +449,88 @@ int ALSA_CheckSetVolume(snd_hctl_t *hctl, int *out_left, int *out_right,
/* Setup and find an element id that exactly matches the characteristic we want
** FIXME: It is probably short sighted to hard code and fixate on PCM Playback Volume */
- snd_ctl_elem_id_set_name(elemidp, "PCM Playback Volume");
- snd_ctl_elem_id_set_interface(elemidp, SND_CTL_ELEM_IFACE_MIXER);
- elem = snd_hctl_find_elem(hctl, elemidp);
- if (elem)
- {
- /* Read and return volume information */
- EXIT_ON_ERROR(snd_hctl_elem_info(elem, eleminfop), "snd_hctl_elem_info", MMSYSERR_NOTSUPPORTED);
- value_count = snd_ctl_elem_info_get_count(eleminfop);
- if (out_min || out_max || out_step)
- {
- if (!snd_ctl_elem_info_is_readable(eleminfop))
- {
- ERR("snd_ctl_elem_info_is_readable returned false; cannot return info\n");
- rc = MMSYSERR_NOTSUPPORTED;
- goto out;
- }
-
- if (out_min)
- *out_min = snd_ctl_elem_info_get_min(eleminfop);
-
- if (out_max)
- *out_max = snd_ctl_elem_info_get_max(eleminfop);
-
- if (out_step)
- *out_step = snd_ctl_elem_info_get_step(eleminfop);
- }
-
- if (out_left || out_right)
- {
- EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);
-
- if (out_left)
- *out_left = snd_ctl_elem_value_get_integer(elemvaluep, 0);
-
- if (out_right)
- {
- if (value_count == 1)
- *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 0);
- else if (value_count == 2)
- *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 1);
- else
- {
- ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while getting volume info\n", value_count);
- rc = -1;
- goto out;
- }
- }
- }
- /* Set the volume */
- if (new_left || new_right)
- {
- EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);
- if (new_left)
- snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_left);
- if (new_right)
- {
- if (value_count == 1)
- snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_right);
- else if (value_count == 2)
- snd_ctl_elem_value_set_integer(elemvaluep, 1, *new_right);
- else
- {
- ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while setting volume info\n", value_count);
- rc = -1;
- goto out;
- }
- }
-
- EXIT_ON_ERROR(snd_hctl_elem_write(elem, elemvaluep), "snd_hctl_elem_write", MMSYSERR_NOTSUPPORTED);
- }
+ for( name = names; *name; name++ )
+ {
+ snd_ctl_elem_id_set_name(elemidp, *name);
+ snd_ctl_elem_id_set_interface(elemidp, SND_CTL_ELEM_IFACE_MIXER);
+ elem = snd_hctl_find_elem(hctl, elemidp);
+ if (elem)
+ {
+ /* Read and return volume information */
+ EXIT_ON_ERROR(snd_hctl_elem_info(elem, eleminfop), "snd_hctl_elem_info", MMSYSERR_NOTSUPPORTED);
+ value_count = snd_ctl_elem_info_get_count(eleminfop);
+ if (out_min || out_max || out_step)
+ {
+ if (!snd_ctl_elem_info_is_readable(eleminfop))
+ {
+ ERR("snd_ctl_elem_info_is_readable returned false; cannot return info\n");
+ rc = MMSYSERR_NOTSUPPORTED;
+ goto out;
+ }
+
+ if (out_min)
+ *out_min = snd_ctl_elem_info_get_min(eleminfop);
+
+ if (out_max)
+ *out_max = snd_ctl_elem_info_get_max(eleminfop);
+
+ if (out_step)
+ *out_step = snd_ctl_elem_info_get_step(eleminfop);
+ }
+
+ if (out_left || out_right)
+ {
+ EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);
+
+ if (out_left)
+ *out_left = snd_ctl_elem_value_get_integer(elemvaluep, 0);
+
+ if (out_right)
+ {
+ if (value_count == 1)
+ *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 0);
+ else if (value_count == 2)
+ *out_right = snd_ctl_elem_value_get_integer(elemvaluep, 1);
+ else
+ {
+ ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while getting volume info\n", value_count);
+ rc = -1;
+ goto out;
+ }
+ }
+ }
+
+ /* Set the volume */
+ if (new_left || new_right)
+ {
+ EXIT_ON_ERROR(snd_hctl_elem_read(elem, elemvaluep), "snd_hctl_elem_read", MMSYSERR_NOTSUPPORTED);
+ if (new_left)
+ snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_left);
+ if (new_right)
+ {
+ if (value_count == 1)
+ snd_ctl_elem_value_set_integer(elemvaluep, 0, *new_right);
+ else if (value_count == 2)
+ snd_ctl_elem_value_set_integer(elemvaluep, 1, *new_right);
+ else
+ {
+ ERR("Unexpected value count %d from snd_ctl_elem_info_get_count while setting volume info\n", value_count);
+ rc = -1;
+ goto out;
+ }
+ }
+
+ EXIT_ON_ERROR(snd_hctl_elem_write(elem, elemvaluep), "snd_hctl_elem_write", MMSYSERR_NOTSUPPORTED);
+ }
+
+ break;
+ }
}
- else
+
+ if( !*name )
{
- ERR("Could not find 'PCM Playback Volume' element\n");
+ ERR("Could not find '{PCM,Line} Playback Volume' element\n");
rc = MMSYSERR_NOTSUPPORTED;
}
diff --git a/dlls/winealsa.drv/mixer.c b/dlls/winealsa.drv/mixer.c
index 90760eb..7d5b452 100644
--- a/dlls/winealsa.drv/mixer.c
+++ b/dlls/winealsa.drv/mixer.c
@@ -435,7 +435,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, *micelem = NULL;
+ snd_mixer_elem_t *elem, *mastelem = NULL, *headelem = NULL, *captelem = NULL, *pcmelem = NULL, *lineelem = NULL, *micelem = NULL;
memset(info, 0, snd_ctl_card_info_sizeof());
memset(&mixdev[mixnum], 0, sizeof(*mixdev));
@@ -520,6 +520,8 @@ static void ALSA_MixerInit(void)
headelem = elem;
else if (!strcasecmp(snd_mixer_selem_get_name(elem), "PCM") && !pcmelem)
pcmelem = elem;
+ else if (!strcasecmp(snd_mixer_selem_get_name(elem), "Line") && !lineelem)
+ lineelem = elem;
++(mixdev[mixnum].chans);
}
}
@@ -548,6 +550,12 @@ static void ALSA_MixerInit(void)
mastelem = pcmelem;
capcontrols -= !!snd_mixer_selem_has_capture_switch(mastelem);
}
+ else if (lineelem && !mastelem)
+ {
+ /* Use 'Line' as master device */
+ mastelem = lineelem;
+ capcontrols -= !!snd_mixer_selem_has_capture_switch(mastelem);
+ }
else if (!mastelem && !captelem && !micelem)
{
/* If there is nothing sensible that can act as 'Master' control, something is wrong */
More information about the wine-cvs
mailing list