mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 04:07:16 +00:00
[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:
parent
c09a7b5bd7
commit
431f9bf311
4 changed files with 153 additions and 38 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -443,7 +443,7 @@ VolumeDlgProc(HWND hwndDlg,
|
|||
break;
|
||||
|
||||
case IDC_SPEAKER_VOL_BTN:
|
||||
SpeakerVolume(hwndDlg, pGlobalData->hMixer);
|
||||
SpeakerVolume(hwndDlg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue