Author: janderwald
Date: Thu Apr  7 21:31:21 2011
New Revision: 51274

URL: http://svn.reactos.org/svn/reactos?rev=51274&view=rev
Log:
[SNDVOL32]
- Implement retrieving current volume level and mute state and set the dialog 
controls on startup
- Remove last line separator from GUI
- Implement updating slider / switch control when another application modifies 
volume settings
- Implement writing current selected lines settings into registry when the 
preference dialog is closed
- Implement helper functions which receive / set volume level
- Sndvol32 is now fully functional and has been tested in Windows XP SP3
- TODO: implement support for setting volume balance (left - right slider)
- TODO: Resources have not yet been commited

Modified:
    trunk/reactos/base/applications/sndvol32/dialog.c
    trunk/reactos/base/applications/sndvol32/misc.c
    trunk/reactos/base/applications/sndvol32/mixer.c
    trunk/reactos/base/applications/sndvol32/resources.h
    trunk/reactos/base/applications/sndvol32/sndvol32.c
    trunk/reactos/base/applications/sndvol32/sndvol32.h

Modified: trunk/reactos/base/applications/sndvol32/dialog.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/dialog.c?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/dialog.c [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/dialog.c [iso-8859-1] Thu Apr  7 
21:31:21 2011
@@ -159,7 +159,11 @@
         SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM) 1);
 
         /* set available range */
-        SendMessage(hwnd, TBM_SETSEL, (WPARAM) FALSE, (LPARAM) MAKELONG(0, 
5)); 
+        //SendMessage(hwnd, TBM_SETSEL, (WPARAM) FALSE, (LPARAM) MAKELONG(0, 
5));
+
+        /* set position */
+        SendMessage(hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) 0);
+
     }
     else if (!wcsicmp(ClassName, L"static") || !wcsicmp(ClassName, L"button"))
     {
@@ -328,12 +332,15 @@
     DWORD Flags;
     DWORD wID;
     RECT rect;
+    UINT ControlCount = 0, Index;
+    LPMIXERCONTROL Control = NULL;
+    HWND hDlgCtrl;
     PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context;
 
     if (Line->cControls != 0)
     {
       /* get line name */
-      if (SndMixerGetLineName(PrefContext->Mixer, PrefContext->SelectedLine, 
LineName, MIXER_LONG_NAME_CHARS, FALSE) == -1)
+      if (SndMixerGetLineName(PrefContext->MixerWindow->Mixer, 
PrefContext->SelectedLine, LineName, MIXER_LONG_NAME_CHARS, FALSE) == -1)
       {
           /* failed to get line name */
           LineName[0] = L'\0';
@@ -357,6 +364,74 @@
               /* set line name */
               SetDlgItemTextW(PrefContext->MixerWindow->hWnd, wID, 
Line->szName);
 
+              /* query controls */
+              if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) 
== TRUE)
+              {
+                  /* now go through all controls and update their states */
+                  for(Index = 0; Index < ControlCount; Index++)
+                  {
+                     if ((Control[Index].dwControlType & 
MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_SWITCH)
+                     {
+                         MIXERCONTROLDETAILS_BOOLEAN Details;
+
+                         /* get volume control details */
+                         if (SndMixerGetVolumeControlDetails(Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_BOOLEAN), 
(LPVOID)&Details) != -1)
+                         {
+                             /* update dialog control */
+                             wID = (PrefContext->Count + 1) * IDC_LINE_SWITCH;
+
+                            /* get dialog control */
+                            hDlgCtrl = 
GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
+
+                            if (hDlgCtrl != NULL)
+                            {
+                                /* check state */
+                                if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) 
!= Details.fValue)
+                                {
+                                    /* update control state */
+                                    SendMessageW(hDlgCtrl, BM_SETCHECK, 
(WPARAM)Details.fValue, 0);
+                                }
+                            }
+                         }
+                     }
+                     else if ((Control[Index].dwControlType & 
MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_FADER)
+                     {
+                         MIXERCONTROLDETAILS_UNSIGNED Details;
+
+                         /* get volume control details */
+                         if (SndMixerGetVolumeControlDetails(Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_UNSIGNED), 
(LPVOID)&Details) != -1)
+                         {
+                             /* update dialog control */
+                             DWORD Position;
+                             DWORD Step = 0x10000 / 5;
+
+                             /* FIXME: give me granularity */
+                             Position = 5 - (Details.dwValue / Step);
+
+                             /* FIXME support left - right slider */
+                             wID = (PrefContext->Count + 1) * 
IDC_LINE_SLIDER_VERT;
+
+                             /* get dialog control */
+                             hDlgCtrl = 
GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
+
+                             if (hDlgCtrl != NULL)
+                             {
+                                 /* check state */
+                                 LRESULT OldPosition = SendMessageW(hDlgCtrl, 
TBM_GETPOS, 0, 0);
+                                 if (OldPosition != Position)
+                                 {
+                                     /* update control state */
+                                     SendMessageW(hDlgCtrl, TBM_SETPOS, 
(WPARAM)TRUE, Position + Index);
+                                 }
+                             }
+                        }
+                     }
+                  }
+
+                  /* free controls */
+                  HeapFree(GetProcessHeap(), 0, Control);
+              }
+
               /* increment dialog count */
               PrefContext->Count++;
 
