2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll\win32\stobject\volume.cpp
5 * PURPOSE: Volume notification icon handler
6 * PROGRAMMERS: David Quintana <gigaherz@gmail.com>
14 WINE_DEFAULT_DEBUG_CHANNEL(stobject
);
22 DWORD g_muteControlID
;
24 UINT g_mmDeviceChange
;
26 BOOL g_IsMute
= FALSE
;
28 static HRESULT __stdcall
Volume_FindMixerControl(CSysTray
* pSysTray
)
35 TRACE("Volume_FindDefaultMixerID\n");
37 result
= waveOutMessage((HWAVEOUT
) WAVE_MAPPER
, DRVM_MAPPER_PREFERRED_GET
, (DWORD_PTR
) &waveOutId
, (DWORD_PTR
) ¶m2
);
41 if (waveOutId
== (DWORD
)-1)
43 TRACE("WARNING: waveOut has no default device, trying with first available device...\n", waveOutId
);
49 TRACE("waveOut default device is %d\n", waveOutId
);
51 result
= mixerGetID((HMIXEROBJ
) waveOutId
, &mixerId
, MIXER_OBJECTF_WAVEOUT
);
55 TRACE("mixerId for waveOut default device is %d\n", mixerId
);
63 MIXERCONTROL mixerControl
;
64 MIXERLINECONTROLS mixerLineControls
;
69 if (mixerGetDevCapsW(g_mixerId
, &mixerCaps
, sizeof(mixerCaps
)))
72 if (mixerCaps
.cDestinations
== 0)
75 TRACE("mixerCaps.cDestinations %d\n", mixerCaps
.cDestinations
);
78 for (idx
= 0; idx
< mixerCaps
.cDestinations
; idx
++)
80 mixerLine
.cbStruct
= sizeof(mixerLine
);
81 mixerLine
.dwDestination
= idx
;
82 if (!mixerGetLineInfoW((HMIXEROBJ
) g_mixerId
, &mixerLine
, 0))
84 if (mixerLine
.dwComponentType
>= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
&&
85 mixerLine
.dwComponentType
<= MIXERLINE_COMPONENTTYPE_DST_HEADPHONES
)
87 TRACE("Destination %d was not speakers or headphones.\n");
91 if (idx
>= mixerCaps
.cDestinations
)
94 TRACE("Valid destination %d found.\n");
96 g_mixerLineID
= mixerLine
.dwLineID
;
98 mixerLineControls
.cbStruct
= sizeof(mixerLineControls
);
99 mixerLineControls
.dwLineID
= mixerLine
.dwLineID
;
100 mixerLineControls
.cControls
= 1;
101 mixerLineControls
.dwControlType
= MIXERCONTROL_CONTROLTYPE_MUTE
;
102 mixerLineControls
.pamxctrl
= &mixerControl
;
103 mixerLineControls
.cbmxctrl
= sizeof(mixerControl
);
105 if (mixerGetLineControlsW((HMIXEROBJ
) g_mixerId
, &mixerLineControls
, MIXER_GETLINECONTROLSF_ONEBYTYPE
))
108 TRACE("Found control id %d for mute: %d\n", mixerControl
.dwControlID
);
110 g_muteControlID
= mixerControl
.dwControlID
;
115 HRESULT
Volume_IsMute()
118 MIXERCONTROLDETAILS mixerControlDetails
;
120 if (g_mixerId
!= (UINT
)-1 && g_muteControlID
!= (DWORD
)-1)
122 BOOL detailsResult
= 0;
123 mixerControlDetails
.cbStruct
= sizeof(mixerControlDetails
);
124 mixerControlDetails
.hwndOwner
= 0;
125 mixerControlDetails
.dwControlID
= g_muteControlID
;
126 mixerControlDetails
.cChannels
= 1;
127 mixerControlDetails
.paDetails
= &detailsResult
;
128 mixerControlDetails
.cbDetails
= sizeof(detailsResult
);
129 if (mixerGetControlDetailsW((HMIXEROBJ
) g_mixerId
, &mixerControlDetails
, 0))
132 TRACE("Obtained mute status %d\n", detailsResult
);
134 g_IsMute
= detailsResult
!= 0;
140 HRESULT STDMETHODCALLTYPE
Volume_Init(_In_ CSysTray
* pSysTray
)
144 TRACE("Volume_Init\n");
148 hr
= Volume_FindMixerControl(pSysTray
);
152 g_mmDeviceChange
= RegisterWindowMessageW(L
"winmm_devicechange");
155 g_hIconVolume
= LoadIcon(g_hInstance
, MAKEINTRESOURCE(IDI_VOLUME
));
156 g_hIconMute
= LoadIcon(g_hInstance
, MAKEINTRESOURCE(IDI_VOLMUTE
));
164 icon
= g_hIconVolume
;
166 return pSysTray
->NotifyIcon(NIM_ADD
, ID_ICON_VOLUME
, icon
, L
"Volume Control");
169 HRESULT STDMETHODCALLTYPE
Volume_Update(_In_ CSysTray
* pSysTray
)
171 TRACE("Volume_Update\n");
179 icon
= g_hIconVolume
;
181 return pSysTray
->NotifyIcon(NIM_MODIFY
, ID_ICON_VOLUME
, icon
, L
"Placeholder");
184 HRESULT STDMETHODCALLTYPE
Volume_Shutdown(_In_ CSysTray
* pSysTray
)
186 TRACE("Volume_Shutdown\n");
188 return pSysTray
->NotifyIcon(NIM_DELETE
, ID_ICON_VOLUME
, NULL
, NULL
);
191 HRESULT
Volume_OnDeviceChange(_In_ CSysTray
* pSysTray
, WPARAM wParam
, LPARAM lParam
)
193 return Volume_FindMixerControl(pSysTray
);
196 HRESULT STDMETHODCALLTYPE
Volume_Message(_In_ CSysTray
* pSysTray
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
198 if (uMsg
== g_mmDeviceChange
)
199 return Volume_OnDeviceChange(pSysTray
, wParam
, lParam
);
201 if (uMsg
!= ID_ICON_VOLUME
)
203 TRACE("Volume_Message received for unknown ID %d, ignoring.\n");
207 TRACE("Volume_Message uMsg=%d, w=%x, l=%x\n", uMsg
, wParam
, lParam
);
209 Volume_Update(pSysTray
);
216 TRACE("TODO: display volume slider\n");
218 case WM_LBUTTONDBLCLK
:
219 // FIXME: ensure we are loading the right one
220 ShellExecute(NULL
, NULL
, L
"sndvol32.exe", NULL
, NULL
, SW_SHOWNORMAL
);
226 case WM_RBUTTONDBLCLK
: