From 07de2df4a2828dce87f2d4e0c44eb0cad042d857 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Thu, 7 Apr 2011 21:31:21 +0000 Subject: [PATCH] [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 svn path=/trunk/; revision=51274 --- reactos/base/applications/sndvol32/dialog.c | 192 ++++++++++- reactos/base/applications/sndvol32/misc.c | 100 +++++- reactos/base/applications/sndvol32/mixer.c | 52 ++- .../base/applications/sndvol32/resources.h | 5 +- reactos/base/applications/sndvol32/sndvol32.c | 322 +++++++++++++++++- reactos/base/applications/sndvol32/sndvol32.h | 30 +- 6 files changed, 668 insertions(+), 33 deletions(-) diff --git a/reactos/base/applications/sndvol32/dialog.c b/reactos/base/applications/sndvol32/dialog.c index 3cddcd043e2..63b3233b1bf 100644 --- a/reactos/base/applications/sndvol32/dialog.c +++ b/reactos/base/applications/sndvol32/dialog.c @@ -159,7 +159,11 @@ AddDialogControl( 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 @@ EnumConnectionsCallback( 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 @@ EnumConnectionsCallback( /* 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 @@ EnumConnectionsCallback( /* now move the window */ MoveWindow(PrefContext->MixerWindow->hWnd, rect.left, rect.top, (PrefContext->Count * DIALOG_VOLUME_SIZE), rect.bottom, TRUE); - } } } @@ -376,9 +450,117 @@ VOID 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; + } + } +} + diff --git a/reactos/base/applications/sndvol32/misc.c b/reactos/base/applications/sndvol32/misc.c index 169e6114339..48c1d955f3b 100644 --- a/reactos/base/applications/sndvol32/misc.c +++ b/reactos/base/applications/sndvol32/misc.c @@ -126,13 +126,6 @@ LoadAndFormatString(IN HINSTANCE hInstance, 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"); @@ -162,6 +155,97 @@ CloseAppConfig(VOID) RegCloseKey(hAppSettingsKey); hAppSettingsKey = NULL; } +} + +BOOL +WriteLineConfig(IN LPTSTR szDeviceName, + IN LPTSTR szLineName, + IN LPTSTR szControlName, + IN 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)) + { + LineStates[i].Flags = Flags; + Ret = TRUE; + break; + } + } + + /* now update line states */ + if (Ret) + { + RegSetValueEx(hLineKey, LineStatesValue, 0, REG_BINARY, (const BYTE*)LineStates, Size); + } + } + +ExitClose: + HeapFree(GetProcessHeap(), + 0, + LineStates); + RegCloseKey(hLineKey); + } + + return Ret; + + + + } BOOL @@ -205,7 +289,7 @@ ReadLineConfig(IN LPTSTR szDeviceName, } LineStates = HeapAlloc(GetProcessHeap(), - 0, + HEAP_ZERO_MEMORY, Size); if (LineStates != NULL) diff --git a/reactos/base/applications/sndvol32/mixer.c b/reactos/base/applications/sndvol32/mixer.c index d4e883ba2a9..0fbc172fcec 100644 --- a/reactos/base/applications/sndvol32/mixer.c +++ b/reactos/base/applications/sndvol32/mixer.c @@ -107,7 +107,7 @@ SndMixerClose(PSND_MIXER Mixer) } } -static BOOL +BOOL SndMixerQueryControls(PSND_MIXER Mixer, PUINT DisplayControls, LPMIXERLINE LineInfo, @@ -116,7 +116,7 @@ SndMixerQueryControls(PSND_MIXER Mixer, if (LineInfo->cControls > 0) { *Controls = (MIXERCONTROL*) HeapAlloc(GetProcessHeap(), - 0, + HEAP_ZERO_MEMORY, LineInfo->cControls * sizeof(MIXERCONTROL)); if (*Controls != NULL) { @@ -207,7 +207,7 @@ SndMixerQueryConnections(PSND_MIXER Mixer, } Con = (SND_MIXER_CONNECTION*) HeapAlloc(GetProcessHeap(), - 0, + HEAP_ZERO_MEMORY, sizeof(SND_MIXER_CONNECTION)); if (Con != NULL) { @@ -469,6 +469,52 @@ SndMixerEnumProducts(PSND_MIXER Mixer, return Ret; } +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) { diff --git a/reactos/base/applications/sndvol32/resources.h b/reactos/base/applications/sndvol32/resources.h index 2fa18a50a66..737f1794dd8 100644 --- a/reactos/base/applications/sndvol32/resources.h +++ b/reactos/base/applications/sndvol32/resources.h @@ -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 diff --git a/reactos/base/applications/sndvol32/sndvol32.c b/reactos/base/applications/sndvol32/sndvol32.c index 6c8ad7c55c1..df69bb9cf0a 100644 --- a/reactos/base/applications/sndvol32/sndvol32.c +++ b/reactos/base/applications/sndvol32/sndvol32.c @@ -338,6 +338,53 @@ UpdatePrefDlgControls(PPREFERENCES_CONTEXT Context, } } +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 @@ DlgPreferencesProc(HWND hwndDlg, } case IDOK: + { + /* write line settings */ + WriteLineSettings(Preferences, hwndDlg); + + /* fall through */ + } case IDCANCEL: { EndDialog(hwndDlg, @@ -454,18 +507,6 @@ DlgPreferencesProc(HWND hwndDlg, 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; - } - case WM_INITDIALOG: { PREFERENCES_FILL_DEVICES FillDevContext; @@ -567,6 +608,149 @@ RebuildMixerWindowControls(PPREFERENCES_CONTEXT PrefContext) 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 @@ MainWindowProc(HWND hwnd, LPARAM lParam) { PMIXER_WINDOW MixerWindow; + DWORD CtrlID, LineOffset; LRESULT Result = 0; + SET_VOLUME_CONTEXT Context; switch (uMsg) { @@ -598,7 +784,46 @@ MainWindowProc(HWND hwnd, 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 @@ MainWindowProc(HWND hwnd, 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,9 +886,49 @@ MainWindowProc(HWND hwnd, case MM_MIXM_CONTROL_CHANGE: { DPRINT("MM_MIXM_CONTROL_CHANGE\n"); + + /* 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: { MixerWindow = ((LPCREATESTRUCT)lParam)->lpCreateParams; @@ -775,7 +1069,7 @@ CreateApplicationWindow(VOID) 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, diff --git a/reactos/base/applications/sndvol32/sndvol32.h b/reactos/base/applications/sndvol32/sndvol32.h index 9cbae1ccbf8..520ff7d59ff 100644 --- a/reactos/base/applications/sndvol32/sndvol32.h +++ b/reactos/base/applications/sndvol32/sndvol32.h @@ -84,6 +84,22 @@ typedef struct _PREFERENCES_CONTEXT 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 SndMixerDestroy(PSND_MIXER Mixer); 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 @@ 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); +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 @@ ReadLineConfig(IN LPTSTR szDeviceName, IN LPTSTR szControlName, OUT DWORD *Flags); +BOOL +WriteLineConfig(IN LPTSTR szDeviceName, + IN LPTSTR szLineName, + IN LPTSTR szControlName, + IN DWORD Flags); + #endif /* __SNDVOL32_H */