@@ -365,7 +440,6 @@
 
               /* now move the window */
               MoveWindow(PrefContext->MixerWindow->hWnd, rect.left, rect.top, 
(PrefContext->Count * DIALOG_VOLUME_SIZE), rect.bottom, TRUE);
-
           }
       }
     }
@@ -376,9 +450,117 @@
 LoadDialogCtrls(
     PPREFERENCES_CONTEXT PrefContext)
 {
-    /* set dialog count to one */
+    HWND hDlgCtrl;
+
+    /* set dialog count to zero */
     PrefContext->Count = 0;
 
     /* enumerate controls */
-    SndMixerEnumConnections(PrefContext->Mixer, PrefContext->SelectedLine, 
EnumConnectionsCallback, (PVOID)PrefContext);
-}
+    SndMixerEnumConnections(PrefContext->MixerWindow->Mixer, 
PrefContext->SelectedLine, EnumConnectionsCallback, (PVOID)PrefContext);
+
+    /* get last line seperator */
+    hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, IDC_LINE_SEP * 
PrefContext->Count);
+
+    if (hDlgCtrl != NULL)
+    {
+        /* hide last seperator */
+        ShowWindow(hDlgCtrl, SW_HIDE);
+    }
+
+}
+
+VOID
+UpdateDialogLineSwitchControl(
+    PPREFERENCES_CONTEXT PrefContext,
+    LPMIXERLINE Line,
+    LONG fValue)
+{
+    DWORD Index;
+    DWORD wID;
+    HWND hDlgCtrl;
+    WCHAR LineName[MIXER_LONG_NAME_CHARS];
+
+    /* find the index of this line */
+    for(Index = 0; Index < PrefContext->Count; Index++)
+    {
+        /* get id */
+        wID = (Index + 1) * IDC_LINE_NAME;
+
+        if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, 
MIXER_LONG_NAME_CHARS) == 0)
+        {
+            /* failed to retrieve id */
+            continue;
+        }
+
+        /* check if the line name matches */
+        if (!wcsicmp(LineName, Line->szName))
+        {
+            /* found matching line name */
+            wID = (Index + 1) * IDC_LINE_SWITCH;
+
+            /* get dialog control */
+            hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
+
+            if (hDlgCtrl != NULL)
+            {
+                /* check state */
+                if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) != fValue)
+                {
+                    /* update control state */
+                    SendMessageW(hDlgCtrl, BM_SETCHECK, (WPARAM)fValue, 0);
+                }
+            }
+            break;
+        }
+    }
+}
+
+VOID
+UpdateDialogLineSliderControl(
+    PPREFERENCES_CONTEXT PrefContext,
+    LPMIXERLINE Line,
+    DWORD dwControlID,
+    DWORD dwDialogID,
+    DWORD Position)
+{
+    DWORD Index;
+    DWORD wID;
+    HWND hDlgCtrl;
+    WCHAR LineName[MIXER_LONG_NAME_CHARS];
+
+    /* find the index of this line */
+    for(Index = 0; Index < PrefContext->Count; Index++)
+    {
+        /* get id */
+        wID = (Index + 1) * IDC_LINE_NAME;
+
+        if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, 
MIXER_LONG_NAME_CHARS) == 0)
+        {
+            /* failed to retrieve id */
+            continue;
+        }
+
+        /* check if the line name matches */
+        if (!wcsicmp(LineName, Line->szName))
+        {
+            /* found matching line name */
+            wID = (Index + 1) * dwDialogID;
+
+            /* get dialog control */
+            hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
+
+            if (hDlgCtrl != NULL)
+            {
+                /* check state */
+                LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0);
+                if (OldPosition != Position)
+                {
+                    /* update control state */
+                    SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, Position 
+ Index);
+                }
+            }
+            break;
+        }
+    }
+}
+

