From 431f9bf3110b6868ab2d08fab0812841bc0a7f6e Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 20 Jan 2019 21:59:45 +0100 Subject: [PATCH] [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. --- dll/cpl/mmsys/mmsys.c | 14 ++- dll/cpl/mmsys/mmsys.h | 6 +- dll/cpl/mmsys/speakervolume.c | 169 +++++++++++++++++++++++++++++----- dll/cpl/mmsys/volume.c | 2 +- 4 files changed, 153 insertions(+), 38 deletions(-) diff --git a/dll/cpl/mmsys/mmsys.c b/dll/cpl/mmsys/mmsys.c index c7c1ca9a6e7..e2d7c8e5391 100644 --- a/dll/cpl/mmsys/mmsys.c +++ b/dll/cpl/mmsys/mmsys.c @@ -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; } diff --git a/dll/cpl/mmsys/mmsys.h b/dll/cpl/mmsys/mmsys.h index 63d6b2d9003..0fdae63c8ce 100644 --- a/dll/cpl/mmsys/mmsys.h +++ b/dll/cpl/mmsys/mmsys.h @@ -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 */ diff --git a/dll/cpl/mmsys/speakervolume.c b/dll/cpl/mmsys/speakervolume.c index 270cdfcd02e..4acb5a82c57 100644 --- a/dll/cpl/mmsys/speakervolume.c +++ b/dll/cpl/mmsys/speakervolume.c @@ -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); } diff --git a/dll/cpl/mmsys/volume.c b/dll/cpl/mmsys/volume.c index e5cda691088..2d080374842 100644 --- a/dll/cpl/mmsys/volume.c +++ b/dll/cpl/mmsys/volume.c @@ -443,7 +443,7 @@ VolumeDlgProc(HWND hwndDlg, break; case IDC_SPEAKER_VOL_BTN: - SpeakerVolume(hwndDlg, pGlobalData->hMixer); + SpeakerVolume(hwndDlg); break; } break;