103c3dd5aSEric Kohl /*
203c3dd5aSEric Kohl * COPYRIGHT: See COPYING in the top level directory
303c3dd5aSEric Kohl * PROJECT: ReactOS Sound Volume Control
403c3dd5aSEric Kohl * FILE: base/applications/sndvol32/advanced.c
503c3dd5aSEric Kohl * PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
603c3dd5aSEric Kohl */
703c3dd5aSEric Kohl
803c3dd5aSEric Kohl #include "sndvol32.h"
903c3dd5aSEric Kohl
1026b52c4eSEric Kohl typedef struct _ADVANCED_DATA
1126b52c4eSEric Kohl {
1226b52c4eSEric Kohl PADVANCED_CONTEXT Context;
1326b52c4eSEric Kohl
1426b52c4eSEric Kohl BOOL bEnabled[4];
1526b52c4eSEric Kohl DWORD dwControlId[4];
1626b52c4eSEric Kohl
1726b52c4eSEric Kohl /* Bass and Treble */
1826b52c4eSEric Kohl DWORD dwMaximum[2];
1926b52c4eSEric Kohl DWORD dwMinimum[2];
2026b52c4eSEric Kohl
2126b52c4eSEric Kohl } ADVANCED_DATA, *PADVANCED_DATA;
2226b52c4eSEric Kohl
2303c3dd5aSEric Kohl static
2403c3dd5aSEric Kohl VOID
OnInitDialog(HWND hwndDlg,PADVANCED_DATA pData)2503c3dd5aSEric Kohl OnInitDialog(
2603c3dd5aSEric Kohl HWND hwndDlg,
2726b52c4eSEric Kohl PADVANCED_DATA pData)
2803c3dd5aSEric Kohl {
294ba3c904SEric Kohl MIXERCONTROLDETAILS_UNSIGNED UnsignedDetails;
302e797accSEric Kohl MIXERCONTROLDETAILS_BOOLEAN BooleanDetails;
312e797accSEric Kohl WCHAR szRawBuffer[256], szCookedBuffer[256];
3203c3dd5aSEric Kohl LPMIXERCONTROL Control = NULL;
334ba3c904SEric Kohl UINT ControlCount = 0, Index;
344ba3c904SEric Kohl DWORD i, dwStep, dwPosition;
352e797accSEric Kohl DWORD dwOtherControls = 0;
362e797accSEric Kohl RECT rect;
372e797accSEric Kohl LONG dy;
3803c3dd5aSEric Kohl
3903c3dd5aSEric Kohl /* Set the dialog title */
402e797accSEric Kohl LoadStringW(hAppInstance, IDS_ADVANCED_CONTROLS, szRawBuffer, ARRAYSIZE(szRawBuffer));
4126b52c4eSEric Kohl StringCchPrintfW(szCookedBuffer, ARRAYSIZE(szCookedBuffer), szRawBuffer, pData->Context->LineName);
422e797accSEric Kohl SetWindowTextW(hwndDlg, szCookedBuffer);
4303c3dd5aSEric Kohl
4403c3dd5aSEric Kohl /* Disable the tone controls */
4503c3dd5aSEric Kohl for (i = IDC_ADV_BASS_LOW; i<= IDC_ADV_TREBLE_SLIDER; i++)
4603c3dd5aSEric Kohl EnableWindow(GetDlgItem(hwndDlg, i), FALSE);
4703c3dd5aSEric Kohl
484ba3c904SEric Kohl /* Initialize the bass and treble trackbars */
494ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
504ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
514ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPAGESIZE, 0, (LPARAM)VOLUME_PAGE_SIZE);
524ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPAGESIZE, 0, (LPARAM)VOLUME_PAGE_SIZE);
534ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
544ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
554ba3c904SEric Kohl
564ba3c904SEric Kohl /* Calculate and set ticks */
574ba3c904SEric Kohl dwStep = (VOLUME_MAX / (VOLUME_TICKS + 1));
584ba3c904SEric Kohl if (VOLUME_MAX % (VOLUME_TICKS + 1) != 0)
594ba3c904SEric Kohl dwStep++;
604ba3c904SEric Kohl for (i = dwStep; i < VOLUME_MAX; i += dwStep)
614ba3c904SEric Kohl {
624ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETTIC, 0, (LPARAM)i);
634ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETTIC, 0, (LPARAM)i);
644ba3c904SEric Kohl }
654ba3c904SEric Kohl
6603c3dd5aSEric Kohl /* Hide the other controls */
6703c3dd5aSEric Kohl for (i = IDC_ADV_OTHER_CONTROLS; i<= IDC_ADV_OTHER_CHECK2; i++)
6803c3dd5aSEric Kohl ShowWindow(GetDlgItem(hwndDlg, i), SW_HIDE);
6903c3dd5aSEric Kohl
7026b52c4eSEric Kohl if (SndMixerQueryControls(pData->Context->Mixer, &ControlCount, pData->Context->Line, &Control))
7103c3dd5aSEric Kohl {
7203c3dd5aSEric Kohl for (Index = 0; Index < ControlCount; Index++)
7303c3dd5aSEric Kohl {
7403c3dd5aSEric Kohl if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_BASS)
7503c3dd5aSEric Kohl {
762e797accSEric Kohl /* Bass control */
772e797accSEric Kohl
7826b52c4eSEric Kohl if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&UnsignedDetails) != -1)
794ba3c904SEric Kohl {
8003c3dd5aSEric Kohl for (i = IDC_ADV_BASS_LOW; i<= IDC_ADV_BASS_SLIDER; i++)
8103c3dd5aSEric Kohl EnableWindow(GetDlgItem(hwndDlg, i), TRUE);
8203c3dd5aSEric Kohl
834ba3c904SEric Kohl dwStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
844ba3c904SEric Kohl dwPosition = (UnsignedDetails.dwValue - Control[Index].Bounds.dwMinimum) / dwStep;
854ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPOS, (WPARAM)TRUE, dwPosition);
8626b52c4eSEric Kohl
8726b52c4eSEric Kohl pData->bEnabled[0] = TRUE;
8826b52c4eSEric Kohl pData->dwControlId[0] = Control[Index].dwControlID;
8926b52c4eSEric Kohl pData->dwMaximum[0] = Control[Index].Bounds.dwMaximum;
9026b52c4eSEric Kohl pData->dwMinimum[0] = Control[Index].Bounds.dwMinimum;
914ba3c904SEric Kohl }
9203c3dd5aSEric Kohl }
9303c3dd5aSEric Kohl else if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_TREBLE)
9403c3dd5aSEric Kohl {
952e797accSEric Kohl /* Treble control */
962e797accSEric Kohl
9726b52c4eSEric Kohl if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&UnsignedDetails) != -1)
984ba3c904SEric Kohl {
9903c3dd5aSEric Kohl for (i = IDC_ADV_TREBLE_LOW; i<= IDC_ADV_TREBLE_SLIDER; i++)
10003c3dd5aSEric Kohl EnableWindow(GetDlgItem(hwndDlg, i), TRUE);
10103c3dd5aSEric Kohl
1024ba3c904SEric Kohl dwStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
1034ba3c904SEric Kohl dwPosition = (UnsignedDetails.dwValue - Control[Index].Bounds.dwMinimum) / dwStep;
1044ba3c904SEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPOS, (WPARAM)TRUE, dwPosition);
10526b52c4eSEric Kohl
10626b52c4eSEric Kohl pData->bEnabled[1] = TRUE;
10726b52c4eSEric Kohl pData->dwControlId[1] = Control[Index].dwControlID;
10826b52c4eSEric Kohl pData->dwMaximum[1] = Control[Index].Bounds.dwMaximum;
10926b52c4eSEric Kohl pData->dwMinimum[1] = Control[Index].Bounds.dwMinimum;
1104ba3c904SEric Kohl }
11103c3dd5aSEric Kohl }
1122e797accSEric Kohl else if (((Control[Index].dwControlType & (MIXERCONTROL_CT_CLASS_MASK | MIXERCONTROL_CT_SUBCLASS_MASK | MIXERCONTROL_CT_UNITS_MASK)) == MIXERCONTROL_CONTROLTYPE_BOOLEAN) &&
1132e797accSEric Kohl (Control[Index].dwControlType != MIXERCONTROL_CONTROLTYPE_MUTE))
11403c3dd5aSEric Kohl {
1152e797accSEric Kohl /* All boolean controls but the Mute control (Maximum of 2) */
11603c3dd5aSEric Kohl
1172e797accSEric Kohl if (dwOtherControls < 2)
1182e797accSEric Kohl {
11926b52c4eSEric Kohl if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&BooleanDetails) != -1)
1202e797accSEric Kohl {
1212e797accSEric Kohl LoadStringW(hAppInstance, IDS_OTHER_CONTROLS1 + dwOtherControls, szRawBuffer, ARRAYSIZE(szRawBuffer));
1222e797accSEric Kohl StringCchPrintfW(szCookedBuffer, ARRAYSIZE(szCookedBuffer), szRawBuffer, Control[Index].szName);
1232e797accSEric Kohl SetWindowTextW(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls), szCookedBuffer);
1242e797accSEric Kohl
1252e797accSEric Kohl ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls), SW_SHOWNORMAL);
1262e797accSEric Kohl
1272e797accSEric Kohl SendDlgItemMessageW(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls, BM_SETCHECK, (WPARAM)BooleanDetails.fValue, 0);
1282e797accSEric Kohl
12926b52c4eSEric Kohl pData->bEnabled[dwOtherControls + 2] = TRUE;
13026b52c4eSEric Kohl pData->dwControlId[dwOtherControls + 2] = Control[Index].dwControlID;
13126b52c4eSEric Kohl
1322e797accSEric Kohl dwOtherControls++;
1332e797accSEric Kohl }
1342e797accSEric Kohl }
13503c3dd5aSEric Kohl }
13603c3dd5aSEric Kohl }
13703c3dd5aSEric Kohl
138fba5a8fcSEric Kohl /* Free controls */
13903c3dd5aSEric Kohl HeapFree(GetProcessHeap(), 0, Control);
14003c3dd5aSEric Kohl }
1412e797accSEric Kohl
1422e797accSEric Kohl if (dwOtherControls != 0)
1432e797accSEric Kohl {
1442e797accSEric Kohl /* Show the 'Other controls' groupbox and text */
1452e797accSEric Kohl ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CONTROLS), SW_SHOWNORMAL);
1462e797accSEric Kohl ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_TEXT), SW_SHOWNORMAL);
1472e797accSEric Kohl
1482e797accSEric Kohl /* Resize the dialog */
1492e797accSEric Kohl GetWindowRect(hwndDlg, &rect);
1502e797accSEric Kohl
15126b52c4eSEric Kohl dy = MulDiv((dwOtherControls == 1) ? 73 : (73 + 15), pData->Context->MixerWindow->baseUnit.cy, 8);
1522e797accSEric Kohl rect.bottom += dy;
1532e797accSEric Kohl
1542e797accSEric Kohl SetWindowPos(hwndDlg, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
1552e797accSEric Kohl
1562e797accSEric Kohl /* Move the 'Close' button down */
1572e797accSEric Kohl GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect);
1582e797accSEric Kohl MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, 2);
1592e797accSEric Kohl
1602e797accSEric Kohl rect.top += dy;
1612e797accSEric Kohl rect.bottom += dy;
1622e797accSEric Kohl
1632e797accSEric Kohl SetWindowPos(GetDlgItem(hwndDlg, IDOK), HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOSIZE | SWP_NOZORDER);
164fba5a8fcSEric Kohl
165fba5a8fcSEric Kohl if (dwOtherControls == 2)
166fba5a8fcSEric Kohl {
167fba5a8fcSEric Kohl /* Resize the 'Other Controls' groupbox */
168fba5a8fcSEric Kohl GetWindowRect(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CONTROLS), &rect);
169fba5a8fcSEric Kohl MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, 2);
170fba5a8fcSEric Kohl
17126b52c4eSEric Kohl dy = MulDiv(15, pData->Context->MixerWindow->baseUnit.cy, 8);
172fba5a8fcSEric Kohl rect.bottom += dy;
173fba5a8fcSEric Kohl
174fba5a8fcSEric Kohl SetWindowPos(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CONTROLS), HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
175fba5a8fcSEric Kohl }
1762e797accSEric Kohl }
17703c3dd5aSEric Kohl }
17803c3dd5aSEric Kohl
17903c3dd5aSEric Kohl
18026b52c4eSEric Kohl static
18126b52c4eSEric Kohl VOID
OnHScroll(HWND hwndDlg,PADVANCED_DATA pData,DWORD dwCtrlID)18226b52c4eSEric Kohl OnHScroll(
18326b52c4eSEric Kohl HWND hwndDlg,
18426b52c4eSEric Kohl PADVANCED_DATA pData,
18526b52c4eSEric Kohl DWORD dwCtrlID)
18626b52c4eSEric Kohl {
18726b52c4eSEric Kohl MIXERCONTROLDETAILS_UNSIGNED Details;
18826b52c4eSEric Kohl DWORD dwControlID = 0, dwStep, dwPosition;
18926b52c4eSEric Kohl DWORD dwMaximum, dwMinimum;
19026b52c4eSEric Kohl
191*6bf7a8edSEric Kohl if (dwCtrlID != IDC_ADV_BASS_SLIDER &&
19226b52c4eSEric Kohl dwCtrlID != IDC_ADV_TREBLE_SLIDER)
19326b52c4eSEric Kohl return;
19426b52c4eSEric Kohl
19526b52c4eSEric Kohl if (dwCtrlID == IDC_ADV_BASS_SLIDER)
19626b52c4eSEric Kohl {
19726b52c4eSEric Kohl if (pData->bEnabled[0] == FALSE)
19826b52c4eSEric Kohl return;
19926b52c4eSEric Kohl
20026b52c4eSEric Kohl dwControlID = pData->dwControlId[0];
20126b52c4eSEric Kohl dwMaximum = pData->dwMaximum[0];
20226b52c4eSEric Kohl dwMinimum = pData->dwMinimum[0];
20326b52c4eSEric Kohl }
20426b52c4eSEric Kohl else if (dwCtrlID == IDC_ADV_TREBLE_SLIDER)
20526b52c4eSEric Kohl {
20626b52c4eSEric Kohl if (pData->bEnabled[1] == FALSE)
20726b52c4eSEric Kohl return;
20826b52c4eSEric Kohl
20926b52c4eSEric Kohl dwControlID = pData->dwControlId[1];
21026b52c4eSEric Kohl dwMaximum = pData->dwMaximum[1];
21126b52c4eSEric Kohl dwMinimum = pData->dwMinimum[1];
21226b52c4eSEric Kohl }
21326b52c4eSEric Kohl
21426b52c4eSEric Kohl dwPosition = (DWORD)SendDlgItemMessage(hwndDlg, dwCtrlID, TBM_GETPOS, 0, 0);
21526b52c4eSEric Kohl dwStep = (dwMaximum - dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
21626b52c4eSEric Kohl
21726b52c4eSEric Kohl Details.dwValue = (dwPosition * dwStep) + dwMinimum;
21826b52c4eSEric Kohl
21926b52c4eSEric Kohl SndMixerSetVolumeControlDetails(pData->Context->Mixer, dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), &Details);
22026b52c4eSEric Kohl }
22126b52c4eSEric Kohl
22226b52c4eSEric Kohl
22303c3dd5aSEric Kohl INT_PTR
22403c3dd5aSEric Kohl CALLBACK
AdvancedDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)22503c3dd5aSEric Kohl AdvancedDlgProc(
22603c3dd5aSEric Kohl HWND hwndDlg,
22703c3dd5aSEric Kohl UINT uMsg,
22803c3dd5aSEric Kohl WPARAM wParam,
22903c3dd5aSEric Kohl LPARAM lParam)
23003c3dd5aSEric Kohl {
23126b52c4eSEric Kohl PADVANCED_DATA pData;
23226b52c4eSEric Kohl
23326b52c4eSEric Kohl pData = (PADVANCED_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
23403c3dd5aSEric Kohl
23503c3dd5aSEric Kohl switch (uMsg)
23603c3dd5aSEric Kohl {
23703c3dd5aSEric Kohl case WM_INITDIALOG:
23826b52c4eSEric Kohl pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ADVANCED_DATA));
23926b52c4eSEric Kohl if (pData != NULL)
24026b52c4eSEric Kohl {
24126b52c4eSEric Kohl SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
24226b52c4eSEric Kohl pData->Context = (PADVANCED_CONTEXT)((LONG_PTR)lParam);
24326b52c4eSEric Kohl OnInitDialog(hwndDlg, pData);
24426b52c4eSEric Kohl }
24503c3dd5aSEric Kohl return TRUE;
24603c3dd5aSEric Kohl
24703c3dd5aSEric Kohl case WM_COMMAND:
24803c3dd5aSEric Kohl switch (LOWORD(wParam))
24903c3dd5aSEric Kohl {
25003c3dd5aSEric Kohl case IDOK:
25103c3dd5aSEric Kohl EndDialog(hwndDlg, IDOK);
25203c3dd5aSEric Kohl break;
25303c3dd5aSEric Kohl }
25403c3dd5aSEric Kohl break;
25503c3dd5aSEric Kohl
25626b52c4eSEric Kohl case WM_HSCROLL:
25726b52c4eSEric Kohl if (pData != NULL)
25826b52c4eSEric Kohl {
25926b52c4eSEric Kohl if (LOWORD(wParam) == TB_THUMBTRACK)
26026b52c4eSEric Kohl OnHScroll(hwndDlg, pData, GetDlgCtrlID((HWND)lParam));
26126b52c4eSEric Kohl }
26226b52c4eSEric Kohl break;
26326b52c4eSEric Kohl
26403c3dd5aSEric Kohl case WM_CLOSE:
26503c3dd5aSEric Kohl EndDialog(hwndDlg, IDCANCEL);
26603c3dd5aSEric Kohl break;
26726b52c4eSEric Kohl
26826b52c4eSEric Kohl case WM_DESTROY:
26926b52c4eSEric Kohl if (pData != NULL)
27026b52c4eSEric Kohl {
27126b52c4eSEric Kohl HeapFree(GetProcessHeap(), 0, pData);
27226b52c4eSEric Kohl SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)NULL);
27326b52c4eSEric Kohl }
27426b52c4eSEric Kohl break;
27503c3dd5aSEric Kohl }
27603c3dd5aSEric Kohl
27703c3dd5aSEric Kohl return FALSE;
27803c3dd5aSEric Kohl }
27903c3dd5aSEric Kohl
28003c3dd5aSEric Kohl /* EOF */
281