Modified: trunk/reactos/base/applications/sndvol32/misc.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/misc.c?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/misc.c [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/misc.c [iso-8859-1] Thu Apr  7 
21:31:21 2011
@@ -126,13 +126,6 @@
     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");
@@ -165,10 +158,10 @@
 }
 
 BOOL
-ReadLineConfig(IN LPTSTR szDeviceName,
-               IN LPTSTR szLineName,
-               IN LPTSTR szControlName,
-               OUT DWORD *Flags)
+WriteLineConfig(IN LPTSTR szDeviceName,
+                IN LPTSTR szLineName,
+                IN LPTSTR szControlName,
+                IN DWORD Flags)
 {
     HKEY hLineKey;
     DWORD Type;
@@ -205,7 +198,7 @@
         }
 
         LineStates = HeapAlloc(GetProcessHeap(),
-                               0,
+                               HEAP_ZERO_MEMORY,
                                Size);
 
         if (LineStates != NULL)
@@ -228,10 +221,16 @@
                 if (!_tcscmp(szControlName,
                              LineStates[i].LineName))
                 {
-                    *Flags = LineStates[i].Flags;
+                    LineStates[i].Flags = Flags;
                     Ret = TRUE;
                     break;
                 }
+            }
+
+            /* now update line states */
+            if (Ret)
+            {
+                RegSetValueEx(hLineKey, LineStatesValue, 0, REG_BINARY, (const 
BYTE*)LineStates, Size);
             }
         }
 
@@ -243,4 +242,89 @@
     }
 
     return Ret;
-}
+
+
+
+
+}
+
+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(),
+                               HEAP_ZERO_MEMORY,
+                               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/base/applications/sndvol32/mixer.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/mixer.c?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/mixer.c [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/mixer.c [iso-8859-1] Thu Apr  7 
21:31:21 2011
@@ -107,7 +107,7 @@
     }
 }
 
