1 /* $Id: main.c 12852 2005-01-06 13:58:04Z mf $
3 * PROJECT: ReactOS Multimedia Control Panel
4 * FILE: lib/cpl/mmsys/mmsys.c
5 * PURPOSE: ReactOS Multimedia Control Panel
6 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
7 * Johannes Anderwald <janderwald@reactos.com>
8 * Dmitry Chapyshev <dmitry@reactos.org>
13 #define VOLUME_DIVIDER 0xFFF
15 typedef struct _IMGINFO
23 typedef struct _GLOBAL_DATA
32 DWORD volumeControlID
;
37 } GLOBAL_DATA
, *PGLOBAL_DATA
;
41 InitImageInfo(PIMGINFO ImgInfo
)
45 ZeroMemory(ImgInfo
, sizeof(*ImgInfo
));
47 ImgInfo
->hBitmap
= LoadImage(hApplet
,
48 MAKEINTRESOURCE(IDB_SPEAKIMG
),
54 if (ImgInfo
->hBitmap
!= NULL
)
56 GetObject(ImgInfo
->hBitmap
, sizeof(BITMAP
), &bitmap
);
58 ImgInfo
->cxSource
= bitmap
.bmWidth
;
59 ImgInfo
->cySource
= bitmap
.bmHeight
;
64 GetMuteControl(PGLOBAL_DATA pGlobalData
)
68 MIXERLINECONTROLS mxlctrl
;
70 if (pGlobalData
->hMixer
== NULL
)
73 mxln
.cbStruct
= sizeof(MIXERLINE
);
74 mxln
.dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
76 if (mixerGetLineInfo((HMIXEROBJ
)pGlobalData
->hMixer
, &mxln
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINEINFOF_COMPONENTTYPE
)
77 != MMSYSERR_NOERROR
) return;
79 mxlctrl
.cbStruct
= sizeof(MIXERLINECONTROLS
);
80 mxlctrl
.dwLineID
= mxln
.dwLineID
;
81 mxlctrl
.dwControlType
= MIXERCONTROL_CONTROLTYPE_MUTE
;
82 mxlctrl
.cControls
= 1;
83 mxlctrl
.cbmxctrl
= sizeof(MIXERCONTROL
);
84 mxlctrl
.pamxctrl
= &mxc
;
86 if (mixerGetLineControls((HMIXEROBJ
)pGlobalData
->hMixer
, &mxlctrl
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINECONTROLSF_ONEBYTYPE
)
87 != MMSYSERR_NOERROR
) return;
89 pGlobalData
->muteControlID
= mxc
.dwControlID
;
93 GetMuteState(PGLOBAL_DATA pGlobalData
)
95 MIXERCONTROLDETAILS_BOOLEAN mxcdMute
;
96 MIXERCONTROLDETAILS mxcd
;
98 if (pGlobalData
->hMixer
== NULL
)
101 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
102 mxcd
.dwControlID
= pGlobalData
->muteControlID
;
104 mxcd
.cMultipleItems
= 0;
105 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_BOOLEAN
);
106 mxcd
.paDetails
= &mxcdMute
;
108 if (mixerGetControlDetails((HMIXEROBJ
)pGlobalData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
)
112 pGlobalData
->muteVal
= mxcdMute
.fValue
;
116 SwitchMuteState(PGLOBAL_DATA pGlobalData
)
118 MIXERCONTROLDETAILS_BOOLEAN mxcdMute
;
119 MIXERCONTROLDETAILS mxcd
;
121 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
122 mxcd
.dwControlID
= pGlobalData
->muteControlID
;
124 mxcd
.cMultipleItems
= 0;
125 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_BOOLEAN
);
126 mxcd
.paDetails
= &mxcdMute
;
128 mxcdMute
.fValue
= !pGlobalData
->muteVal
;
129 if (mixerSetControlDetails((HMIXEROBJ
)pGlobalData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
)
133 pGlobalData
->muteVal
= mxcdMute
.fValue
;
137 GetVolumeControl(PGLOBAL_DATA pGlobalData
)
141 MIXERLINECONTROLS mxlc
;
143 if (pGlobalData
->hMixer
== NULL
)
146 mxln
.cbStruct
= sizeof(MIXERLINE
);
147 mxln
.dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
148 if (mixerGetLineInfo((HMIXEROBJ
)pGlobalData
->hMixer
, &mxln
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINEINFOF_COMPONENTTYPE
)
152 mxlc
.cbStruct
= sizeof(MIXERLINECONTROLS
);
153 mxlc
.dwLineID
= mxln
.dwLineID
;
154 mxlc
.dwControlType
= MIXERCONTROL_CONTROLTYPE_VOLUME
;
156 mxlc
.cbmxctrl
= sizeof(MIXERCONTROL
);
157 mxlc
.pamxctrl
= &mxc
;
158 if (mixerGetLineControls((HMIXEROBJ
)pGlobalData
->hMixer
, &mxlc
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINECONTROLSF_ONEBYTYPE
)
162 pGlobalData
->volumeMinimum
= mxc
.Bounds
.dwMinimum
;
163 pGlobalData
->volumeMaximum
= mxc
.Bounds
.dwMaximum
;
164 pGlobalData
->volumeControlID
= mxc
.dwControlID
;
168 GetVolumeValue(PGLOBAL_DATA pGlobalData
)
170 MIXERCONTROLDETAILS_UNSIGNED mxcdVolume
;
171 MIXERCONTROLDETAILS mxcd
;
173 if (pGlobalData
->hMixer
== NULL
)
176 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
177 mxcd
.dwControlID
= pGlobalData
->volumeControlID
;
179 mxcd
.cMultipleItems
= 0;
180 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
181 mxcd
.paDetails
= &mxcdVolume
;
183 if (mixerGetControlDetails((HMIXEROBJ
)pGlobalData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
)
187 pGlobalData
->volumeValue
= mxcdVolume
.dwValue
;
191 SetVolumeValue(PGLOBAL_DATA pGlobalData
){
192 MIXERCONTROLDETAILS_UNSIGNED mxcdVolume
;
193 MIXERCONTROLDETAILS mxcd
;
195 if (pGlobalData
->hMixer
== NULL
)
198 mxcdVolume
.dwValue
= pGlobalData
->volumeValue
;
199 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
200 mxcd
.dwControlID
= pGlobalData
->volumeControlID
;
202 mxcd
.cMultipleItems
= 0;
203 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
204 mxcd
.paDetails
= &mxcdVolume
;
206 if (mixerSetControlDetails((HMIXEROBJ
)pGlobalData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
)
210 pGlobalData
->volumeValue
= mxcdVolume
.dwValue
;
215 InitVolumeControls(HWND hwndDlg
, PGLOBAL_DATA pGlobalData
)
220 NumMixers
= mixerGetNumDevs();
223 EnableWindow(GetDlgItem(hwndDlg
, IDC_VOLUME_TRACKBAR
), FALSE
);
224 EnableWindow(GetDlgItem(hwndDlg
, IDC_MUTE_CHECKBOX
), FALSE
);
225 EnableWindow(GetDlgItem(hwndDlg
, IDC_ICON_IN_TASKBAR
), FALSE
);
226 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADVANCED_BTN
), FALSE
);
227 EnableWindow(GetDlgItem(hwndDlg
, IDC_SPEAKER_SET_BTN
), FALSE
);
228 EnableWindow(GetDlgItem(hwndDlg
, IDC_SPEAKER_VOL_BTN
), FALSE
);
229 EnableWindow(GetDlgItem(hwndDlg
, IDC_ADVANCED2_BTN
), FALSE
);
230 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconMuted
);
234 if (mixerOpen(&pGlobalData
->hMixer
, 0, PtrToUlong(hwndDlg
), 0, MIXER_OBJECTF_MIXER
| CALLBACK_WINDOW
) != MMSYSERR_NOERROR
)
236 MessageBox(hwndDlg
, _T("Cannot open mixer"), NULL
, MB_OK
);
240 ZeroMemory(&mxc
, sizeof(MIXERCAPS
));
241 if (mixerGetDevCaps(PtrToUint(pGlobalData
->hMixer
), &mxc
, sizeof(MIXERCAPS
)) != MMSYSERR_NOERROR
)
243 MessageBox(hwndDlg
, _T("mixerGetDevCaps failed"), NULL
, MB_OK
);
247 GetMuteControl(pGlobalData
);
248 GetMuteState(pGlobalData
);
249 if (pGlobalData
->muteVal
)
251 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, (LPARAM
)0);
252 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconMuted
);
256 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_UNCHECKED
, (LPARAM
)0);
257 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconUnMuted
);
260 GetVolumeControl(pGlobalData
);
261 GetVolumeValue(pGlobalData
);
263 SendDlgItemMessage(hwndDlg
, IDC_DEVICE_NAME
, WM_SETTEXT
, 0, (LPARAM
)mxc
.szPname
);
264 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETRANGE
, (WPARAM
)TRUE
,
265 (LPARAM
)MAKELONG(pGlobalData
->volumeMinimum
, pGlobalData
->volumeMaximum
/VOLUME_DIVIDER
));
266 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETPAGESIZE
, (WPARAM
)FALSE
, (LPARAM
)1);
267 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETSEL
, (WPARAM
)FALSE
,
268 (LPARAM
)MAKELONG(pGlobalData
->volumeMinimum
, pGlobalData
->volumeValue
/VOLUME_DIVIDER
));
269 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)pGlobalData
->volumeValue
/VOLUME_DIVIDER
);
273 LaunchSoundControl(HWND hwndDlg
)
275 if ((INT_PTR
)ShellExecuteW(NULL
, L
"open", L
"sndvol32.exe", NULL
, NULL
, SW_SHOWNORMAL
) > 32)
277 MessageBox(hwndDlg
, _T("Cannot run sndvol32.exe"), NULL
, MB_OK
);
280 /* Volume property page dialog callback */
281 //static INT_PTR CALLBACK
283 VolumeDlgProc(HWND hwndDlg
,
288 static IMGINFO ImgInfo
;
289 PGLOBAL_DATA pGlobalData
;
290 UNREFERENCED_PARAMETER(lParam
);
291 UNREFERENCED_PARAMETER(wParam
);
293 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
299 case MM_MIXM_LINE_CHANGE
:
301 GetMuteState(pGlobalData
);
302 if (pGlobalData
->muteVal
)
304 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, (LPARAM
)0);
305 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconMuted
);
309 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_UNCHECKED
, (LPARAM
)0);
310 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconUnMuted
);
314 case MM_MIXM_CONTROL_CHANGE
:
316 GetVolumeValue(pGlobalData
);
317 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETSEL
, (WPARAM
)FALSE
, (LPARAM
)MAKELONG(pGlobalData
->volumeMinimum
, pGlobalData
->volumeValue
/VOLUME_DIVIDER
));
318 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)pGlobalData
->volumeValue
/VOLUME_DIVIDER
);
323 pGlobalData
= (GLOBAL_DATA
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLOBAL_DATA
));
324 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
326 pGlobalData
->hIconUnMuted
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_CPLICON
), IMAGE_ICON
, 32, 32, LR_DEFAULTCOLOR
);
327 pGlobalData
->hIconMuted
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_MUTED_ICON
), IMAGE_ICON
, 32, 32, LR_DEFAULTCOLOR
);
329 InitImageInfo(&ImgInfo
);
330 InitVolumeControls(hwndDlg
, pGlobalData
);
336 LPDRAWITEMSTRUCT lpDrawItem
;
337 lpDrawItem
= (LPDRAWITEMSTRUCT
) lParam
;
338 if(lpDrawItem
->CtlID
== IDC_SPEAKIMG
)
343 /* position image in centre of dialog */
344 left
= (lpDrawItem
->rcItem
.right
- ImgInfo
.cxSource
) / 2;
346 hdcMem
= CreateCompatibleDC(lpDrawItem
->hDC
);
349 SelectObject(hdcMem
, ImgInfo
.hBitmap
);
350 BitBlt(lpDrawItem
->hDC
,
352 lpDrawItem
->rcItem
.top
,
353 lpDrawItem
->rcItem
.right
- lpDrawItem
->rcItem
.left
,
354 lpDrawItem
->rcItem
.bottom
- lpDrawItem
->rcItem
.top
,
367 switch (LOWORD(wParam
))
369 case IDC_MUTE_CHECKBOX
:
370 SwitchMuteState(pGlobalData
);
371 if (pGlobalData
->muteVal
)
373 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, (LPARAM
)0);
374 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconMuted
);
378 SendDlgItemMessage(hwndDlg
, IDC_MUTE_CHECKBOX
, BM_SETCHECK
, (WPARAM
)BST_UNCHECKED
, (LPARAM
)0);
379 SendDlgItemMessage(hwndDlg
, IDC_MUTE_ICON
, STM_SETIMAGE
, IMAGE_ICON
, (LPARAM
)pGlobalData
->hIconUnMuted
);
382 case IDC_ADVANCED_BTN
:
383 LaunchSoundControl(hwndDlg
);
391 HWND hVolumeTrackbar
= GetDlgItem(hwndDlg
, IDC_VOLUME_TRACKBAR
);
392 if (hVolumeTrackbar
== (HWND
)lParam
)
394 pGlobalData
->volumeValue
= (DWORD
)SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_GETPOS
, 0, 0)*VOLUME_DIVIDER
;
395 SetVolumeValue(pGlobalData
);
396 SendDlgItemMessage(hwndDlg
, IDC_VOLUME_TRACKBAR
, TBM_SETSEL
, (WPARAM
)TRUE
,
397 (LPARAM
)MAKELONG(pGlobalData
->volumeMinimum
, pGlobalData
->volumeValue
/VOLUME_DIVIDER
));
403 mixerClose(pGlobalData
->hMixer
);
404 DestroyIcon(pGlobalData
->hIconMuted
);
405 DestroyIcon(pGlobalData
->hIconUnMuted
);
406 HeapFree(GetProcessHeap(), 0, pGlobalData
);