[MMSYS] Improvements to the speaker volume property page

- Open a separate mixer instance for the page, so that MM_MIXM_CONTROL_CHANGE notifications can be received.
- Keep line and channel configurations in a global struct.
- Handle MM_MIXM_CONTROL_CHANGE and WM_HSCROLL notifications.
This commit is contained in:
Eric Kohl 2019-01-20 21:59:45 +01:00
parent c09a7b5bd7
commit 431f9bf311
4 changed files with 153 additions and 38 deletions

View file

@ -733,11 +733,11 @@ MmSysApplet(HWND hwnd,
psh.ppsp = psp;
psh.pfnCallback = PropSheetProc;
InitPropSheetPage(&psp[0], IDD_VOLUME,VolumeDlgProc, 0);
InitPropSheetPage(&psp[1], IDD_SOUNDS,SoundsDlgProc, 0);
InitPropSheetPage(&psp[2], IDD_AUDIO,AudioDlgProc, 0);
InitPropSheetPage(&psp[3], IDD_VOICE,VoiceDlgProc, 0);
InitPropSheetPage(&psp[4], IDD_HARDWARE,HardwareDlgProc, 0);
InitPropSheetPage(&psp[0], IDD_VOLUME,VolumeDlgProc);
InitPropSheetPage(&psp[1], IDD_SOUNDS,SoundsDlgProc);
InitPropSheetPage(&psp[2], IDD_AUDIO,AudioDlgProc);
InitPropSheetPage(&psp[3], IDD_VOICE,VoiceDlgProc);
InitPropSheetPage(&psp[4], IDD_HARDWARE,HardwareDlgProc);
return (LONG)(PropertySheet(&psh) != -1);
}
@ -745,8 +745,7 @@ MmSysApplet(HWND hwnd,
VOID
InitPropSheetPage(PROPSHEETPAGE *psp,
WORD idDlg,
DLGPROC DlgProc,
LPARAM lParam)
DLGPROC DlgProc)
{
ZeroMemory(psp, sizeof(PROPSHEETPAGE));
psp->dwSize = sizeof(PROPSHEETPAGE);
@ -754,7 +753,6 @@ InitPropSheetPage(PROPSHEETPAGE *psp,
psp->hInstance = hApplet;
psp->pszTemplate = MAKEINTRESOURCE(idDlg);
psp->pfnDlgProc = DlgProc;
psp->lParam = lParam;
}

View file

@ -48,8 +48,7 @@ VOID
InitPropSheetPage(
PROPSHEETPAGE *psp,
WORD idDlg,
DLGPROC DlgProc,
LPARAM lParam);
DLGPROC DlgProc);
LONG APIENTRY
MmSysApplet(HWND hwnd,
@ -93,7 +92,6 @@ AudioDlgProc(HWND hwndDlg,
/* speakervolume.c */
INT_PTR
SpeakerVolume(HWND hwndDlg,
HMIXER hMixer);
SpeakerVolume(HWND hwndDlg);
#endif /* _MMSYS_H */

View file

@ -7,30 +7,48 @@
#include "mmsys.h"
typedef struct _PAGE_DATA
{
HMIXER hMixer;
DWORD volumeControlID;
DWORD volumeChannels;
DWORD volumeMinimum;
DWORD volumeMaximum;
DWORD volumeStep;
PMIXERCONTROLDETAILS_UNSIGNED volumeValues;
} PAGE_DATA, *PPAGE_DATA;
static
BOOL
OnInitDialog(
HWND hwndDlg,
LPARAM lParam)
PPAGE_DATA pPageData,
HWND hwndDlg)
{
TCHAR szBuffer[256];
MIXERLINE mxln;
MIXERCONTROL mxc;
MIXERLINECONTROLS mxlctrl;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume[8];
INT i, j;
DWORD dwStep;
HMIXER hMixer;
hMixer = (HMIXER)((LPPROPSHEETPAGE)lParam)->lParam;
/* Open the mixer */
if (mixerOpen(&pPageData->hMixer, 0, PtrToUlong(hwndDlg), 0, MIXER_OBJECTF_MIXER | CALLBACK_WINDOW) != MMSYSERR_NOERROR)
{
MessageBox(hwndDlg, _T("Cannot open mixer"), NULL, MB_OK);
return FALSE;
}
/* Retrieve the mixer information */
mxln.cbStruct = sizeof(MIXERLINE);
mxln.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if (mixerGetLineInfo((HMIXEROBJ)hMixer, &mxln, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
if (mixerGetLineInfo((HMIXEROBJ)pPageData->hMixer, &mxln, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
return FALSE;
pPageData->volumeChannels = mxln.cChannels;
/* Retrieve the line information */
mxlctrl.cbStruct = sizeof(MIXERLINECONTROLS);
mxlctrl.dwLineID = mxln.dwLineID;
mxlctrl.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
@ -38,39 +56,46 @@ OnInitDialog(
mxlctrl.cbmxctrl = sizeof(MIXERCONTROL);
mxlctrl.pamxctrl = &mxc;
if (mixerGetLineControls((HMIXEROBJ)hMixer, &mxlctrl, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR)
if (mixerGetLineControls((HMIXEROBJ)pPageData->hMixer, &mxlctrl, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR)
return FALSE;
// pGlobalData->volumeMinimum = mxc.Bounds.dwMinimum;
// pGlobalData->volumeMaximum = mxc.Bounds.dwMaximum;
// pGlobalData->volumeControlID = mxc.dwControlID;
// pGlobalData->volumeStep = (pGlobalData->volumeMaximum - pGlobalData->volumeMinimum) / (VOLUME_MAX - VOLUME_MIN);
dwStep = (mxc.Bounds.dwMaximum - mxc.Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
pPageData->volumeControlID = mxc.dwControlID;
pPageData->volumeMinimum = mxc.Bounds.dwMinimum;
pPageData->volumeMaximum = mxc.Bounds.dwMaximum;
pPageData->volumeStep = (pPageData->volumeMaximum - pPageData->volumeMinimum) / (VOLUME_MAX - VOLUME_MIN);
/* Allocate a buffer for all channel volume values */
pPageData->volumeValues = HeapAlloc(GetProcessHeap(),
0,
mxln.cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
if (pPageData->volumeValues == NULL)
return FALSE;
/* Retrieve the channel volume values */
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = mxc.dwControlID;
mxcd.cChannels = mxln.cChannels;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
mxcd.paDetails = pPageData->volumeValues;
if (mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
if (mixerGetControlDetails((HMIXEROBJ)pPageData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return FALSE;
// pGlobalData->volumeValue[i] = mxcdVolume[i].dwValue;
/* Initialize the channels */
for (i = 0; i < min(mxln.cChannels, 5); i++)
{
j = i * 4;
LoadString(hApplet, 5792 + i, szBuffer, _countof(szBuffer));
/* Set the channel name */
LoadString(hApplet, IDS_SPEAKER_LEFT + i, szBuffer, _countof(szBuffer));
SetWindowText(GetDlgItem(hwndDlg, 9472 + j), szBuffer);
/* Initialize the channel trackbar */
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETTICFREQ, VOLUME_TICFREQ, 0);
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETPAGESIZE, 0, VOLUME_PAGESIZE);
// SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pGlobalData->volumeValue - pGlobalData->volumeMinimum) / pGlobalData->volumeStep);
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(mxcdVolume[i].dwValue - mxc.Bounds.dwMinimum) / dwStep);
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pPageData->volumeValues[i].dwValue - pPageData->volumeMinimum) / pPageData->volumeStep);
}
/* Hide the unused controls */
@ -87,6 +112,69 @@ OnInitDialog(
}
static
VOID
OnMixerControlChange(
PPAGE_DATA pPageData,
HWND hwndDlg)
{
MIXERCONTROLDETAILS mxcd;
INT i, j;
/* Retrieve the channel volume values */
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pPageData->volumeControlID;
mxcd.cChannels = pPageData->volumeChannels;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = pPageData->volumeValues;
if (mixerGetControlDetails((HMIXEROBJ)pPageData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return;
for (i = 0; i < min(pPageData->volumeChannels, 5); i++)
{
j = i * 4;
SendDlgItemMessage(hwndDlg, 9475 + j, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pPageData->volumeValues[i].dwValue - pPageData->volumeMinimum) / pPageData->volumeStep);
}
}
static
VOID
OnHScroll(
PPAGE_DATA pPageData,
HWND hwndDlg,
WPARAM wParam,
LPARAM lParam)
{
MIXERCONTROLDETAILS mxcd;
INT id, idx;
id = (INT)GetWindowLongPtr((HWND)lParam, GWLP_ID);
if (id < 9475 && id > 9503)
return;
if ((id - 9475) % 4 != 0)
return;
idx = (id - 9475) / 4;
pPageData->volumeValues[idx].dwValue = ((DWORD)SendDlgItemMessage(hwndDlg, id, TBM_GETPOS, 0, 0) * pPageData->volumeStep) + pPageData->volumeMinimum;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pPageData->volumeControlID;
mxcd.cChannels = pPageData->volumeChannels;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = pPageData->volumeValues;
if (mixerSetControlDetails((HMIXEROBJ)pPageData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
return;
}
INT_PTR
CALLBACK
SpeakerVolumeDlgProc(
@ -95,19 +183,51 @@ SpeakerVolumeDlgProc(
WPARAM wParam,
LPARAM lParam)
{
PPAGE_DATA pPageData;
UNREFERENCED_PARAMETER(wParam);
pPageData = (PPAGE_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch(uMsg)
{
case WM_INITDIALOG:
OnInitDialog(hwndDlg, lParam);
pPageData = (PPAGE_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PAGE_DATA));
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPageData);
if (pPageData)
{
OnInitDialog(pPageData, hwndDlg);
}
break;
case WM_DESTROY:
if (pPageData)
{
if (pPageData->volumeValues)
HeapFree(GetProcessHeap(), 0, pPageData->volumeValues);
if (pPageData->hMixer)
mixerClose(pPageData->hMixer);
HeapFree(GetProcessHeap(), 0, pPageData);
pPageData = NULL;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)NULL);
}
break;
case WM_HSCROLL:
if (pPageData)
OnHScroll(pPageData, hwndDlg, wParam, lParam);
break;
case WM_NOTIFY:
return TRUE;
case MM_MIXM_CONTROL_CHANGE:
if (pPageData)
OnMixerControlChange(pPageData, hwndDlg);
break;
}
return FALSE;
@ -116,8 +236,7 @@ SpeakerVolumeDlgProc(
INT_PTR
SpeakerVolume(
HWND hwnd,
HMIXER hMixer)
HWND hwndDlg)
{
PROPSHEETPAGE psp[1];
PROPSHEETHEADER psh;
@ -128,14 +247,14 @@ SpeakerVolume(
ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE;
psh.hwndParent = hwnd;
psh.hwndParent = hwndDlg;
psh.hInstance = hApplet;
psh.pszCaption = Caption;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = psp;
InitPropSheetPage(&psp[0], IDD_MULTICHANNEL, SpeakerVolumeDlgProc, (LPARAM)hMixer);
InitPropSheetPage(&psp[0], IDD_MULTICHANNEL, SpeakerVolumeDlgProc);
return (LONG)(PropertySheet(&psh) != -1);
}

View file

@ -443,7 +443,7 @@ VolumeDlgProc(HWND hwndDlg,
break;
case IDC_SPEAKER_VOL_BTN:
SpeakerVolume(hwndDlg, pGlobalData->hMixer);
SpeakerVolume(hwndDlg);
break;
}
break;