2019-02-21 21:26:58 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Sound Volume Control
|
|
|
|
* FILE: base/applications/sndvol32/advanced.c
|
|
|
|
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sndvol32.h"
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
typedef struct _ADVANCED_DATA
|
|
|
|
{
|
|
|
|
PADVANCED_CONTEXT Context;
|
|
|
|
|
|
|
|
BOOL bEnabled[4];
|
|
|
|
DWORD dwControlId[4];
|
|
|
|
|
|
|
|
/* Bass and Treble */
|
|
|
|
DWORD dwMaximum[2];
|
|
|
|
DWORD dwMinimum[2];
|
|
|
|
|
|
|
|
} ADVANCED_DATA, *PADVANCED_DATA;
|
|
|
|
|
2019-02-21 21:26:58 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
OnInitDialog(
|
|
|
|
HWND hwndDlg,
|
2019-02-24 11:50:37 +00:00
|
|
|
PADVANCED_DATA pData)
|
2019-02-21 21:26:58 +00:00
|
|
|
{
|
2019-02-22 22:33:47 +00:00
|
|
|
MIXERCONTROLDETAILS_UNSIGNED UnsignedDetails;
|
2019-02-23 11:51:14 +00:00
|
|
|
MIXERCONTROLDETAILS_BOOLEAN BooleanDetails;
|
|
|
|
WCHAR szRawBuffer[256], szCookedBuffer[256];
|
2019-02-21 21:26:58 +00:00
|
|
|
LPMIXERCONTROL Control = NULL;
|
2019-02-22 22:33:47 +00:00
|
|
|
UINT ControlCount = 0, Index;
|
|
|
|
DWORD i, dwStep, dwPosition;
|
2019-02-23 11:51:14 +00:00
|
|
|
DWORD dwOtherControls = 0;
|
|
|
|
RECT rect;
|
|
|
|
LONG dy;
|
2019-02-21 21:26:58 +00:00
|
|
|
|
|
|
|
/* Set the dialog title */
|
2019-02-23 11:51:14 +00:00
|
|
|
LoadStringW(hAppInstance, IDS_ADVANCED_CONTROLS, szRawBuffer, ARRAYSIZE(szRawBuffer));
|
2019-02-24 11:50:37 +00:00
|
|
|
StringCchPrintfW(szCookedBuffer, ARRAYSIZE(szCookedBuffer), szRawBuffer, pData->Context->LineName);
|
2019-02-23 11:51:14 +00:00
|
|
|
SetWindowTextW(hwndDlg, szCookedBuffer);
|
2019-02-21 21:26:58 +00:00
|
|
|
|
|
|
|
/* Disable the tone controls */
|
|
|
|
for (i = IDC_ADV_BASS_LOW; i<= IDC_ADV_TREBLE_SLIDER; i++)
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, i), FALSE);
|
|
|
|
|
2019-02-22 22:33:47 +00:00
|
|
|
/* Initialize the bass and treble trackbars */
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPAGESIZE, 0, (LPARAM)VOLUME_PAGE_SIZE);
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPAGESIZE, 0, (LPARAM)VOLUME_PAGE_SIZE);
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
|
|
|
|
|
|
|
|
/* Calculate and set ticks */
|
|
|
|
dwStep = (VOLUME_MAX / (VOLUME_TICKS + 1));
|
|
|
|
if (VOLUME_MAX % (VOLUME_TICKS + 1) != 0)
|
|
|
|
dwStep++;
|
|
|
|
for (i = dwStep; i < VOLUME_MAX; i += dwStep)
|
|
|
|
{
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETTIC, 0, (LPARAM)i);
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETTIC, 0, (LPARAM)i);
|
|
|
|
}
|
|
|
|
|
2019-02-21 21:26:58 +00:00
|
|
|
/* Hide the other controls */
|
|
|
|
for (i = IDC_ADV_OTHER_CONTROLS; i<= IDC_ADV_OTHER_CHECK2; i++)
|
|
|
|
ShowWindow(GetDlgItem(hwndDlg, i), SW_HIDE);
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
if (SndMixerQueryControls(pData->Context->Mixer, &ControlCount, pData->Context->Line, &Control))
|
2019-02-21 21:26:58 +00:00
|
|
|
{
|
|
|
|
for (Index = 0; Index < ControlCount; Index++)
|
|
|
|
{
|
|
|
|
if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_BASS)
|
|
|
|
{
|
2019-02-23 11:51:14 +00:00
|
|
|
/* Bass control */
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&UnsignedDetails) != -1)
|
2019-02-22 22:33:47 +00:00
|
|
|
{
|
|
|
|
for (i = IDC_ADV_BASS_LOW; i<= IDC_ADV_BASS_SLIDER; i++)
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, i), TRUE);
|
2019-02-21 21:26:58 +00:00
|
|
|
|
2019-02-22 22:33:47 +00:00
|
|
|
dwStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
|
|
|
|
dwPosition = (UnsignedDetails.dwValue - Control[Index].Bounds.dwMinimum) / dwStep;
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_BASS_SLIDER, TBM_SETPOS, (WPARAM)TRUE, dwPosition);
|
2019-02-24 11:50:37 +00:00
|
|
|
|
|
|
|
pData->bEnabled[0] = TRUE;
|
|
|
|
pData->dwControlId[0] = Control[Index].dwControlID;
|
|
|
|
pData->dwMaximum[0] = Control[Index].Bounds.dwMaximum;
|
|
|
|
pData->dwMinimum[0] = Control[Index].Bounds.dwMinimum;
|
2019-02-22 22:33:47 +00:00
|
|
|
}
|
2019-02-21 21:26:58 +00:00
|
|
|
}
|
|
|
|
else if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_TREBLE)
|
|
|
|
{
|
2019-02-23 11:51:14 +00:00
|
|
|
/* Treble control */
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&UnsignedDetails) != -1)
|
2019-02-22 22:33:47 +00:00
|
|
|
{
|
|
|
|
for (i = IDC_ADV_TREBLE_LOW; i<= IDC_ADV_TREBLE_SLIDER; i++)
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, i), TRUE);
|
2019-02-21 21:26:58 +00:00
|
|
|
|
2019-02-22 22:33:47 +00:00
|
|
|
dwStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
|
|
|
|
dwPosition = (UnsignedDetails.dwValue - Control[Index].Bounds.dwMinimum) / dwStep;
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_TREBLE_SLIDER, TBM_SETPOS, (WPARAM)TRUE, dwPosition);
|
2019-02-24 11:50:37 +00:00
|
|
|
|
|
|
|
pData->bEnabled[1] = TRUE;
|
|
|
|
pData->dwControlId[1] = Control[Index].dwControlID;
|
|
|
|
pData->dwMaximum[1] = Control[Index].Bounds.dwMaximum;
|
|
|
|
pData->dwMinimum[1] = Control[Index].Bounds.dwMinimum;
|
2019-02-22 22:33:47 +00:00
|
|
|
}
|
2019-02-21 21:26:58 +00:00
|
|
|
}
|
2019-02-23 11:51:14 +00:00
|
|
|
else if (((Control[Index].dwControlType & (MIXERCONTROL_CT_CLASS_MASK | MIXERCONTROL_CT_SUBCLASS_MASK | MIXERCONTROL_CT_UNITS_MASK)) == MIXERCONTROL_CONTROLTYPE_BOOLEAN) &&
|
|
|
|
(Control[Index].dwControlType != MIXERCONTROL_CONTROLTYPE_MUTE))
|
2019-02-21 21:26:58 +00:00
|
|
|
{
|
2019-02-23 11:51:14 +00:00
|
|
|
/* All boolean controls but the Mute control (Maximum of 2) */
|
|
|
|
|
|
|
|
if (dwOtherControls < 2)
|
|
|
|
{
|
2019-02-24 11:50:37 +00:00
|
|
|
if (SndMixerGetVolumeControlDetails(pData->Context->Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&BooleanDetails) != -1)
|
2019-02-23 11:51:14 +00:00
|
|
|
{
|
|
|
|
LoadStringW(hAppInstance, IDS_OTHER_CONTROLS1 + dwOtherControls, szRawBuffer, ARRAYSIZE(szRawBuffer));
|
|
|
|
StringCchPrintfW(szCookedBuffer, ARRAYSIZE(szCookedBuffer), szRawBuffer, Control[Index].szName);
|
|
|
|
SetWindowTextW(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls), szCookedBuffer);
|
2019-02-21 21:26:58 +00:00
|
|
|
|
2019-02-23 11:51:14 +00:00
|
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls), SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_ADV_OTHER_CHECK1 + dwOtherControls, BM_SETCHECK, (WPARAM)BooleanDetails.fValue, 0);
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
pData->bEnabled[dwOtherControls + 2] = TRUE;
|
|
|
|
pData->dwControlId[dwOtherControls + 2] = Control[Index].dwControlID;
|
|
|
|
|
2019-02-23 11:51:14 +00:00
|
|
|
dwOtherControls++;
|
|
|
|
}
|
|
|
|
}
|
2019-02-21 21:26:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-23 16:21:25 +00:00
|
|
|
/* Free controls */
|
2019-02-21 21:26:58 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, Control);
|
|
|
|
}
|
2019-02-23 11:51:14 +00:00
|
|
|
|
|
|
|
if (dwOtherControls != 0)
|
|
|
|
{
|
|
|
|
/* Show the 'Other controls' groupbox and text */
|
|
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CONTROLS), SW_SHOWNORMAL);
|
|
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_ADV_OTHER_TEXT), SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
/* Resize the dialog */
|
|
|
|
GetWindowRect(hwndDlg, &rect);
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
dy = MulDiv((dwOtherControls == 1) ? 73 : (73 + 15), pData->Context->MixerWindow->baseUnit.cy, 8);
|
2019-02-23 11:51:14 +00:00
|
|
|
rect.bottom += dy;
|
|
|
|
|
|
|
|
SetWindowPos(hwndDlg, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
|
|
|
|
/* Move the 'Close' button down */
|
|
|
|
GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect);
|
|
|
|
MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, 2);
|
|
|
|
|
|
|
|
rect.top += dy;
|
|
|
|
rect.bottom += dy;
|
|
|
|
|
|
|
|
SetWindowPos(GetDlgItem(hwndDlg, IDOK), HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOSIZE | SWP_NOZORDER);
|
2019-02-23 16:21:25 +00:00
|
|
|
|
|
|
|
if (dwOtherControls == 2)
|
|
|
|
{
|
|
|
|
/* Resize the 'Other Controls' groupbox */
|
|
|
|
GetWindowRect(GetDlgItem(hwndDlg, IDC_ADV_OTHER_CONTROLS), &rect);
|
|
|
|
MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, 2);
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
dy = MulDiv(15, pData->Context->MixerWindow->baseUnit.cy, 8);
|
2019-02-23 16:21:25 +00:00
|
|
|
rect.bottom += dy;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2019-02-23 11:51:14 +00:00
|
|
|
}
|
2019-02-21 21:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
OnHScroll(
|
|
|
|
HWND hwndDlg,
|
|
|
|
PADVANCED_DATA pData,
|
|
|
|
DWORD dwCtrlID)
|
|
|
|
{
|
|
|
|
MIXERCONTROLDETAILS_UNSIGNED Details;
|
|
|
|
DWORD dwControlID = 0, dwStep, dwPosition;
|
|
|
|
DWORD dwMaximum, dwMinimum;
|
|
|
|
|
2019-09-24 21:28:17 +00:00
|
|
|
if (dwCtrlID != IDC_ADV_BASS_SLIDER &&
|
2019-02-24 11:50:37 +00:00
|
|
|
dwCtrlID != IDC_ADV_TREBLE_SLIDER)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (dwCtrlID == IDC_ADV_BASS_SLIDER)
|
|
|
|
{
|
|
|
|
if (pData->bEnabled[0] == FALSE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dwControlID = pData->dwControlId[0];
|
|
|
|
dwMaximum = pData->dwMaximum[0];
|
|
|
|
dwMinimum = pData->dwMinimum[0];
|
|
|
|
}
|
|
|
|
else if (dwCtrlID == IDC_ADV_TREBLE_SLIDER)
|
|
|
|
{
|
|
|
|
if (pData->bEnabled[1] == FALSE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dwControlID = pData->dwControlId[1];
|
|
|
|
dwMaximum = pData->dwMaximum[1];
|
|
|
|
dwMinimum = pData->dwMinimum[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
dwPosition = (DWORD)SendDlgItemMessage(hwndDlg, dwCtrlID, TBM_GETPOS, 0, 0);
|
|
|
|
dwStep = (dwMaximum - dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
|
|
|
|
|
|
|
|
Details.dwValue = (dwPosition * dwStep) + dwMinimum;
|
|
|
|
|
|
|
|
SndMixerSetVolumeControlDetails(pData->Context->Mixer, dwControlID, 1, sizeof(MIXERCONTROLDETAILS_UNSIGNED), &Details);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-21 21:26:58 +00:00
|
|
|
INT_PTR
|
|
|
|
CALLBACK
|
|
|
|
AdvancedDlgProc(
|
|
|
|
HWND hwndDlg,
|
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2019-02-24 11:50:37 +00:00
|
|
|
PADVANCED_DATA pData;
|
|
|
|
|
|
|
|
pData = (PADVANCED_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
|
2019-02-21 21:26:58 +00:00
|
|
|
|
|
|
|
switch (uMsg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
2019-02-24 11:50:37 +00:00
|
|
|
pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ADVANCED_DATA));
|
|
|
|
if (pData != NULL)
|
|
|
|
{
|
|
|
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
|
|
|
|
pData->Context = (PADVANCED_CONTEXT)((LONG_PTR)lParam);
|
|
|
|
OnInitDialog(hwndDlg, pData);
|
|
|
|
}
|
2019-02-21 21:26:58 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case IDOK:
|
|
|
|
EndDialog(hwndDlg, IDOK);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-02-24 11:50:37 +00:00
|
|
|
case WM_HSCROLL:
|
|
|
|
if (pData != NULL)
|
|
|
|
{
|
|
|
|
if (LOWORD(wParam) == TB_THUMBTRACK)
|
|
|
|
OnHScroll(hwndDlg, pData, GetDlgCtrlID((HWND)lParam));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-02-21 21:26:58 +00:00
|
|
|
case WM_CLOSE:
|
|
|
|
EndDialog(hwndDlg, IDCANCEL);
|
|
|
|
break;
|
2019-02-24 11:50:37 +00:00
|
|
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
if (pData != NULL)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, pData);
|
|
|
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)NULL);
|
|
|
|
}
|
|
|
|
break;
|
2019-02-21 21:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|