[NTDLL] Allow shimdata to override the process manifest.
[reactos.git] / dll / shellext / stobject / volume.cpp
index f3d23af..931cd2e 100644 (file)
@@ -1,18 +1,15 @@
 /*
  * 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;
 
@@ -23,18 +20,19 @@ DWORD  g_muteControlID;
 
 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) &param2);
+    result = waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&waveOutId, (DWORD_PTR)&param2);
     if (result)
         return E_FAIL;
 
@@ -48,7 +46,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
     {
         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;
 
@@ -79,7 +77,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
     {
         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)
@@ -102,11 +100,11 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
     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;
@@ -114,6 +112,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
 
 HRESULT Volume_IsMute()
 {
+#if 0
     MIXERCONTROLDETAILS mixerControlDetails;
 
     if (g_mixerId != (UINT)-1 && g_muteControlID != (DWORD)-1)
@@ -132,13 +131,14 @@ HRESULT Volume_IsMute()
 
         g_IsMute = detailsResult != 0;
     }
-
+#endif
     return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray)
 {
     HRESULT hr;
+    WCHAR strTooltip[128];
 
     TRACE("Volume_Init\n");
 
@@ -156,35 +156,56 @@ HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray)
 
     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);
 }
 
@@ -193,39 +214,122 @@ HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM wParam, LPARAM lP
     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;
 }