77 */
88
99#include " precomp.h"
10+ #include " winuser.h"
1011
1112#include < mmddk.h>
1213
@@ -174,69 +175,93 @@ HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray)
174175 Volume_IsMute ();
175176
176177 // Unmute if volume is increased or unmuted explicitly
177- if (pSysTray->lpVolCmd )
178- {
178+ if (!pSysTray->lpVolCmd )
179+ return S_OK;
180+
181+ if (pSysTray->lpVolCmd == APPCOMMAND_VOLUME_UP || pSysTray->lpVolCmd == APPCOMMAND_VOLUME_MUTE)
179182 g_IsMute = pSysTray->lpVolCmd == APPCOMMAND_VOLUME_UP ? FALSE : !g_IsMute;
180183
181- MIXERCONTROLDETAILS_BOOLEAN mxcdMute = {0 };
182- mxcdMute.fValue = g_IsMute;
184+ MIXERCONTROLDETAILS_BOOLEAN mxcdMute{};
185+ mxcdMute.fValue = g_IsMute;
186+
187+ MIXERCONTROLDETAILS mxcd{};
188+ mxcd.cbStruct = sizeof (mxcd);
189+ mxcd.cChannels = 1 ;
190+ mxcd.hwndOwner = NULL ;
191+ mxcd.dwControlID = g_muteControlID;
192+ mxcd.paDetails = &mxcdMute;
193+ mxcd.cbDetails = sizeof (mxcdMute);
194+
195+ MMRESULT mmres = mixerSetControlDetails ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxcd, MIXER_SETCONTROLDETAILSF_VALUE);
196+
197+ if (mmres != MMSYSERR_NOERROR)
198+ {
199+ ERR (" Volume_Update failed at updating mute state: %d\n " , mmres);
200+ return E_FAIL;
201+ }
202+
203+ if (pSysTray->lpVolCmd == APPCOMMAND_VOLUME_UP || pSysTray->lpVolCmd == APPCOMMAND_VOLUME_DOWN)
204+ {
205+ MIXERLINECONTROLSW mxlc{};
206+ MIXERCONTROLW mxctrl{};
183207
184- MIXERCONTROLDETAILS mxcd = {0 };
185- mxcd.cbStruct = sizeof (mxcd);
186- mxcd.cChannels = 1 ;
187- mxcd.hwndOwner = NULL ;
188- mxcd.dwControlID = g_muteControlID;
189- mxcd.paDetails = &mxcdMute;
190- mxcd.cbDetails = sizeof (mxcdMute);
208+ mxlc.cbStruct = sizeof (mxlc);
209+ mxlc.dwLineID = g_mixerLineID;
210+ mxlc.cControls = 1 ;
211+ mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
212+ mxlc.pamxctrl = &mxctrl;
213+ mxlc.cbmxctrl = sizeof (mxctrl);
191214
192- MMRESULT mmres = mixerSetControlDetails ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxcd, MIXER_SETCONTROLDETAILSF_VALUE );
215+ mmres = mixerGetLineControlsW ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE );
193216
194- if (mmres)
217+ if (mmres != MMSYSERR_NOERROR )
195218 {
196- ERR (" Volume_Update failed at updating mute state : %d\n " , mmres);
219+ ERR (" Volume_Update failed retrieving line control : %d\n " , mmres);
197220 return E_FAIL;
198221 }
199222
200- // Update volume depending on pressed button.
201- if (pSysTray->lpVolCmd != APPCOMMAND_VOLUME_MUTE)
202- {
203- MIXERLINECONTROLSW mxlc;
204- MIXERCONTROLW mxctrl;
205-
206- mxlc.cbStruct = sizeof (mxlc);
207- mxlc.dwLineID = g_mixerLineID;
208- mxlc.cControls = 1 ;
209- mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
210- mxlc.pamxctrl = &mxctrl;
211- mxlc.cbmxctrl = sizeof (mxctrl);
212-
213- mmres = mixerGetLineControlsW ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
223+ MIXERCONTROLDETAILS_UNSIGNED mxcdVolume{};
214224
215- if (mmres)
216- {
217- ERR (" Volume_Update failed retrieving line control: %d\n " , mmres);
218- return E_FAIL;
219- }
225+ mxcd.dwControlID = mxctrl.dwControlID ;
226+ mxcd.paDetails = &mxcdVolume;
227+ mxcd.cbDetails = sizeof (mxcdVolume);
220228
221- MIXERCONTROLDETAILS_UNSIGNED mxcdVolume ;
229+ mmres = mixerGetControlDetailsW ((HMIXEROBJ) UlongToHandle (g_mixerId), &mxcd, MIXER_GETCONTROLDETAILSF_VALUE) ;
222230
223- mxcd.dwControlID = mxctrl.dwControlID ;
224- mxcd.paDetails = &mxcdVolume;
225- mxcd.cbDetails = sizeof (mxcdVolume);
231+ if (mmres != MMSYSERR_NOERROR)
232+ {
233+ ERR (" Volume_Update failed reading current volume: %d\n " , mmres);
234+ return E_FAIL;
235+ }
226236
227- mmres = mixerGetControlDetailsW ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
237+ DPRINTF (" Volume_Update: Current volume is %d, volume is expected to go %s\n " , mxcdVolume.dwValue , pSysTray->lpVolCmd == APPCOMMAND_VOLUME_UP ? " up" : " down" );
238+ DPRINTF (" Volume_Update: Control step: %u | Bounds: (%u, %u)\n " , mxctrl.Metrics .cSteps , mxctrl.Bounds .dwMinimum , mxctrl.Bounds .dwMaximum );
239+
240+ /*
241+ * In perfect conditions, there must be exactly 50 steps when changing volume.
242+ * The formula of mxctrl.Metrics.cSteps * 7, assuming cSteps == 192, gives us 48 whole steps.
243+ * In close to bounds situations we have odd results, so the volume value is explicitly set
244+ * to 65535 or 0 depending on volume change direction.
245+ */
246+ if (pSysTray->lpVolCmd == APPCOMMAND_VOLUME_UP)
247+ mxcdVolume.dwValue += mxctrl.Metrics .cSteps * 7 ;
248+ else
249+ mxcdVolume.dwValue -= mxctrl.Metrics .cSteps * 7 ;
228250
229- if (mmres)
230- {
231- ERR (" Volume_Update failed reading current volume: %d\n " , mmres);
232- return E_FAIL;
233- }
251+ mmres = mixerSetControlDetails ((HMIXEROBJ)UlongToHandle (g_mixerId), &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
234252
235- pSysTray->lpVolCmd = 0 ;
253+ if (mmres != MMSYSERR_NOERROR)
254+ {
255+ ERR (" Volume_Update failed writing current volume: %d\n " , mmres);
256+ return E_FAIL;
257+ }
258+ else
259+ {
236260 DPRINTF (" Volume_Update: Current volume is %d\n " , mxcdVolume.dwValue );
237261 }
238262 }
239263
264+ // Update system tray icon depending on new volume settings
240265 if (pSysTray->lpVolCmd == APPCOMMAND_VOLUME_MUTE || PrevState != g_IsMute)
241266 {
242267 WCHAR strTooltip[128 ];
@@ -255,10 +280,9 @@ HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray)
255280 pSysTray->lpVolCmd = 0 ;
256281 return pSysTray->NotifyIcon (NIM_MODIFY, ID_ICON_VOLUME, icon, strTooltip);
257282 }
258- else
259- {
260- return S_OK;
261- }
283+
284+ pSysTray->lpVolCmd = 0 ;
285+ return S_OK;
262286}
263287
264288HRESULT STDMETHODCALLTYPE Volume_Shutdown (_In_ CSysTray * pSysTray)
0 commit comments