[STOBJECT]
authorDavid Quintana <gigaherz@gmail.com>
Mon, 28 Jul 2014 13:24:56 +0000 (13:24 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Mon, 28 Jul 2014 13:24:56 +0000 (13:24 +0000)
* Nothing happened. No files were missing. Look elsewhere.

svn path=/branches/shell-experiments/; revision=63752

dll/win32/stobject/volume.cpp [new file with mode: 0644]

diff --git a/dll/win32/stobject/volume.cpp b/dll/win32/stobject/volume.cpp
new file mode 100644 (file)
index 0000000..133809a
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * PROJECT:     ReactOS system libraries
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        dll\win32\stobject\volume.cpp
+ * PURPOSE:     Systray shell service object
+ * PROGRAMMERS: Robert Naumann
+                David Quintana <gigaherz@gmail.com>
+ */
+
+#include "precomp.h"
+
+#include <mmsystem.h>
+#include <mmddk.h>
+
+HICON g_hIconVolume;
+HICON g_hIconMute;
+
+HMIXER g_hMixer;
+UINT   g_mixerId;
+DWORD  g_mixerLineID;
+DWORD  g_muteControlID;
+
+UINT g_mmDeviceChange;
+
+BOOL g_IsMute = FALSE;
+
+static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
+{
+    MMRESULT result;
+    UINT mixerId    = 0;
+    DWORD waveOutId = 0;
+    DWORD param2    = 0;
+
+    DbgPrint("Volume_FindDefaultMixerID\n");
+
+    result = waveOutMessage((HWAVEOUT) WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD) &waveOutId, (DWORD) &param2);
+    if (result)
+        return E_FAIL;
+
+    if (waveOutId == (DWORD)-1)
+    {
+        DbgPrint("WARNING: waveOut has no default device, trying with first available device...\n", waveOutId);
+
+        mixerId = 0;
+    }
+    else
+    {
+        DbgPrint("waveOut default device is %d\n", waveOutId);
+
+        result = mixerGetID((HMIXEROBJ) waveOutId, &mixerId, MIXER_OBJECTF_WAVEOUT);
+        if (result)
+            return E_FAIL;
+
+        DbgPrint("mixerId for waveOut default device is %d\n", mixerId);
+    }
+
+    g_mixerId = mixerId;
+    return S_OK;
+
+    MIXERCAPS mixerCaps;
+    MIXERLINE mixerLine;
+    MIXERCONTROL mixerControl;
+    MIXERLINECONTROLS mixerLineControls;
+
+    g_mixerLineID = -1;
+    g_muteControlID = -1;
+
+    if (mixerGetDevCapsW(g_mixerId, &mixerCaps, sizeof(mixerCaps)))
+        return E_FAIL;
+
+    if (mixerCaps.cDestinations == 0)
+        return S_FALSE;
+
+    DbgPrint("mixerCaps.cDestinations %d\n", mixerCaps.cDestinations);
+
+    DWORD idx;
+    for (idx = 0; idx < mixerCaps.cDestinations; idx++)
+    {
+        mixerLine.cbStruct = sizeof(mixerLine);
+        mixerLine.dwDestination = idx;
+        if (!mixerGetLineInfoW((HMIXEROBJ) g_mixerId, &mixerLine, 0))
+        {
+            if (mixerLine.dwComponentType >= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS &&
+                mixerLine.dwComponentType <= MIXERLINE_COMPONENTTYPE_DST_HEADPHONES)
+                break;
+            DbgPrint("Destination %d was not speakers or headphones.\n");
+        }
+    }
+
+    if (idx >= mixerCaps.cDestinations)
+        return E_FAIL;
+
+    DbgPrint("Valid destination %d found.\n");
+
+    g_mixerLineID = mixerLine.dwLineID;
+
+    mixerLineControls.cbStruct = sizeof(mixerLineControls);
+    mixerLineControls.dwLineID = mixerLine.dwLineID;
+    mixerLineControls.cControls = 1;
+    mixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
+    mixerLineControls.pamxctrl = &mixerControl;
+    mixerLineControls.cbmxctrl = sizeof(mixerControl);
+
+    if (mixerGetLineControlsW((HMIXEROBJ) g_mixerId, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE))
+        return E_FAIL;
+
+    DbgPrint("Found control id %d for mute: %d\n", mixerControl.dwControlID);
+    
+    g_muteControlID = mixerControl.dwControlID;
+
+    return S_OK;
+}
+
+HRESULT Volume_IsMute()
+{
+    MIXERCONTROLDETAILS mixerControlDetails;
+
+    if (g_mixerId != (UINT)-1 && g_muteControlID != (DWORD)-1)
+    {
+        BOOL detailsResult = 0;
+        mixerControlDetails.cbStruct = sizeof(mixerControlDetails);
+        mixerControlDetails.hwndOwner = 0;
+        mixerControlDetails.dwControlID = g_muteControlID;
+        mixerControlDetails.cChannels = 1;
+        mixerControlDetails.paDetails = &detailsResult;
+        mixerControlDetails.cbDetails = sizeof(detailsResult);
+        if (mixerGetControlDetailsW((HMIXEROBJ) g_mixerId, &mixerControlDetails, 0))
+            return E_FAIL;
+
+        DbgPrint("Obtained mute status %d\n", detailsResult);
+
+        g_IsMute = detailsResult != 0;
+    }
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray)
+{
+    HRESULT hr;
+
+    DbgPrint("Volume_Init\n");
+
+    if (!g_hMixer)
+    {
+        hr = Volume_FindMixerControl(pSysTray);
+        if (FAILED(hr))
+            return hr;
+
+        g_mmDeviceChange = RegisterWindowMessageW(L"winmm_devicechange");
+    }
+
+    g_hIconVolume = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_VOLUME));
+    g_hIconMute = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_VOLMUTE));
+
+    Volume_IsMute();
+
+    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");
+}
+
+HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray)
+{
+    DbgPrint("Volume_Update\n");
+
+    Volume_IsMute();
+
+    HICON icon;
+    if (g_IsMute)
+        icon = g_hIconMute;
+    else
+        icon = g_hIconVolume;
+
+    return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_VOLUME, icon, L"Placeholder");
+}
+
+HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray)
+{
+    DbgPrint("Volume_Shutdown\n");
+
+    return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_VOLUME, NULL, NULL);
+}
+
+HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM wParam, LPARAM lParam)
+{
+    return Volume_FindMixerControl(pSysTray);
+}
+
+HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    if (uMsg == g_mmDeviceChange)
+        return Volume_OnDeviceChange(pSysTray, wParam, lParam);
+
+    if (uMsg != ID_ICON_VOLUME)
+        return S_FALSE;
+
+    DbgPrint("Volume_Message\n");
+
+    DbgPrint("Calling update...\n");
+    Volume_Update(pSysTray);
+
+    switch (lParam)
+    {
+    case WM_LBUTTONDOWN:
+        break;
+    case WM_LBUTTONUP:
+        DbgPrint("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:
+        break;
+    case WM_RBUTTONUP:
+        break;
+    case WM_RBUTTONDBLCLK:
+        break;
+    case WM_MOUSEMOVE:
+        break;
+    }
+
+    return S_OK;
+}