load some settings from the registry
Modified: trunk/reactos/subsys/system/sndvol32/misc.c
Modified: trunk/reactos/subsys/system/sndvol32/mixer.c
Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.c
Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.h

Modified: trunk/reactos/subsys/system/sndvol32/misc.c
--- trunk/reactos/subsys/system/sndvol32/misc.c	2005-09-27 12:43:36 UTC (rev 18122)
+++ trunk/reactos/subsys/system/sndvol32/misc.c	2005-09-27 13:42:20 UTC (rev 18123)
@@ -127,3 +127,121 @@
     return Ret;
 }
 
+/* NOTE: do NOT modify SNDVOL_REG_LINESTATE for binary compatibility with XP! */
+typedef struct _SNDVOL_REG_LINESTATE
+{
+    DWORD Flags;
+    WCHAR LineName[MIXER_LONG_NAME_CHARS];
+} SNDVOL_REG_LINESTATE, *PSNDVOL_REG_LINESTATE;
+
+static const TCHAR AppRegSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Volume Control");
+static const TCHAR AppOptionsKey[] = TEXT("Options");
+static const TCHAR LineStatesValue[] = TEXT("LineStates");
+static const TCHAR StyleValue[] = TEXT("Style");
+
+HKEY hAppSettingsKey = NULL;
+
+BOOL
+InitAppConfig(VOID)
+{
+    return RegCreateKeyEx(HKEY_CURRENT_USER,
+                          AppRegSettings,
+                          0,
+                          NULL,
+                          REG_OPTION_NON_VOLATILE,
+                          KEY_READ | KEY_WRITE,
+                          NULL,
+                          &hAppSettingsKey,
+                          NULL) == ERROR_SUCCESS;
+}
+
+VOID
+CloseAppConfig(VOID)
+{
+    if (hAppSettingsKey != NULL)
+    {
+        RegCloseKey(hAppSettingsKey);
+        hAppSettingsKey = NULL;
+    }
+}
+
+BOOL
+ReadLineConfig(IN LPTSTR szDeviceName,
+               IN LPTSTR szLineName,
+               IN LPTSTR szControlName,
+               OUT DWORD *Flags)
+{
+    HKEY hLineKey;
+    DWORD Type;
+    DWORD i, Size = 0;
+    PSNDVOL_REG_LINESTATE LineStates = NULL;
+    TCHAR szDevRegKey[MAX_PATH];
+    BOOL Ret = FALSE;
+
+    _stprintf(szDevRegKey,
+              TEXT("%s\\%s"),
+              szDeviceName,
+              szLineName);
+
+    if (RegCreateKeyEx(hAppSettingsKey,
+                       szDevRegKey,
+                       0,
+                       NULL,
+                       REG_OPTION_NON_VOLATILE,
+                       KEY_READ | KEY_WRITE,
+                       NULL,
+                       &hLineKey,
+                       NULL) == ERROR_SUCCESS)
+    {
+        if (RegQueryValueEx(hLineKey,
+                            LineStatesValue,
+                            NULL,
+                            &Type,
+                            NULL,
+                            &Size) != ERROR_SUCCESS ||
+            Type != REG_BINARY ||
+            Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
+        {
+            goto ExitClose;
+        }
+        
+        LineStates = HeapAlloc(GetProcessHeap(),
+                               0,
+                               Size);
+
+        if (LineStates != NULL)
+        {
+            if (RegQueryValueEx(hLineKey,
+                                LineStatesValue,
+                                NULL,
+                                &Type,
+                                (LPBYTE)LineStates,
+                                &Size) != ERROR_SUCCESS ||
+                Type != REG_BINARY ||
+                Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
+            {
+                goto ExitClose;
+            }
+            
+            /* try to find the control */
+            for (i = 0; i < Size / sizeof(SNDVOL_REG_LINESTATE); i++)
+            {
+                if (!_tcscmp(szControlName,
+                             LineStates[i].LineName))
+                {
+                    *Flags = LineStates[i].Flags;
+                    Ret = TRUE;
+                    break;
+                }
+            }
+        }
+
+ExitClose:
+        HeapFree(GetProcessHeap(),
+                 0,
+                 LineStates);
+        RegCloseKey(hLineKey);
+    }
+    
+    return Ret;
+}

Modified: trunk/reactos/subsys/system/sndvol32/mixer.c
--- trunk/reactos/subsys/system/sndvol32/mixer.c	2005-09-27 12:43:36 UTC (rev 18122)
+++ trunk/reactos/subsys/system/sndvol32/mixer.c	2005-09-27 13:42:20 UTC (rev 18123)
@@ -111,6 +111,7 @@
 
 static BOOL
 SndMixerQueryControls(PSND_MIXER Mixer,
+                      PUINT DisplayControls,
                       LPMIXERLINE LineInfo,
                       LPMIXERCONTROL *Controls)
 {
@@ -138,7 +139,13 @@
             {
                 for (j = 0; j < LineControls.cControls; j++)
                 {
-                    DPRINT("Line control: %ws\n", (*Controls)[j].szName);
+                    if (SndMixerIsDisplayControl(Mixer,
+                                                 &(*Controls)[j]))
+                    {
+                        (*DisplayControls)++;
+                    }
+
+                    DPRINT("Line control: %ws (0x%x, 0x%x)\n", (*Controls)[j].szName, (*Controls)[j].fdwControl, (*Controls)[j].dwControlType);
                 }
 
                 return TRUE;
@@ -169,7 +176,7 @@
 SndMixerQueryConnections(PSND_MIXER Mixer,
                          PSND_MIXER_DESTINATION Line)
 {
-    UINT i;
+    UINT i, DispControls;
     MIXERLINE LineInfo;
     MMRESULT Result;
     BOOL Ret = TRUE;
@@ -188,8 +195,11 @@
             PSND_MIXER_CONNECTION Con;
             
             DPRINT("++ Source: %ws\n", LineInfo.szName);
+            
+            DispControls = 0;
 
             if (!SndMixerQueryControls(Mixer,
+                                       &DispControls,
                                        &LineInfo,
                                        &Controls))
             {
@@ -205,6 +215,7 @@
             {
                 Con->Info = LineInfo;
                 Con->Controls = Controls;
+                Con->DisplayControls = DispControls;
                 Con->Next = Line->Connections;
                 Line->Connections = Con;
             }
@@ -247,15 +258,10 @@
                                  &Line->Info,
                                  MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR)
             {
-                DPRINT("+ Destination: %ws (%d)\n", Line->Info.szName, Line->Info.dwComponentType);
-
-                if (!SndMixerQueryConnections(Mixer, Line))
-                {
-                    DPRINT("Failed to query mixer connections!\n");
-                    Ret = FALSE;
-                    break;
-                }
+                DPRINT("+ Destination: %ws (0x%x, %d)\n", Line->Info.szName, Line->Info.dwLineID, Line->Info.dwComponentType);
+                
                 if (!SndMixerQueryControls(Mixer,
+                                           &Line->DisplayControls,
                                            &Line->Info,
                                            &Line->Controls))
                 {
@@ -264,6 +270,13 @@
                     break;
                 }
 
+                if (!SndMixerQueryConnections(Mixer, Line))
+                {
+                    DPRINT("Failed to query mixer connections!\n");
+                    Ret = FALSE;
+                    break;
+                }
+
                 Line->Next = Mixer->Lines;
                 Mixer->Lines = Line;
             }
@@ -374,6 +387,47 @@
     return -1;
 }
 
+INT
+SndMixerGetLineName(PSND_MIXER Mixer,
+                    DWORD LineID,
+                    LPTSTR lpBuffer,
+                    UINT uSize,
+                    BOOL LongName)
+{
+    if (Mixer->hmx)
+    {
+        int lnsz;
+        PSND_MIXER_DESTINATION Line;
+        LPMIXERLINE lpl = NULL;
+
+        for (Line = Mixer->Lines; Line != NULL; Line = Line->Next)
+        {
+            if (Line->Info.dwLineID == LineID)
+            {
+                lpl = &Line->Info;
+                break;
+            }
+        }
+
+        if (lpl != NULL)
+        {
+            lnsz = lstrlen(LongName ? lpl->szName : lpl->szShortName);
+            if(lnsz + 1 > uSize)
+            {
+                return lnsz + 1;
+            }
+            else
+            {
+                memcpy(lpBuffer, LongName ? lpl->szName : lpl->szShortName, lnsz * sizeof(TCHAR));
+                lpBuffer[lnsz] = _T('\0');
+                return lnsz;
+            }
+        }
+    }
+
+    return -1;
+}
+
 BOOL
 SndMixerEnumProducts(PSND_MIXER Mixer,
                      PFNSNDMIXENUMPRODUCTS EnumProc,
@@ -436,6 +490,7 @@
         {
             if (!EnumProc(Mixer,
                           &Line->Info,
+                          Line->DisplayControls,
                           Context))
             {
                 return FALSE;
@@ -463,6 +518,17 @@
             if (Line->Info.dwLineID == LineID)
             {
                 PSND_MIXER_CONNECTION Connection;
+                
+                if (Line->DisplayControls != 0)
+                {
+                    if (!EnumProc(Mixer,
+                                  LineID,
+                                  &Line->Info,
+                                  Context))
+                    {
+                        return FALSE;
+                    }
+                }
 
                 for (Connection = Line->Connections; Connection != NULL; Connection = Connection->Next)
                 {
@@ -483,3 +549,20 @@
     return FALSE;
 }
 
+BOOL
+SndMixerIsDisplayControl(PSND_MIXER Mixer,
+                         LPMIXERCONTROL Control)
+{
+    if (Mixer->hmx && !(Control->fdwControl & MIXERCONTROL_CONTROLF_DISABLED))
+    {
+        switch (Control->dwControlType & MIXERCONTROL_CT_CLASS_MASK)
+        {
+            case MIXERCONTROL_CT_CLASS_FADER:
+            case MIXERCONTROL_CT_CLASS_SWITCH:
+                return TRUE;
+        }
+    }
+    
+    return FALSE;
+}
+

Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.c
--- trunk/reactos/subsys/system/sndvol32/sndvol32.c	2005-09-27 12:43:36 UTC (rev 18122)
+++ trunk/reactos/subsys/system/sndvol32/sndvol32.c	2005-09-27 13:42:20 UTC (rev 18123)
@@ -51,6 +51,7 @@
     DWORD PlaybackID;
     DWORD RecordingID;
     UINT OtherLines;
+    TCHAR DeviceName[128];
     
     DWORD tmp;
 } PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT;
@@ -98,6 +99,7 @@
 static BOOL CALLBACK
 PrefDlgAddLine(PSND_MIXER Mixer,
                LPMIXERLINE Line,
+               UINT DisplayControls,
                PVOID Context)
 {
     PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context;
@@ -113,6 +115,8 @@
                 {
                     PrefContext->SelectedLine = Line->dwLineID;
                 }
+                
+                DPRINT("!%ws cControls: %d\n", Line->szName, Line->cControls);
             }
             else
                 goto AddToOthersLines;
@@ -128,6 +132,7 @@
                 {
                     PrefContext->SelectedLine = Line->dwLineID;
                 }
+                DPRINT("!%ws cControls: %d\n", Line->szName, Line->cControls);
             }
             else
                 goto AddToOthersLines;
@@ -196,10 +201,33 @@
                         (LPARAM)&lvi);
         if (i != (UINT)-1)
         {
-            /* FIXME - read config from registry */
+            TCHAR LineName[MIXER_LONG_NAME_CHARS];
+            DWORD Flags;
+            BOOL SelLine = FALSE;
+            
+            if (SndMixerGetLineName(PrefContext->Mixer,
+                                    PrefContext->SelectedLine,
+                                    LineName,
+                                    MIXER_LONG_NAME_CHARS,
+                                    FALSE) == -1)
+            {
+                LineName[0] = TEXT('\0');
+            }
+            
+            if (ReadLineConfig(PrefContext->DeviceName,
+                               LineName,
+                               Line->szName,
+                               &Flags))
+            {
+                if (Flags != 0x4)
+                {
+                    SelLine = TRUE;
+                }
+            }
+
             ListView_SetCheckState(hwndControls,
                                    i,
-                                   FALSE);
+                                   SelLine);
         }
     }
                            
@@ -214,18 +242,18 @@
     INT DeviceCbIndex;
 
     /* select the mixer */
-    DeviceCbIndex = SendMessage(GetDlgItem(Context->hwndDlg,
-                                           IDC_MIXERDEVICE),
-                                CB_GETCURSEL,
-                                0,
-                                0);
+    DeviceCbIndex = SendDlgItemMessage(Context->hwndDlg,
+                                       IDC_MIXERDEVICE,
+                                       CB_GETCURSEL,
+                                       0,
+                                       0);
     if (DeviceCbIndex != CB_ERR)
     {
-        MixerID = SendMessage(GetDlgItem(Context->hwndDlg,
-                                         IDC_MIXERDEVICE),
-                              CB_GETITEMDATA,
-                              DeviceCbIndex,
-                              0);
+        MixerID = SendDlgItemMessage(Context->hwndDlg,
+                                     IDC_MIXERDEVICE,
+                                     CB_GETITEMDATA,
+                                     DeviceCbIndex,
+                                     0);
         if (MixerID == CB_ERR)
         {
             MixerID = 0;
@@ -244,6 +272,10 @@
         Context->RecordingID = (DWORD)-1;
         Context->OtherLines = 0;
         Context->SelectedLine = (DWORD)-1;
+        
+        SndMixerGetProductName(Context->Mixer,
+                               Context->DeviceName,
+                               sizeof(Context->DeviceName) / sizeof(Context->DeviceName[0]));
 
         if (SndMixerEnumLines(Context->Mixer,
                               PrefDlgAddLine,
@@ -271,11 +303,11 @@
             if (Context->OtherLines != 0)
             {
                 /* select the first item in the other lines combo box by default */
-                SendMessage(GetDlgItem(Context->hwndDlg,
-                                       IDC_LINE),
-                            CB_SETCURSEL,
-                            0,
-                            0);
+                SendDlgItemMessage(Context->hwndDlg,
+                                   IDC_LINE,
+                                   CB_SETCURSEL,
+                                   0,
+                                   0);
             }
             EnableWindow(GetDlgItem(Context->hwndDlg,
                                     IDC_LINE),
@@ -349,18 +381,18 @@
                         DWORD LineID;
                         DWORD Index;
                         
-                        Index = SendMessage(GetDlgItem(hwndDlg,
-                                                       IDC_LINE),
-                                            CB_GETCURSEL,
-                                            0,
-                                            0);
+                        Index = SendDlgItemMessage(hwndDlg,
+                                                   IDC_LINE,
+                                                   CB_GETCURSEL,
+                                                   0,
+                                                   0);
                         if (Index != CB_ERR)
                         {
-                            LineID = SendMessage(GetDlgItem(hwndDlg,
-                                                            IDC_LINE),
-                                                 CB_GETITEMDATA,
-                                                 Index,
-                                                 0);
+                            LineID = SendDlgItemMessage(hwndDlg,
+                                                        IDC_LINE,
+                                                        CB_GETITEMDATA,
+                                                        Index,
+                                                        0);
                             if (LineID != CB_ERR)
                             {
                                 UpdatePrefDlgControls(Context,
@@ -769,6 +801,12 @@
     hAppInstance = hInstance;
     hAppHeap = GetProcessHeap();
     
+    if (!InitAppConfig())
+    {
+        DPRINT("Unable to open the Volume Control registry key!\n");
+        return 1;
+    }
+    
     /* load the application title */
     if (AllocAndLoadString(&lpAppTitle,
                            hAppInstance,
@@ -809,6 +847,8 @@
     {
         LocalFree(lpAppTitle);
     }
+    
+    CloseAppConfig();
 
     return 0;
 }

Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.h
--- trunk/reactos/subsys/system/sndvol32/sndvol32.h	2005-09-27 12:43:36 UTC (rev 18122)
+++ trunk/reactos/subsys/system/sndvol32/sndvol32.h	2005-09-27 13:42:20 UTC (rev 18123)
@@ -42,6 +42,7 @@
   struct _SND_MIXER_CONNECTION *Next;
   MIXERLINE Info;
   LPMIXERCONTROL Controls;
+  UINT DisplayControls;
 } SND_MIXER_CONNECTION, *PSND_MIXER_CONNECTION;
 
 
@@ -50,6 +51,7 @@
   struct _SND_MIXER_DESTINATION *Next;
   MIXERLINE Info;
   LPMIXERCONTROL Controls;
+  UINT DisplayControls;
   PSND_MIXER_CONNECTION Connections;
 } SND_MIXER_DESTINATION, *PSND_MIXER_DESTINATION;
 
@@ -63,7 +65,7 @@
   PSND_MIXER_DESTINATION Lines;
 } SND_MIXER, *PSND_MIXER;
 
-typedef BOOL (CALLBACK *PFNSNDMIXENUMLINES)(PSND_MIXER Mixer, LPMIXERLINE Line, PVOID Context);
+typedef BOOL (CALLBACK *PFNSNDMIXENUMLINES)(PSND_MIXER Mixer, LPMIXERLINE Line, UINT DisplayControls, PVOID Context);
 typedef BOOL (CALLBACK *PFNSNDMIXENUMCONNECTIONS)(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, PVOID Context);
 typedef BOOL (CALLBACK *PFNSNDMIXENUMPRODUCTS)(PSND_MIXER Mixer, UINT Id, LPCTSTR ProductName, PVOID Context);
 
@@ -73,14 +75,25 @@
 BOOL SndMixerSelect(PSND_MIXER Mixer, UINT MixerId);
 UINT SndMixerGetSelection(PSND_MIXER Mixer);
 INT SndMixerGetProductName(PSND_MIXER Mixer, LPTSTR lpBuffer, UINT uSize);
+INT SndMixerGetLineName(PSND_MIXER Mixer, DWORD LineID, LPTSTR lpBuffer, UINT uSize, BOOL LongName);
 BOOL SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOID Context);
 INT SndMixerGetDestinationCount(PSND_MIXER Mixer);
 BOOL SndMixerEnumLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context);
 BOOL SndMixerEnumConnections(PSND_MIXER Mixer, DWORD LineID, PFNSNDMIXENUMCONNECTIONS EnumProc, PVOID Context);
+BOOL SndMixerIsDisplayControl(PSND_MIXER Mixer, LPMIXERCONTROL Control);
 
 /*
  * MISC
  */
+
+extern HKEY hAppSettingsKey;
+
+BOOL
+InitAppConfig(VOID);
+
+VOID
+CloseAppConfig(VOID);
+
 INT
 AllocAndLoadString(OUT LPWSTR *lpTarget,
                    IN HINSTANCE hInst,
@@ -92,4 +105,10 @@
                     OUT LPWSTR *lpTarget,
                     ...);
 
+BOOL
+ReadLineConfig(IN LPTSTR szDeviceName,
+               IN LPTSTR szLineName,
+               IN LPTSTR szControlName,
+               OUT DWORD *Flags);
+
 #endif /* __SNDVOL32_H */