-static BOOL
+BOOL
 SndMixerQueryControls(PSND_MIXER Mixer,
                       PUINT DisplayControls,
                       LPMIXERLINE LineInfo,
@@ -116,7 +116,7 @@
     if (LineInfo->cControls > 0)
     {
         *Controls = (MIXERCONTROL*) HeapAlloc(GetProcessHeap(),
-                              0,
+                              HEAP_ZERO_MEMORY,
                               LineInfo->cControls * sizeof(MIXERCONTROL));
         if (*Controls != NULL)
         {
@@ -207,7 +207,7 @@
             }
 
             Con = (SND_MIXER_CONNECTION*) HeapAlloc(GetProcessHeap(),
-                            0,
+                            HEAP_ZERO_MEMORY,
                             sizeof(SND_MIXER_CONNECTION));
             if (Con != NULL)
             {
@@ -470,6 +470,52 @@
 }
 
 INT
+SndMixerSetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD 
cbDetails, LPVOID paDetails)
+{
+    MIXERCONTROLDETAILS MixerDetails;
+
+    if (Mixer->hmx)
+    {
+        MixerDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
+        MixerDetails.dwControlID = dwControlID;
+        MixerDetails.cChannels = 1; //FIXME
+        MixerDetails.cMultipleItems = 0;
+        MixerDetails.cbDetails = cbDetails;
+        MixerDetails.paDetails = paDetails;
+
+        if (mixerSetControlDetails((HMIXEROBJ)Mixer->hmx, &MixerDetails, 
MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
+        {
+            return 1;
+        }
+    }
+
+    return -1;
+}
+
+
+INT
+SndMixerGetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD 
cbDetails, LPVOID paDetails)
+{
+    MIXERCONTROLDETAILS MixerDetails;
+
+    if (Mixer->hmx)
+    {
+        MixerDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
+        MixerDetails.dwControlID = dwControlID;
+        MixerDetails.cChannels = 1; //FIXME
+        MixerDetails.cMultipleItems = 0;
+        MixerDetails.cbDetails = cbDetails;
+        MixerDetails.paDetails = paDetails;
+
+        if (mixerGetControlDetails((HMIXEROBJ)Mixer->hmx, &MixerDetails, 
MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
+        {
+            return 1;
+        }
+    }
+    return -1;
+}
+
+INT
 SndMixerGetDestinationCount(PSND_MIXER Mixer)
 {
     return (Mixer->hmx ? (INT)Mixer->Caps.cDestinations : -1);

Modified: trunk/reactos/base/applications/sndvol32/resources.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/resources.h?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/resources.h [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/resources.h [iso-8859-1] Thu Apr  
7 21:31:21 2011
@@ -19,10 +19,13 @@
 #define IDC_LABELCONTROLS 1006
 #define IDC_CONTROLS 1007
 #define IDC_LINE_NAME 1008
+#define IDC_LINE_SWITCH 1009
+#define IDC_LINE_SLIDER_HORZ 1010
+#define IDC_LINE_SLIDER_VERT 1011
+#define IDC_LINE_SEP 1012
 
 #define IDS_SNDVOL32 100
 #define IDS_NOMIXERDEVICES 101
 
-
 #define IDD_VOLUME_CTRL 200
 #define IDD_PREFERENCES 201

Modified: trunk/reactos/base/applications/sndvol32/sndvol32.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/sndvol32.c?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/sndvol32.c [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/sndvol32.c [iso-8859-1] Thu Apr  7 
21:31:21 2011
@@ -338,6 +338,53 @@
     }
 }
 
+static 
+VOID
+WriteLineSettings(PREFERENCES_CONTEXT Context, HWND hwndDlg)
+{
+    HWND hwndControls;
+    INT Count, Index;
+    WCHAR LineName[MIXER_LONG_NAME_CHARS];
+    WCHAR DestinationName[MIXER_LONG_NAME_CHARS];
+    DWORD Flags;
+
+    /* get list view */
+    hwndControls = GetDlgItem(hwndDlg, IDC_CONTROLS);
+
+    /* get list item count */
+    Count = ListView_GetItemCount(hwndControls);
+
+    /* sanity check */
+    assert(Count);
+
+    if (SndMixerGetLineName(Preferences.MixerWindow->Mixer, 
Preferences.SelectedLine, DestinationName, MIXER_LONG_NAME_CHARS, TRUE) == -1)
+    {
+        /* failed to get destination line name */
+        return;
+    }
+
+    /* allocate line states array */
+    for(Index = 0; Index < Count; Index++)
+    {
+        /* set to empty */
+        LineName[0] = L'\0';
+
+        /* get item text */
+        ListView_GetItemText(hwndControls, Index, 0, LineName, 
MIXER_LONG_NAME_CHARS);
+
+        /* make sure it is null terminated */
+        LineName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+
+        /* get check state */
+        Flags = (ListView_GetCheckState(hwndControls, Index) == 0 ? 0x4 : 0);
+
+        /* write configuration */
+        WriteLineConfig(Preferences.DeviceName, DestinationName, LineName, 
Flags);
+    }
+
+
+}
+
 static INT_PTR CALLBACK
 DlgPreferencesProc(HWND hwndDlg,
                    UINT uMsg,
@@ -444,6 +491,12 @@
                 }
 
                 case IDOK:
+                {
+                    /* write line settings */
+                    WriteLineSettings(Preferences, hwndDlg);
+
+                    /* fall through */
+                }
                 case IDCANCEL:
                 {
                     EndDialog(hwndDlg,
@@ -451,18 +504,6 @@
                     break;
                 }
             }
-            break;
-        }
-
-        case MM_MIXM_LINE_CHANGE:
-        {
-            DPRINT("MM_MIXM_LINE_CHANGE\n");
-            break;
-        }
-
-        case MM_MIXM_CONTROL_CHANGE:
-        {
-            DPRINT("MM_MIXM_CONTROL_CHANGE\n");
             break;
         }
 
@@ -567,6 +608,149 @@
     return TRUE;
 }
 
+static
+BOOL
+CALLBACK
+SetVolumeCallback(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, PVOID Ctx)
+{
+    UINT ControlCount = 0, Index;
+    LPMIXERCONTROL Control = NULL;
+    MIXERCONTROLDETAILS_UNSIGNED uDetails;
+    MIXERCONTROLDETAILS_BOOLEAN bDetails;
+    PSET_VOLUME_CONTEXT Context = (PSET_VOLUME_CONTEXT)Ctx;
+
+    /* check if the line name is equal */
+    if (wcsicmp(Line->szName, Context->LineName))
+    {
+        /* it is not */
+        return TRUE;
+    }
+
+    /* query controls */
+    if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) == FALSE)
+    {
+        /* failed to query for controls */
+        return FALSE;
+    }
+
+    /* now go through all controls and compare control ids */
+    for(Index = 0; Index < ControlCount; Index++)
+    {
+        if (Context->bVertical)
+        {
+            if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == 
MIXERCONTROL_CT_CLASS_FADER)
+            {
+                /* FIXME: give me granularity */
+                DWORD Step = 0x10000 / 5;
+
+                /* set up details */
+                uDetails.dwValue = 0x10000 - Step * Context->SliderPos;
+
+                /* set volume */
+                
SndMixerSetVolumeControlDetails(Preferences.MixerWindow->Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_UNSIGNED), 
(LPVOID)&uDetails);
+
+                /* done */
+                break;
+            }
+        }
+        else if (Context->bSwitch)
+        {
+            if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == 
MIXERCONTROL_CT_CLASS_SWITCH)
+            {
+                /* set up details */
+                bDetails.fValue = Context->SliderPos;
+
+                /* set volume */
+                
SndMixerSetVolumeControlDetails(Preferences.MixerWindow->Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_BOOLEAN), 
(LPVOID)&bDetails);
+
+                /* done */
+                break;
+            }
+        }
+        else
+        {
+            /* FIXME: implement left - right channel switch support */
+            assert(0);
+        }
+    }
+
+    /* free controls */
+    HeapFree(GetProcessHeap(), 0, Control);
+
+
+    /* done */
+    return TRUE;
+}
+
+static
+BOOL
+CALLBACK
+MixerControlChangeCallback(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, 
PVOID Context)
+{
+    UINT ControlCount = 0, Index;
+    LPMIXERCONTROL Control = NULL;
+
+    /* check if the line has controls */
+    if (Line->cControls == 0)
+    {
+        /* no controls */
+        return TRUE;
+    }
+
+    /* query controls */
+    if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) == FALSE)
+    {
+        /* failed to query for controls */
+        return FALSE;
+    }
+
+    /* now go through all controls and compare control ids */
+    for(Index = 0; Index < ControlCount; Index++)
+    {
+        if (Control[Index].dwControlID == PtrToUlong(Context))
+        {
+            if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == 
MIXERCONTROL_CT_CLASS_SWITCH)
+            {
+                MIXERCONTROLDETAILS_BOOLEAN Details;
+
+                /* get volume control details */
+                if 
(SndMixerGetVolumeControlDetails(Preferences.MixerWindow->Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_BOOLEAN), 
(LPVOID)&Details) != -1)
+                {
+                    /* update dialog control */
+                    UpdateDialogLineSwitchControl(&Preferences, Line, 
Details.fValue);
+                }
+            }
+            else if ((Control[Index].dwControlType & 
MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_FADER)
+            {
+                MIXERCONTROLDETAILS_UNSIGNED Details;
+
+                /* get volume control details */
+                if 
(SndMixerGetVolumeControlDetails(Preferences.MixerWindow->Mixer, 
Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_UNSIGNED), 
(LPVOID)&Details) != -1)
+                {
+                    /* update dialog control */
+                    DWORD Position;
+                    DWORD Step = 0x10000 / 5;
+
+                    /* FIXME: give me granularity */
+                    Position = 5 - (Details.dwValue / Step);
+
+                    /* update volume control slider */
+                    UpdateDialogLineSliderControl(&Preferences, Line, 
Control[Index].dwControlID, IDC_LINE_SLIDER_VERT, Position);
+                }
+            }
+            break;
+        }
+    }
+
+    /* free controls */
+    HeapFree(GetProcessHeap(), 0, Control);
+
+
+    /* done */
+    return TRUE;
+}
+
+
 static LRESULT CALLBACK
 MainWindowProc(HWND hwnd,
                UINT uMsg,
@@ -574,7 +758,9 @@
                LPARAM lParam)
 {
     PMIXER_WINDOW MixerWindow;
+    DWORD CtrlID, LineOffset;
     LRESULT Result = 0;
+    SET_VOLUME_CONTEXT Context;
 
     switch (uMsg)
     {
@@ -598,7 +784,46 @@
                                        DlgPreferencesProc,
                                        (LPARAM)&Preferences) == IDOK)
                     {
-                        /* FIXME - update window */
+                        /* update window */
+                        TCHAR szProduct[MAXPNAMELEN];
+
+                        /* get mixer product name */
+                        if (SndMixerGetProductName(MixerWindow->Mixer,
+                                                   szProduct,
+                                                   sizeof(szProduct) / 
sizeof(szProduct[0])) == -1)
+                        {
+                            /* failed to get name */
+                            szProduct[0] = L'\0';
+                        }
+                        else
+                        {
+                            /* copy product */
+                            wcscpy(Preferences.DeviceName, szProduct);
+                        }
+
+                        /* destroy old status bar */
+                        DestroyWindow(MixerWindow->hStatusBar);
+
+                        /* rebuild dialog controls */
+                        if (RebuildMixerWindowControls(&Preferences))
+                        {
+                            DPRINT("Rebuilding mixer window controls 
failed!\n");
+                        }
+
+                        /* create status window */
+                        MixerWindow->hStatusBar = 
CreateStatusWindow(WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
+                                                                     NULL,
+                                                                     hwnd,
+                                                                     0);
+
+                        /* set status bar */
+                        if (MixerWindow->hStatusBar)
+                        {
+                            SendMessage(MixerWindow->hStatusBar,
+                                WM_SETTEXT,
+                                0,
+                                (LPARAM)szProduct);
+                        }
                     }
                     break;
                 }
