/*
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: dll\win32\stobject\volume.cpp
+ * FILE: dll/shellext/stobject/volume.cpp
* PURPOSE: Volume notification icon handler
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/
#include "precomp.h"
-#include <mmsystem.h>
#include <mmddk.h>
-WINE_DEFAULT_DEBUG_CHANNEL(stobject);
-
HICON g_hIconVolume;
HICON g_hIconMute;
UINT g_mmDeviceChange;
-BOOL g_IsMute = FALSE;
+static BOOL g_IsMute = FALSE;
+static BOOL g_IsRunning = FALSE;
static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
{
MMRESULT result;
- UINT mixerId = 0;
+ UINT mixerId = 0;
DWORD waveOutId = 0;
- DWORD param2 = 0;
+ DWORD param2 = 0;
TRACE("Volume_FindDefaultMixerID\n");
- result = waveOutMessage((HWAVEOUT) WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &waveOutId, (DWORD_PTR) ¶m2);
+ result = waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveOutId, (DWORD_PTR)¶m2);
if (result)
return E_FAIL;
{
TRACE("waveOut default device is %d\n", waveOutId);
- result = mixerGetID((HMIXEROBJ) waveOutId, &mixerId, MIXER_OBJECTF_WAVEOUT);
+ result = mixerGetID((HMIXEROBJ)waveOutId, &mixerId, MIXER_OBJECTF_WAVEOUT);
if (result)
return E_FAIL;
{
mixerLine.cbStruct = sizeof(mixerLine);
mixerLine.dwDestination = idx;
- if (!mixerGetLineInfoW((HMIXEROBJ) g_mixerId, &mixerLine, 0))
+ if (!mixerGetLineInfoW((HMIXEROBJ)g_mixerId, &mixerLine, 0))
{
if (mixerLine.dwComponentType >= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS &&
mixerLine.dwComponentType <= MIXERLINE_COMPONENTTYPE_DST_HEADPHONES)
mixerLineControls.pamxctrl = &mixerControl;
mixerLineControls.cbmxctrl = sizeof(mixerControl);
- if (mixerGetLineControlsW((HMIXEROBJ) g_mixerId, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE))
+ if (mixerGetLineControlsW((HMIXEROBJ)g_mixerId, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE))
return E_FAIL;
TRACE("Found control id %d for mute: %d\n", mixerControl.dwControlID);
-
+
g_muteControlID = mixerControl.dwControlID;
return S_OK;
HRESULT Volume_IsMute()
{
+#if 0
MIXERCONTROLDETAILS mixerControlDetails;
if (g_mixerId != (UINT)-1 && g_muteControlID != (DWORD)-1)
g_IsMute = detailsResult != 0;
}
-
+#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray)
{
HRESULT hr;
+ WCHAR strTooltip[128];
TRACE("Volume_Init\n");
Volume_IsMute();
+ g_IsRunning = TRUE;
+
HICON icon;
if (g_IsMute)
icon = g_hIconMute;
else
icon = g_hIconVolume;
- pSysTray->NotifyIcon(NIM_ADD, ID_ICON_VOLUME, icon, L"Placeholder");
- return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_VOLUME, icon, L"Placeholder");
+ LoadStringW(g_hInstance, IDS_VOL_VOLUME, strTooltip, _countof(strTooltip));
+ return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_VOLUME, icon, strTooltip);
}
HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray)
{
+ BOOL PrevState;
+
TRACE("Volume_Update\n");
+ PrevState = g_IsMute;
Volume_IsMute();
- HICON icon;
- if (g_IsMute)
- icon = g_hIconMute;
- else
- icon = g_hIconVolume;
+ if (PrevState != g_IsMute)
+ {
+ WCHAR strTooltip[128];
+ HICON icon;
+ if (g_IsMute)
+ {
+ icon = g_hIconMute;
+ LoadStringW(g_hInstance, IDS_VOL_MUTED, strTooltip, _countof(strTooltip));
+ }
+ else
+ {
+ icon = g_hIconVolume;
+ LoadStringW(g_hInstance, IDS_VOL_VOLUME, strTooltip, _countof(strTooltip));
+ }
- return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_VOLUME, icon, L"Placeholder");
+ return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_VOLUME, icon, strTooltip);
+ }
+ else
+ {
+ return S_OK;
+ }
}
HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray)
{
TRACE("Volume_Shutdown\n");
+ g_IsRunning = FALSE;
+
return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_VOLUME, NULL, NULL);
}
return Volume_FindMixerControl(pSysTray);
}
-HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static void _RunVolume(BOOL bTray)
{
- if (uMsg == g_mmDeviceChange)
- return Volume_OnDeviceChange(pSysTray, wParam, lParam);
+ ShellExecuteW(NULL, NULL, bTray ? L"sndvol32.exe /t" : L"sndvol32.exe", NULL, NULL, SW_SHOWNORMAL);
+}
- if (uMsg != ID_ICON_VOLUME)
- return S_FALSE;
+static void _RunMMCpl()
+{
+ ShellExecuteW(NULL, NULL, L"mmsys.cpl", NULL, NULL, SW_NORMAL);
+}
+
+static void _ShowContextMenu(CSysTray * pSysTray)
+{
+ WCHAR strAdjust[128];
+ WCHAR strOpen[128];
+ LoadStringW(g_hInstance, IDS_VOL_OPEN, strOpen, _countof(strOpen));
+ LoadStringW(g_hInstance, IDS_VOL_ADJUST, strAdjust, _countof(strAdjust));
- TRACE("Volume_Message\n");
+ HMENU hPopup = CreatePopupMenu();
+ AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen);
+ AppendMenuW(hPopup, MF_STRING, IDS_VOL_ADJUST, strAdjust);
- TRACE("Calling update...\n");
- Volume_Update(pSysTray);
+ DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
+ POINT pt;
+ SetForegroundWindow(pSysTray->GetHWnd());
+ GetCursorPos(&pt);
- switch (lParam)
+ DWORD id = TrackPopupMenuEx(hPopup, flags,
+ pt.x, pt.y,
+ pSysTray->GetHWnd(), NULL);
+
+ DestroyMenu(hPopup);
+
+ switch (id)
{
- case WM_LBUTTONDOWN:
- break;
- case WM_LBUTTONUP:
- TRACE("TODO: display volume slider\n");
- break;
- case WM_LBUTTONDBLCLK:
- // FIXME: ensure we are loading the right one
- ShellExecute(NULL, NULL, L"sndvol32.exe", NULL, NULL, SW_SHOWNORMAL);
- break;
- case WM_RBUTTONDOWN:
+ case IDS_VOL_OPEN:
+ _RunVolume(FALSE);
break;
- case WM_RBUTTONUP:
- break;
- case WM_RBUTTONDBLCLK:
- break;
- case WM_MOUSEMOVE:
+ case IDS_VOL_ADJUST:
+ _RunMMCpl();
break;
}
+}
- return S_OK;
+HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
+{
+ if (uMsg == g_mmDeviceChange)
+ return Volume_OnDeviceChange(pSysTray, wParam, lParam);
+
+ switch (uMsg)
+ {
+ case WM_USER + 220:
+ TRACE("Volume_Message: WM_USER+220\n");
+ if (wParam == 4)
+ {
+ if (lParam == FALSE)
+ return Volume_Init(pSysTray);
+ else
+ return Volume_Shutdown(pSysTray);
+ }
+ return S_FALSE;
+
+ case WM_USER + 221:
+ TRACE("Volume_Message: WM_USER+221\n");
+ if (wParam == 4)
+ {
+ lResult = (LRESULT)g_IsRunning;
+ return S_OK;
+ }
+ return S_FALSE;
+
+ case WM_TIMER:
+ if (wParam == VOLUME_TIMER_ID)
+ {
+ KillTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID);
+ _RunVolume(TRUE);
+ }
+ break;
+
+ case ID_ICON_VOLUME:
+ TRACE("Volume_Message uMsg=%d, w=%x, l=%x\n", uMsg, wParam, lParam);
+
+ Volume_Update(pSysTray);
+
+ switch (lParam)
+ {
+ case WM_LBUTTONDOWN:
+ SetTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID, GetDoubleClickTime(), NULL);
+ break;
+
+ case WM_LBUTTONUP:
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ KillTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID);
+ _RunVolume(FALSE);
+ break;
+
+ case WM_RBUTTONDOWN:
+ break;
+
+ case WM_RBUTTONUP:
+ _ShowContextMenu(pSysTray);
+ break;
+
+ case WM_RBUTTONDBLCLK:
+ break;
+
+ case WM_MOUSEMOVE:
+ break;
+ }
+ return S_OK;
+
+ default:
+ TRACE("Volume_Message received for unknown ID %d, ignoring.\n");
+ return S_FALSE;
+ }
+
+ return S_FALSE;
}