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…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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 */