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