@@ -619,6 +844,35 @@
                                hAppIcon);
                     break;
                 }
+
+                default:
+                {
+                    /* get button id */
+                    CtrlID = LOWORD(wParam);
+
+                    /* check if the message is from the line switch */
+                    if (HIWORD(wParam) == BN_CLICKED && (CtrlID % 
IDC_LINE_SWITCH == 0))
+                    {
+                         /* compute line offset */
+                         LineOffset = CtrlID / IDC_LINE_SWITCH;
+
+                        /* compute window id of line name static control */
+                        CtrlID = LineOffset * IDC_LINE_NAME;
+
+                       /* get line name */
+                       if (GetDlgItemTextW(hwnd, CtrlID, Context.LineName, 
MIXER_LONG_NAME_CHARS) != 0)
+                       {
+                           /* setup context */
+                           Context.SliderPos = SendMessage((HWND)lParam, 
BM_GETCHECK, 0, 0);
+                           Context.bVertical = FALSE;
+                           Context.bSwitch = TRUE;
+
+                           /* set volume */
+                           
SndMixerEnumConnections(Preferences.MixerWindow->Mixer, 
Preferences.SelectedLine, SetVolumeCallback, (LPVOID)&Context);
+                       }
+                    }
+                }
+
             }
             break;
         }
