VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/VBoxMMNotificationClient.cpp@ 86075

Last change on this file since 86075 was 84408, checked in by vboxsync, 5 years ago

VBoxMMNotificationClient.cpp: Use newly added wrapper for the problematic header (endpointvolume.h). bugref:8489

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.7 KB
Line 
1/* $Id: VBoxMMNotificationClient.cpp 84408 2020-05-20 14:29:30Z vboxsync $ */
2/** @file
3 * VBoxMMNotificationClient.cpp - Implementation of the IMMNotificationClient interface
4 * to detect audio endpoint changes.
5 */
6
7/*
8 * Copyright (C) 2017-2020 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxMMNotificationClient.h"
20
21#include <iprt/win/windows.h>
22#include <mmdeviceapi.h>
23#include <iprt/win/endpointvolume.h>
24
25#ifdef LOG_GROUP /** @todo r=bird: wtf? Put it before all other includes like you're supposed to. */
26# undef LOG_GROUP
27#endif
28#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
29#include <VBox/log.h>
30
31VBoxMMNotificationClient::VBoxMMNotificationClient(void)
32 : m_fRegisteredClient(false)
33 , m_cRef(1)
34{
35}
36
37VBoxMMNotificationClient::~VBoxMMNotificationClient(void)
38{
39}
40
41/**
42 * Registers the mulitmedia notification client implementation.
43 */
44HRESULT VBoxMMNotificationClient::Register(void)
45{
46 HRESULT hr = m_pEnum->RegisterEndpointNotificationCallback(this);
47 if (SUCCEEDED(hr))
48 {
49 m_fRegisteredClient = true;
50
51 hr = AttachToDefaultEndpoint();
52 }
53
54 return hr;
55}
56
57/**
58 * Unregisters the mulitmedia notification client implementation.
59 */
60void VBoxMMNotificationClient::Unregister(void)
61{
62 DetachFromEndpoint();
63
64 if (m_fRegisteredClient)
65 {
66 m_pEnum->UnregisterEndpointNotificationCallback(this);
67
68 m_fRegisteredClient = false;
69 }
70}
71
72/**
73 * Initializes the mulitmedia notification client implementation.
74 *
75 * @return HRESULT
76 */
77HRESULT VBoxMMNotificationClient::Initialize(void)
78{
79 HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), 0, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
80 (void **)&m_pEnum);
81
82 LogFunc(("Returning %Rhrc\n", hr));
83 return hr;
84}
85
86/**
87 * Registration callback implementation for storing our (required) contexts.
88 *
89 * @return IPRT status code.
90 * @param pDrvIns Driver instance to register the notification client to.
91 * @param pfnCallback Audio callback to call by the notification client in case of new events.
92 */
93int VBoxMMNotificationClient::RegisterCallback(PPDMDRVINS pDrvIns, PFNPDMHOSTAUDIOCALLBACK pfnCallback)
94{
95 this->m_pDrvIns = pDrvIns;
96 this->m_pfnCallback = pfnCallback;
97
98 return VINF_SUCCESS;
99}
100
101/**
102 * Unregistration callback implementation for cleaning up our mess when we're done handling
103 * with notifications.
104 */
105void VBoxMMNotificationClient::UnregisterCallback(void)
106{
107 this->m_pDrvIns = NULL;
108 this->m_pfnCallback = NULL;
109}
110
111/**
112 * Stub being called when attaching to the default audio endpoint.
113 * Does nothing at the moment.
114 */
115HRESULT VBoxMMNotificationClient::AttachToDefaultEndpoint(void)
116{
117 return S_OK;
118}
119
120/**
121 * Stub being called when detaching from the default audio endpoint.
122 * Does nothing at the moment.
123 */
124void VBoxMMNotificationClient::DetachFromEndpoint(void)
125{
126
127}
128
129/**
130 * Helper function for invoking the audio connector callback (if any).
131 */
132void VBoxMMNotificationClient::doCallback(void)
133{
134#ifdef VBOX_WITH_AUDIO_CALLBACKS
135 AssertPtr(this->m_pDrvIns);
136 AssertPtr(this->m_pfnCallback);
137
138 if (this->m_pfnCallback)
139 /* Ignore rc */ this->m_pfnCallback(this->m_pDrvIns, PDMAUDIOBACKENDCBTYPE_DEVICES_CHANGED, NULL, 0);
140#endif
141}
142
143/**
144 * Handler implementation which is called when an audio device state
145 * has been changed.
146 *
147 * @return HRESULT
148 * @param pwstrDeviceId Device ID the state is announced for.
149 * @param dwNewState New state the device is now in.
150 */
151STDMETHODIMP VBoxMMNotificationClient::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState)
152{
153 char *pszState = "unknown";
154
155 switch (dwNewState)
156 {
157 case DEVICE_STATE_ACTIVE:
158 pszState = "active";
159 break;
160 case DEVICE_STATE_DISABLED:
161 pszState = "disabled";
162 break;
163 case DEVICE_STATE_NOTPRESENT:
164 pszState = "not present";
165 break;
166 case DEVICE_STATE_UNPLUGGED:
167 pszState = "unplugged";
168 break;
169 default:
170 break;
171 }
172
173 LogRel(("Audio: Device '%ls' has changed state to '%s'\n", pwstrDeviceId, pszState));
174
175 doCallback();
176
177 return S_OK;
178}
179
180/**
181 * Handler implementation which is called when a new audio device has been added.
182 *
183 * @return HRESULT
184 * @param pwstrDeviceId Device ID which has been added.
185 */
186STDMETHODIMP VBoxMMNotificationClient::OnDeviceAdded(LPCWSTR pwstrDeviceId)
187{
188 LogRel(("Audio: Device '%ls' has been added\n", pwstrDeviceId));
189
190 return S_OK;
191}
192
193/**
194 * Handler implementation which is called when an audio device has been removed.
195 *
196 * @return HRESULT
197 * @param pwstrDeviceId Device ID which has been removed.
198 */
199STDMETHODIMP VBoxMMNotificationClient::OnDeviceRemoved(LPCWSTR pwstrDeviceId)
200{
201 LogRel(("Audio: Device '%ls' has been removed\n", pwstrDeviceId));
202
203 return S_OK;
204}
205
206/**
207 * Handler implementation which is called when the device audio device has been
208 * changed.
209 *
210 * @return HRESULT
211 * @param eFlow Flow direction of the new default device.
212 * @param eRole Role of the new default device.
213 * @param pwstrDefaultDeviceId ID of the new default device.
214 */
215STDMETHODIMP VBoxMMNotificationClient::OnDefaultDeviceChanged(EDataFlow eFlow, ERole eRole, LPCWSTR pwstrDefaultDeviceId)
216{
217 RT_NOREF(eRole);
218
219 char *pszRole = "unknown";
220
221 if (eFlow == eRender)
222 pszRole = "output";
223 else if (eFlow == eCapture)
224 pszRole = "input";
225
226 LogRel(("Audio: Default %s device has been changed to '%ls'\n", pszRole, pwstrDefaultDeviceId));
227
228 doCallback();
229
230 return S_OK;
231}
232
233STDMETHODIMP VBoxMMNotificationClient::QueryInterface(REFIID interfaceID, void **ppvInterface)
234{
235 const IID MY_IID_IMMNotificationClient = __uuidof(IMMNotificationClient);
236
237 if ( IsEqualIID(interfaceID, IID_IUnknown)
238 || IsEqualIID(interfaceID, MY_IID_IMMNotificationClient))
239 {
240 *ppvInterface = static_cast<IMMNotificationClient*>(this);
241 AddRef();
242 return S_OK;
243 }
244
245 *ppvInterface = NULL;
246 return E_NOINTERFACE;
247}
248
249STDMETHODIMP_(ULONG) VBoxMMNotificationClient::AddRef(void)
250{
251 return InterlockedIncrement(&m_cRef);
252}
253
254STDMETHODIMP_(ULONG) VBoxMMNotificationClient::Release(void)
255{
256 long lRef = InterlockedDecrement(&m_cRef);
257 if (lRef == 0)
258 delete this;
259
260 return lRef;
261}
262
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette