diff -r 310c376aa30a cmd/ossxmix/ossxmix.c
--- a/cmd/ossxmix/ossxmix.c	Mon May 26 13:10:40 2008 +0300
+++ b/cmd/ossxmix/ossxmix.c	Thu Jun 05 02:23:18 2008 +0400
@@ -841,7 +841,7 @@
   int ngroups = 0;
   int parent;
   int change_color;
-  oss_mixext *thisrec, *nextrec;
+  oss_mixext *thisrec;
   oss_mixerinfo mi;
   GdkColor color;
   GtkWidget *wid, *wid2, *gang, *rootwid = NULL, *pw, *frame, *box;
@@ -849,6 +849,8 @@
   GtkObject *adjust, *adjust2;
   gboolean change_orient = TRUE, ori, orient[256] = { FALSE };
   gboolean expand, use_layout_b = FALSE;
+  int *visible_groups;
+  int visible_groups_changes;
 
   mi.dev = dev;
   if (ioctl (mixer_fd, SNDCTL_MIXERINFO, &mi) == -1)
@@ -877,6 +879,50 @@
   extrec[dev] = ossxmix_calloc (n+1, sizeof (oss_mixext));
   extnames = ossxmix_malloc ((n+1) * sizeof (char *));
 
+  for(i = 0; i < n; i++)
+  {
+    thisrec = &extrec[dev][i];
+    thisrec->dev = dev;
+    thisrec->ctrl = i;
+    if (ioctl (mixer_fd, SNDCTL_MIX_EXTINFO, thisrec) == -1)
+    {
+	    if (errno == EINVAL)
+	      printf ("Incompatible OSS version\n");
+	    else
+	      perror ("SNDCTL_MIX_EXTINFO");
+      exit (-1);
+    }
+  }
+
+  visible_groups = ossxmix_malloc(n * sizeof(int));
+  for(i = 0; i < n; i++)
+    visible_groups[i] = 0;
+
+  do
+  {
+    visible_groups_changes = 0;
+    for(i = 0; i < n; i++)
+    {
+      int parent;
+      oss_mixext *rec;
+      rec = &extrec[dev][i];
+      parent = rec->parent;
+      if(parent >= 0 && parent < n)
+      {
+        oss_mixext *parentrec;
+        parentrec = &extrec[dev][parent];
+        if(parentrec->type == MIXT_GROUP && visible_groups[parent] == 0)
+        {
+          if(rec->type != MIXT_GROUP || visible_groups[i] != 0)
+          {
+            visible_groups[parent] = 1;
+            visible_groups_changes++;
+          }
+        }
+      }
+    }
+  }while(visible_groups_changes != 0);
+
   for (i = 0; i < n; i++)
     {
       change_color = 0;
@@ -885,17 +931,6 @@
       expand = TRUE;
 
       thisrec = &extrec[dev][i];
-      thisrec->dev = dev;
-      thisrec->ctrl = i;
-
-      if (ioctl (mixer_fd, SNDCTL_MIX_EXTINFO, thisrec) == -1)
-	{
-	  if (errno == EINVAL)
-	      printf ("Incompatible OSS version\n");
-	  else
-	      perror ("SNDCTL_MIX_EXTINFO");
-	  exit (-1);
-	}
 
       if (thisrec->id[0] == '-')	/* Hidden one */
 	thisrec->id[0] = '\0';
@@ -938,29 +973,13 @@
 	case MIXT_GROUP:
 	  if (!show_all)
 	    break;
-#if 1
+#if 1 
 /*
  * Ignore the group if the next mixer entry is also a group. This 
  * should prevent empty groups on the screen. By Clive Wright.
  */
-	  nextrec = &extrec[dev][i+1];
-	  nextrec->dev = dev;
-	  nextrec->ctrl = i+1;
-
-	  if (ioctl (mixer_fd, SNDCTL_MIX_EXTINFO, nextrec) == -1)
-	    {
-	      if (errno == EINVAL)
-	          printf ("Incompatible OSS version\n");
-	      else
-	          perror ("SNDCTL_MIX_EXTINFO");
-	      exit (-1);
-	    }
-	  /*
-	   * Ignore group if next record is also a group with the same parent
-	   */
-	  if (nextrec->type == MIXT_GROUP
-	      && (thisrec->parent == nextrec->parent))
-	    break;
+    if(visible_groups[i] == 0)
+      break;
 #endif
 	  parent = thisrec->parent;
 	  name = cut_name (thisrec->id);
@@ -1497,6 +1516,7 @@
 
     }
 
+  free(visible_groups);
   free (extnames);
   return rootwid;
 }
