This is a patch that makes WINE detect snd_usb_audio mics and assign
them a mixer and working master control. See bug #12706 for more
information about this problem: http://bugs.winehq.org/show_bug.cgi?id=12706

I wasn't able to test it completely because I wasn't able to switch my
default input device to the USB mic and no one in IRC is helping with
this, but it might make things work because theoretically the only
problem was that WINE was ignoring devices that looked like
snd_usb_audio's microphones. I suggest that someone who CAN get
snd_usb_audio mic as their default test it out and confirm, I would
really appreciate that.

Thanks to all in IRC who helped me get things this far, especially
mlankhorst.

This patch is based against the current git HEAD, eaa227c12d8bb. I've
also posted it at the aforementioned bug.

--
Jeff Cook
(801) 231-3157
j...@deserettechnology.com


diff --git a/dlls/winealsa.drv/mixer.c b/dlls/winealsa.drv/mixer.c
index cfdf95f..352bc83 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;
@@ -258,6 +262,7 @@ static void fillcontrols(mixer *mmixer)
         else
             snd_mixer_selem_get_playback_volume_range(mline->elem, &min, &max);
 
+        
         /* (!snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) */
         /* Volume, always enabled by definition of blacklisted channels */
         mmixer->controls[ofs].enabled = 1;
@@ -332,17 +337,23 @@ 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) {
+        FIXME("mastelem found on %s, building master...\n");
+        /* 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 {
+        FIXME("no mastelem, skipping\n");
+        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
@@ -352,8 +363,10 @@ static void filllines(mixer *mmixer, snd_mixer_elem_t *mastelem, snd_mixer_elem_
     ++mline;
     if (capt)
     {
+        FIXME("captelem found\n");
         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));
+        FIXME("elem name: %s\n", snd_mixer_selem_get_name(captelem));
         mline->dst = 1;
         mline->capt = 1;
         mline->elem = captelem;
@@ -361,6 +374,8 @@ static void filllines(mixer *mmixer, snd_mixer_elem_t *mastelem, snd_mixer_elem_
 
         snd_mixer_elem_set_callback(captelem, &elem_callback);
         snd_mixer_elem_set_callback_private(captelem, mmixer);
+    } else {
+        FIXME("no capt\n");
     }
 
     for (elem = snd_mixer_first_elem(mmixer->mix); elem; elem = snd_mixer_elem_next(elem))
@@ -395,6 +410,24 @@ 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;
+    
+        FIXME("captelem found\n");
+        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));
+        FIXME("elem name: %s\n", 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 +447,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));
@@ -449,6 +482,8 @@ static void ALSA_MixerInit(void)
             WARN("Error occurred opening mixer: %s\n", snd_strerror(err));
             continue;
         }
+        
+        FIXME("Card: %s\n", cardname);
 
         err = snd_mixer_attach(mixdev[mixnum].mix, cardname);
         if (err < 0)
@@ -466,10 +501,15 @@ static void ALSA_MixerInit(void)
          * If there are multiple Master or Captures, all except 1 will be added as slaves
          */
         for (elem = snd_mixer_first_elem(mixdev[mixnum].mix); elem; elem = snd_mixer_elem_next(elem))
+            //crashes on this fixme if enabled
+            //if not, there is no crash, but no sliders work for sndvol32.exe
+            //FIXME("elem name: %s on card %s\n", snd_mixer_selem_get_name(elem), cardname);
             if (!strcasecmp(snd_mixer_selem_get_name(elem), "Master") && !mastelem)
                 mastelem = elem;
-            else if (!strcasecmp(snd_mixer_selem_get_name(elem), "Capture") && !captelem)
+            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)
+                micelem = elem;
             else if (!blacklisted(elem))
             {
                 DWORD comp = getcomponenttype(snd_mixer_selem_get_name(elem));
@@ -519,7 +559,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 +589,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));
@@ -826,6 +869,7 @@ static int getsrccntfromchan(mixer *mmixer, int dad)
     int i, j=0;
 
     for (i=0; i<mmixer->chans; ++i)
+        FIXME("Chans for this mixer: %d\n", mmixer->chans);
         if (i != dad && mmixer->lines[i].dst == dad)
         {
             ++j;



Reply via email to