[MMSYS] Improvements to the speaker volume property page
authorEric Kohl <eric.kohl@reactos.org>
Sun, 20 Jan 2019 20:59:45 +0000 (21:59 +0100)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 20 Jan 2019 21:00:42 +0000 (22:00 +0100)
- 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
dll/cpl/mmsys/mmsys.h
dll/cpl/mmsys/speakervolume.c
dll/cpl/mmsys/volume.c

index c7c1ca9..e2d7c8e 100644 (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;
 }
 
 
index 63d6b2d..0fdae63 100644 (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 */
index 270cdfc..4acb5a8 100644 (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);
 }
index e5cda69..2d08037 100644 (file)
@@ -443,7 +443,7 @@ VolumeDlgProc(HWND hwndDlg,
                     break;
 
                 case IDC_SPEAKER_VOL_BTN:
-                    SpeakerVolume(hwndDlg, pGlobalData->hMixer);
+                    SpeakerVolume(hwndDlg);
                     break;
             }
             break;