2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Sound Volume Control
4 * FILE: base/applications/sndvol32/tray.c
5 * PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
10 typedef struct _DIALOG_DATA
13 DWORD volumeControlID
;
21 PMIXERCONTROLDETAILS_UNSIGNED volumeInitValues
;
22 PMIXERCONTROLDETAILS_UNSIGNED volumeCurrentValues
;
25 } DIALOG_DATA
, *PDIALOG_DATA
;
39 GetCursorPos(&ptCursor
);
41 GetWindowRect(hwnd
, &rcWindow
);
43 GetWindowRect(GetDesktopWindow(), &rcScreen
);
45 cx
= rcWindow
.right
- rcWindow
.left
;
46 cy
= rcWindow
.bottom
- rcWindow
.top
;
48 if (ptCursor
.y
+ cy
> rcScreen
.bottom
)
53 if (ptCursor
.x
+ cx
> rcScreen
.right
)
58 SetWindowPos(hwnd
, HWND_TOPMOST
, x
, y
, 0, 0, SWP_NOSIZE
);
65 PDIALOG_DATA pDialogData
,
70 MIXERLINECONTROLS mxlctrl
;
71 MIXERCONTROLDETAILS mxcd
;
72 MIXERCONTROLDETAILS_BOOLEAN mxcdBool
;
76 if (mixerOpen(&pDialogData
->hMixer
, 0, PtrToUlong(hwndDlg
), 0, MIXER_OBJECTF_MIXER
| CALLBACK_WINDOW
) != MMSYSERR_NOERROR
)
79 /* Retrieve the mixer information */
80 mxln
.cbStruct
= sizeof(MIXERLINE
);
81 mxln
.dwComponentType
= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
;
83 if (mixerGetLineInfo((HMIXEROBJ
)pDialogData
->hMixer
, &mxln
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINEINFOF_COMPONENTTYPE
) != MMSYSERR_NOERROR
)
86 pDialogData
->volumeChannels
= mxln
.cChannels
;
88 /* Retrieve the line information */
89 mxlctrl
.cbStruct
= sizeof(MIXERLINECONTROLS
);
90 mxlctrl
.dwLineID
= mxln
.dwLineID
;
91 mxlctrl
.dwControlType
= MIXERCONTROL_CONTROLTYPE_VOLUME
;
92 mxlctrl
.cControls
= 1;
93 mxlctrl
.cbmxctrl
= sizeof(MIXERCONTROL
);
94 mxlctrl
.pamxctrl
= &mxc
;
96 if (mixerGetLineControls((HMIXEROBJ
)pDialogData
->hMixer
, &mxlctrl
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINECONTROLSF_ONEBYTYPE
) != MMSYSERR_NOERROR
)
99 pDialogData
->volumeControlID
= mxc
.dwControlID
;
100 pDialogData
->volumeMinimum
= mxc
.Bounds
.dwMinimum
;
101 pDialogData
->volumeMaximum
= mxc
.Bounds
.dwMaximum
;
102 pDialogData
->volumeStep
= (pDialogData
->volumeMaximum
- pDialogData
->volumeMinimum
) / (VOLUME_MAX
- VOLUME_MIN
);
104 /* Allocate a buffer for all channel volume values */
105 pDialogData
->volumeInitValues
= HeapAlloc(GetProcessHeap(),
107 mxln
.cChannels
* sizeof(MIXERCONTROLDETAILS_UNSIGNED
));
108 if (pDialogData
->volumeInitValues
== NULL
)
111 pDialogData
->volumeCurrentValues
= HeapAlloc(GetProcessHeap(),
113 mxln
.cChannels
* sizeof(MIXERCONTROLDETAILS_UNSIGNED
));
114 if (pDialogData
->volumeCurrentValues
== NULL
)
117 /* Retrieve the channel volume values */
118 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
119 mxcd
.dwControlID
= mxc
.dwControlID
;
120 mxcd
.cChannels
= mxln
.cChannels
;
121 mxcd
.cMultipleItems
= 0;
122 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
123 mxcd
.paDetails
= pDialogData
->volumeInitValues
;
125 if (mixerGetControlDetails((HMIXEROBJ
)pDialogData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
128 pDialogData
->maxVolume
= 0;
129 for (i
= 0; i
< pDialogData
->volumeChannels
; i
++)
131 pDialogData
->volumeCurrentValues
[i
].dwValue
= pDialogData
->volumeInitValues
[i
].dwValue
;
133 if (pDialogData
->volumeInitValues
[i
].dwValue
> pDialogData
->maxVolume
)
134 pDialogData
->maxVolume
= pDialogData
->volumeInitValues
[i
].dwValue
;
137 /* Initialize the volume trackbar */
138 SendDlgItemMessage(hwndDlg
, IDC_LINE_SLIDER_VERT
, TBM_SETRANGE
, TRUE
, MAKELONG(VOLUME_MIN
, VOLUME_MAX
));
139 SendDlgItemMessage(hwndDlg
, IDC_LINE_SLIDER_VERT
, TBM_SETPAGESIZE
, 0, VOLUME_PAGE_SIZE
);
140 SendDlgItemMessage(hwndDlg
, IDC_LINE_SLIDER_VERT
, TBM_SETPOS
, TRUE
, VOLUME_MAX
-(pDialogData
->maxVolume
- pDialogData
->volumeMinimum
) / pDialogData
->volumeStep
);
142 /* Retrieve the mute control information */
143 mxlctrl
.cbStruct
= sizeof(MIXERLINECONTROLS
);
144 mxlctrl
.dwLineID
= mxln
.dwLineID
;
145 mxlctrl
.dwControlType
= MIXERCONTROL_CONTROLTYPE_MUTE
;
146 mxlctrl
.cControls
= 1;
147 mxlctrl
.cbmxctrl
= sizeof(MIXERCONTROL
);
148 mxlctrl
.pamxctrl
= &mxc
;
150 if (mixerGetLineControls((HMIXEROBJ
)pDialogData
->hMixer
, &mxlctrl
, MIXER_OBJECTF_HMIXER
| MIXER_GETLINECONTROLSF_ONEBYTYPE
) != MMSYSERR_NOERROR
)
153 pDialogData
->muteControlID
= mxc
.dwControlID
;
155 /* Retrieve the mute value */
156 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
157 mxcd
.dwControlID
= mxc
.dwControlID
;
159 mxcd
.cMultipleItems
= 0;
160 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_BOOLEAN
);
161 mxcd
.paDetails
= &mxcdBool
;
163 if (mixerGetControlDetails((HMIXEROBJ
)pDialogData
->hMixer
, &mxcd
, MIXER_OBJECTF_HMIXER
| MIXER_GETCONTROLDETAILSF_VALUE
) != MMSYSERR_NOERROR
)
166 /* Initialize the mute checkbox */
167 SendDlgItemMessage(hwndDlg
, IDC_LINE_SWITCH
, BM_SETCHECK
, (WPARAM
)(mxcdBool
.fValue
? BST_CHECKED
: BST_UNCHECKED
), 0);
174 PDIALOG_DATA pDialogData
,
179 MIXERCONTROLDETAILS mxcd
;
180 MIXERCONTROLDETAILS_BOOLEAN mxcdMute
;
182 if ((LOWORD(wParam
) == IDC_LINE_SWITCH
) &&
183 (HIWORD(wParam
) == BN_CLICKED
))
185 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
186 mxcd
.dwControlID
= pDialogData
->muteControlID
;
188 mxcd
.cMultipleItems
= 0;
189 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_BOOLEAN
);
190 mxcd
.paDetails
= &mxcdMute
;
192 mxcdMute
.fValue
= (SendMessage((HWND
)lParam
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
194 mixerSetControlDetails((HMIXEROBJ
)pDialogData
->hMixer
,
196 MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
);
204 PDIALOG_DATA pDialogData
,
209 MIXERCONTROLDETAILS mxcd
;
210 DWORD dwPosition
, dwVolume
, i
;
212 switch (LOWORD(wParam
))
214 case TB_THUMBPOSITION
:
218 PlaySound((LPCTSTR
)SND_ALIAS_SYSTEMDEFAULT
, NULL
, SND_ASYNC
| SND_ALIAS_ID
);
222 dwPosition
= VOLUME_MAX
- (DWORD
)SendDlgItemMessage(hwndDlg
, IDC_LINE_SLIDER_VERT
, TBM_GETPOS
, 0, 0);
224 if (dwPosition
== VOLUME_MIN
)
225 dwVolume
= pDialogData
->volumeMinimum
;
226 else if (dwPosition
== VOLUME_MAX
)
227 dwVolume
= pDialogData
->volumeMaximum
;
229 dwVolume
= (dwPosition
* pDialogData
->volumeStep
) + pDialogData
->volumeMinimum
;
231 for (i
= 0; i
< pDialogData
->volumeChannels
; i
++)
233 if (pDialogData
->volumeInitValues
[i
].dwValue
== pDialogData
->maxVolume
)
235 pDialogData
->volumeCurrentValues
[i
].dwValue
= dwVolume
;
239 pDialogData
->volumeCurrentValues
[i
].dwValue
=
240 pDialogData
->volumeInitValues
[i
].dwValue
* dwVolume
/ pDialogData
-> maxVolume
;
244 mxcd
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
245 mxcd
.dwControlID
= pDialogData
->volumeControlID
;
246 mxcd
.cChannels
= pDialogData
->volumeChannels
;
247 mxcd
.cMultipleItems
= 0;
248 mxcd
.cbDetails
= sizeof(MIXERCONTROLDETAILS_UNSIGNED
);
249 mxcd
.paDetails
= pDialogData
->volumeCurrentValues
;
251 mixerSetControlDetails((HMIXEROBJ
)pDialogData
->hMixer
,
253 MIXER_OBJECTF_HMIXER
| MIXER_SETCONTROLDETAILSF_VALUE
);
268 PDIALOG_DATA pDialogData
;
270 pDialogData
= (PDIALOG_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
275 OnTrayInitDialog(hwndDlg
, wParam
, lParam
);
277 pDialogData
= (PDIALOG_DATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DIALOG_DATA
));
278 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pDialogData
);
281 OnTrayInitMixer(pDialogData
, hwndDlg
);
286 OnCommand(pDialogData
, hwndDlg
, wParam
, lParam
);
291 OnVScroll(pDialogData
, hwndDlg
, wParam
, lParam
);
297 if (pDialogData
->volumeInitValues
)
298 HeapFree(GetProcessHeap(), 0, pDialogData
->volumeInitValues
);
300 if (pDialogData
->volumeCurrentValues
)
301 HeapFree(GetProcessHeap(), 0, pDialogData
->volumeCurrentValues
);
303 if (pDialogData
->hMixer
)
304 mixerClose(pDialogData
->hMixer
);
306 HeapFree(GetProcessHeap(), 0, pDialogData
);
308 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)NULL
);
313 if (LOWORD(wParam
) == WA_INACTIVE
)
314 EndDialog(hwndDlg
, IDOK
);