#include "mmsys.h"
+typedef struct _PAGE_DATA
+{
+ HMIXER hMixer;
+ DWORD volumeControlID;
+ DWORD volumeChannels;
+ DWORD volumeMinimum;
+ DWORD volumeMaximum;
+ DWORD volumeStep;
+ PMIXERCONTROLDETAILS_UNSIGNED volumeValues;
+ BOOL volumeSync;
+} 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;
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 */
}
+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 < pPageData->volumeChannels; 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;
+ DWORD dwValue, dwPosition;
+ INT id, idx, i, j;
+
+ id = (INT)GetWindowLongPtr((HWND)lParam, GWLP_ID);
+ if (id < 9475 && id > 9503)
+ return;
+
+ if ((id - 9475) % 4 != 0)
+ return;
+
+ dwPosition = (DWORD)SendDlgItemMessage(hwndDlg, id, TBM_GETPOS, 0, 0);
+
+ if (dwPosition == VOLUME_MIN)
+ dwValue = pPageData->volumeMinimum;
+ else if (dwPosition == VOLUME_MAX)
+ dwValue = pPageData->volumeMaximum;
+ else
+ dwValue = (dwPosition * pPageData->volumeStep) + pPageData->volumeMinimum;
+
+ if (pPageData->volumeSync)
+ {
+ for (i = 0; i < pPageData->volumeChannels; i++)
+ {
+ j = 9475 + (i * 4);
+ if (j != id)
+ SendDlgItemMessage(hwndDlg, j, TBM_SETPOS, (WPARAM)TRUE, dwPosition);
+
+ pPageData->volumeValues[i].dwValue = dwValue;
+ }
+ }
+ else
+ {
+ idx = (id - 9475) / 4;
+ pPageData->volumeValues[idx].dwValue = dwValue;
+ }
+
+ 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;
+}
+
+
+static
+VOID
+OnSetDefaults(
+ PPAGE_DATA pPageData,
+ HWND hwndDlg)
+{
+ MIXERCONTROLDETAILS mxcd;
+ DWORD dwValue, i;
+
+ dwValue = ((VOLUME_MAX - VOLUME_MIN) / 2 * pPageData->volumeStep) + pPageData->volumeMinimum;
+
+ for (i = 0; i < pPageData->volumeChannels; i++)
+ pPageData->volumeValues[i].dwValue = dwValue;
+
+ 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(
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);
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case 9504:
+ if (HIWORD(wParam) == BN_CLICKED)
+ pPageData->volumeSync = (SendDlgItemMessage(hwndDlg, 9504, BM_GETCHECK, 0, 0) == BST_CHECKED);
+ break;
+
+ case 9505:
+ OnSetDefaults(pPageData, hwndDlg);
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ break;
+ }
break;
case WM_NOTIFY:
return TRUE;
+
+ case MM_MIXM_CONTROL_CHANGE:
+ if (pPageData)
+ OnMixerControlChange(pPageData, hwndDlg);
+ break;
}
return FALSE;
INT_PTR
SpeakerVolume(
- HWND hwnd,
- HMIXER hMixer)
+ HWND hwndDlg)
{
PROPSHEETPAGE psp[1];
PROPSHEETHEADER psh;
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);
+ psp[0].dwFlags |= PSP_USETITLE;
+ psp[0].pszTitle = Caption;
return (LONG)(PropertySheet(&psh) != -1);
}