2 * PROJECT: ReactOS Multimedia Control Panel
3 * FILE: dll/cpl/mmsys/speakervolume.c
4 * PURPOSE: ReactOS Multimedia Control Panel
5 * PROGRAMMER: Eric Kohl <eric.kohl@reactos.com>
10 typedef struct _PAGE_DATA
13 DWORD volumeControlID
;
18 PMIXERCONTROLDETAILS_UNSIGNED volumeValues
;
20 } PAGE_DATA
, *PPAGE_DATA
;
32 MIXERLINECONTROLS mxlctrl
;
33 MIXERCONTROLDETAILS mxcd
;
37 if (mixerOpen(&pPageData
->hMixer
, 0, PtrToUlong(hwndDlg
), 0, MIXER_OBJECTF_MIXER
| CALLBACK_WINDOW
) != MMSYSERR_NOERROR
)
39 MessageBox(hwndDlg
, _T("Cannot open mixer"), NULL
, MB_OK
);
43 /* Retrieve the mixer information */
44 mxln
.cbStruct
= sizeof(MIXERLINE
);
45 mxln
.dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
47 if (mixerGetLineInfo((HMIXEROBJ
)pPageData
->hMixer
, &mxln
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINEINFOF_COMPONENTTYPE
) != MMSYSERR_NOERROR
)
50 pPageData
->volumeChannels
= mxln
.cChannels
;
52 /* Retrieve the line information */
53 mxlctrl
.cbStruct
= sizeof(MIXERLINECONTROLS
);
54 mxlctrl
.dwLineID
= mxln
.dwLineID
;
55 mxlctrl
.dwControlType
= MIXERCONTROL_CONTROLTYPE_VOLUME
;
56 mxlctrl
.cControls
= 1;
57 mxlctrl
.cbmxctrl
= sizeof(MIXERCONTROL
);
58 mxlctrl
.pamxctrl
= &mxc
;
60 if (mixerGetLineControls((HMIXEROBJ
)pPageData
->hMixer
, &mxlctrl
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINECONTROLSF_ONEBYTYPE
) != MMSYSERR_NOERROR
)
63 pPageData
->volumeControlID
= mxc
.dwControlID
;
64 pPageData
->volumeMinimum
= mxc
.Bounds
.dwMinimum
;
65 pPageData
->volumeMaximum
= mxc
.Bounds
.dwMaximum
;
66 pPageData
->volumeStep
= (pPageData
->volumeMaximum
- pPageData
->volumeMinimum
) / (VOLUME_MAX
- VOLUME_MIN
);
68 /* Allocate a buffer for all channel volume values */
69 pPageData
->volumeValues
= HeapAlloc(GetProcessHeap(),
71 mxln
.cChannels
* sizeof(MIXERCONTROLDETAILS_UNSIGNED
));
72 if (pPageData
->volumeValues
== NULL
)
75 /* Retrieve the channel volume values */
76 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
77 mxcd
.dwControlID
= mxc
.dwControlID
;
78 mxcd
.cChannels
= mxln
.cChannels
;
79 mxcd
.cMultipleItems
= 0;
80 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
81 mxcd
.paDetails
= pPageData
->volumeValues
;
83 if (mixerGetControlDetails((HMIXEROBJ
)pPageData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
86 /* Initialize the channels */
87 for (i
= 0; i
< min(mxln
.cChannels
, 5); i
++)
91 /* Set the channel name */
92 LoadString(hApplet
, IDS_SPEAKER_LEFT
+ i
, szBuffer
, _countof(szBuffer
));
93 SetWindowText(GetDlgItem(hwndDlg
, 9472 + j
), szBuffer
);
95 /* Initialize the channel trackbar */
96 SendDlgItemMessage(hwndDlg
, 9475 + j
, TBM_SETRANGE
, (WPARAM
)TRUE
, (LPARAM
)MAKELONG(VOLUME_MIN
, VOLUME_MAX
));
97 SendDlgItemMessage(hwndDlg
, 9475 + j
, TBM_SETTICFREQ
, VOLUME_TICFREQ
, 0);
98 SendDlgItemMessage(hwndDlg
, 9475 + j
, TBM_SETPAGESIZE
, 0, VOLUME_PAGESIZE
);
99 SendDlgItemMessage(hwndDlg
, 9475 + j
, TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)(pPageData
->volumeValues
[i
].dwValue
- pPageData
->volumeMinimum
) / pPageData
->volumeStep
);
102 /* Hide the unused controls */
103 for (i
= mxln
.cChannels
; i
< 8; i
++)
106 ShowWindow(GetDlgItem(hwndDlg
, 9472 + j
), SW_HIDE
);
107 ShowWindow(GetDlgItem(hwndDlg
, 9473 + j
), SW_HIDE
);
108 ShowWindow(GetDlgItem(hwndDlg
, 9474 + j
), SW_HIDE
);
109 ShowWindow(GetDlgItem(hwndDlg
, 9475 + j
), SW_HIDE
);
118 OnMixerControlChange(
119 PPAGE_DATA pPageData
,
122 MIXERCONTROLDETAILS mxcd
;
125 /* Retrieve the channel volume values */
126 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
127 mxcd
.dwControlID
= pPageData
->volumeControlID
;
128 mxcd
.cChannels
= pPageData
->volumeChannels
;
129 mxcd
.cMultipleItems
= 0;
130 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
131 mxcd
.paDetails
= pPageData
->volumeValues
;
133 if (mixerGetControlDetails((HMIXEROBJ
)pPageData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
136 for (i
= 0; i
< pPageData
->volumeChannels
; i
++)
140 SendDlgItemMessage(hwndDlg
, 9475 + j
, TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)(pPageData
->volumeValues
[i
].dwValue
- pPageData
->volumeMinimum
) / pPageData
->volumeStep
);
148 PPAGE_DATA pPageData
,
153 MIXERCONTROLDETAILS mxcd
;
154 DWORD dwValue
, dwPosition
;
157 id
= (INT
)GetWindowLongPtr((HWND
)lParam
, GWLP_ID
);
158 if (id
< 9475 && id
> 9503)
161 if ((id
- 9475) % 4 != 0)
164 dwPosition
= (DWORD
)SendDlgItemMessage(hwndDlg
, id
, TBM_GETPOS
, 0, 0);
166 if (dwPosition
== VOLUME_MIN
)
167 dwValue
= pPageData
->volumeMinimum
;
168 else if (dwPosition
== VOLUME_MAX
)
169 dwValue
= pPageData
->volumeMaximum
;
171 dwValue
= (dwPosition
* pPageData
->volumeStep
) + pPageData
->volumeMinimum
;
173 if (pPageData
->volumeSync
)
175 for (i
= 0; i
< pPageData
->volumeChannels
; i
++)
179 SendDlgItemMessage(hwndDlg
, j
, TBM_SETPOS
, (WPARAM
)TRUE
, dwPosition
);
181 pPageData
->volumeValues
[i
].dwValue
= dwValue
;
186 idx
= (id
- 9475) / 4;
187 pPageData
->volumeValues
[idx
].dwValue
= dwValue
;
190 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
191 mxcd
.dwControlID
= pPageData
->volumeControlID
;
192 mxcd
.cChannels
= pPageData
->volumeChannels
;
193 mxcd
.cMultipleItems
= 0;
194 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
195 mxcd
.paDetails
= pPageData
->volumeValues
;
197 if (mixerSetControlDetails((HMIXEROBJ
)pPageData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
205 PPAGE_DATA pPageData
,
208 MIXERCONTROLDETAILS mxcd
;
211 dwValue
= ((VOLUME_MAX
- VOLUME_MIN
) / 2 * pPageData
->volumeStep
) + pPageData
->volumeMinimum
;
213 for (i
= 0; i
< pPageData
->volumeChannels
; i
++)
214 pPageData
->volumeValues
[i
].dwValue
= dwValue
;
216 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
217 mxcd
.dwControlID
= pPageData
->volumeControlID
;
218 mxcd
.cChannels
= pPageData
->volumeChannels
;
219 mxcd
.cMultipleItems
= 0;
220 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
221 mxcd
.paDetails
= pPageData
->volumeValues
;
223 if (mixerSetControlDetails((HMIXEROBJ
)pPageData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
230 SpeakerVolumeDlgProc(
236 PPAGE_DATA pPageData
;
238 UNREFERENCED_PARAMETER(wParam
);
240 pPageData
= (PPAGE_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
245 pPageData
= (PPAGE_DATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PAGE_DATA
));
246 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pPageData
);
250 OnInitDialog(pPageData
, hwndDlg
);
257 if (pPageData
->volumeValues
)
258 HeapFree(GetProcessHeap(), 0, pPageData
->volumeValues
);
260 if (pPageData
->hMixer
)
261 mixerClose(pPageData
->hMixer
);
263 HeapFree(GetProcessHeap(), 0, pPageData
);
265 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)NULL
);
272 OnHScroll(pPageData
, hwndDlg
, wParam
, lParam
);
273 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
278 switch (LOWORD(wParam
))
281 if (HIWORD(wParam
) == BN_CLICKED
)
282 pPageData
->volumeSync
= (SendDlgItemMessage(hwndDlg
, 9504, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
286 OnSetDefaults(pPageData
, hwndDlg
);
287 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
295 case MM_MIXM_CONTROL_CHANGE
:
297 OnMixerControlChange(pPageData
, hwndDlg
);
309 PROPSHEETPAGE psp
[1];
313 LoadString(hApplet
, IDS_SPEAKER_VOLUME
, Caption
, _countof(Caption
));
315 ZeroMemory(&psh
, sizeof(PROPSHEETHEADER
));
316 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
317 psh
.dwFlags
= PSH_PROPSHEETPAGE
;
318 psh
.hwndParent
= hwndDlg
;
319 psh
.hInstance
= hApplet
;
320 psh
.pszCaption
= Caption
;
321 psh
.nPages
= sizeof(psp
) / sizeof(PROPSHEETPAGE
);
325 InitPropSheetPage(&psp
[0], IDD_MULTICHANNEL
, SpeakerVolumeDlgProc
);
326 psp
[0].dwFlags
|= PSP_USETITLE
;
327 psp
[0].pszTitle
= Caption
;
329 return (LONG
)(PropertySheet(&psh
) != -1);