@@ -632,8 +886,48 @@
         case MM_MIXM_CONTROL_CHANGE:
         {
             DPRINT("MM_MIXM_CONTROL_CHANGE\n");
-            break;
-        }
+
+            /* get mixer window */
+            MixerWindow = GetWindowData(hwnd,
+                                        MIXER_WINDOW);
+
+            /* sanity checks */
+            assert(MixerWindow);
+            assert(MixerWindow->Mixer->hmx == (HMIXER)wParam);
+
+            SndMixerEnumConnections(MixerWindow->Mixer, 
Preferences.SelectedLine, MixerControlChangeCallback, (PVOID)lParam);
+            break;
+        }
+
+        case WM_VSCROLL:
+        {
+            if (LOWORD(wParam) == TB_THUMBTRACK)
+            {
+                /* get dialog item ctrl */
+                CtrlID = GetDlgCtrlID((HWND)lParam);
+
+                /* get line index */
+                LineOffset = CtrlID / IDC_LINE_SLIDER_VERT;
+
+                /* compute window id of line name static control */
+                CtrlID = LineOffset * IDC_LINE_NAME;
+
+                /* get line name */
+                if (GetDlgItemTextW(hwnd, CtrlID, Context.LineName, 
MIXER_LONG_NAME_CHARS) != 0)
+                {
+                    /* setup context */
+                    Context.SliderPos = HIWORD(wParam);
+                    Context.bVertical = TRUE;
+                    Context.bSwitch = FALSE;
+
+                    /* set volume */
+                    SndMixerEnumConnections(Preferences.MixerWindow->Mixer, 
Preferences.SelectedLine, SetVolumeCallback, (LPVOID)&Context);
+                }
+            }
+
+            break;
+        }
+
 
         case WM_CREATE:
         {
@@ -775,7 +1069,7 @@
         hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT,
                               SZ_APP_CLASS,
                               lpAppTitle,
-                              WS_OVERLAPPEDWINDOW | WS_VISIBLE, //WS_DLGFRAME 
| WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS 
| WS_VISIBLE, 
+                              WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | 
WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, 
                               0, 0, 300, 315,
                               NULL,
                               LoadMenu(hAppInstance,

Modified: trunk/reactos/base/applications/sndvol32/sndvol32.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/sndvol32/sndvol32.h?rev=51274&r1=51273&r2=51274&view=diff
==============================================================================
--- trunk/reactos/base/applications/sndvol32/sndvol32.h [iso-8859-1] (original)
+++ trunk/reactos/base/applications/sndvol32/sndvol32.h [iso-8859-1] Thu Apr  7 
21:31:21 2011
@@ -84,6 +84,22 @@
     DWORD tmp;
 } PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT;
 
+typedef struct
+{
+    WCHAR LineName[MIXER_LONG_NAME_CHARS];
+    UINT SliderPos;
+    BOOL bVertical;
+    BOOL bSwitch;
+
+}SET_VOLUME_CONTEXT, *PSET_VOLUME_CONTEXT;
+
+/* 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;
+
 
 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);
@@ -94,6 +110,8 @@
 VOID SndMixerClose(PSND_MIXER Mixer);
 BOOL SndMixerSelect(PSND_MIXER Mixer, UINT MixerId);
 UINT SndMixerGetSelection(PSND_MIXER Mixer);
+INT SndMixerSetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD 
cbDetails, LPVOID paDetails);
+INT SndMixerGetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD 
cbDetails, LPVOID paDetails);
 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);
@@ -101,12 +119,14 @@
 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);
+BOOL SndMixerQueryControls(PSND_MIXER Mixer, PUINT DisplayControls, 
LPMIXERLINE LineInfo, LPMIXERCONTROL *Controls);
 
 /*
  * dialog.c
  */
-VOID
-LoadDialogCtrls(PPREFERENCES_CONTEXT PrefContext);
+VOID LoadDialogCtrls(PPREFERENCES_CONTEXT PrefContext);
+VOID UpdateDialogLineSliderControl(PPREFERENCES_CONTEXT PrefContext, 
LPMIXERLINE Line, DWORD dwControlID, DWORD DialogID, DWORD Position);
+VOID UpdateDialogLineSwitchControl(PPREFERENCES_CONTEXT PrefContext, 
LPMIXERLINE Line, LONG fValue);
 
 /*
  * MISC
@@ -137,4 +157,10 @@
                IN LPTSTR szControlName,
                OUT DWORD *Flags);
 
+BOOL
+WriteLineConfig(IN LPTSTR szDeviceName,
+                IN LPTSTR szLineName,
+                IN LPTSTR szControlName,
+                IN DWORD Flags);
+
 #endif /* __SNDVOL32_H */


Reply via email to