VirtualBox

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

Last change on this file since 80596 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.3 KB
Line 
1/* $Id: VBoxMMNotificationClient.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxMMNotificationClient.cpp - Implementation of the IMMNotificationClient interface
4 * to detect audio endpoint changes.
5 */
6
7/*
8 * Copyright (C) 2017-2019 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
23#pragma warning(push)
24#pragma warning(disable: 4201)
25#include <mmdeviceapi.h>
26#include <endpointvolume.h>
27#pragma warning(pop)
28
29#ifdef LOG_GROUP
30# undef LOG_GROUP
31#endif
32#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
33#include <VBox/log.h>
34
35VBoxMMNotificationClient::VBoxMMNotificationClient(void)
36 : m_fRegisteredClient(false)
37 , m_cRef(1)
38{
39}
40
41VBoxMMNotificationClient::~VBoxMMNotificationClient(void)
42{
43}
44
45/**
46 * Uninitializes the mulitmedia notification client implementation.
47 */
48void VBoxMMNotificationClient::Dispose(void)
49{
50 DetachFromEndpoint();
51
52 if (m_fRegisteredClient)
53 {
54 m_pEnum->UnregisterEndpointNotificationCallback(this);
55
56 m_fRegisteredClient = false;
57 }
58}
59
60/**
61 * Initializes the mulitmedia notification client implementation.
62 *
63 * @return HRESULT
64 */
65HRESULT VBoxMMNotificationClient::Initialize(void)
66{
67 HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), 0, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
68 (void **)&m_pEnum);
69 if (SUCCEEDED(hr))
70 {
71 hr = m_pEnum->RegisterEndpointNotificationCallback(this);
72 if (SUCCEEDED(hr))
73 {
74 m_fRegisteredClient = true;
75
76 hr = AttachToDefaultEndpoint();
77 }
78 }
79
80 LogFunc(("Returning %Rhrc\n", hr));
81 return hr;
82}
83
84/**
85 * Registration callback implementation for storing our (required) contexts.
86 *
87 * @return IPRT status code.
88 * @param pDrvIns Driver instance to register the notification client to.
89 * @param pfnCallback Audio callback to call by the notification client in case of new events.
90 */
91int VBoxMMNotificationClient::RegisterCallback(PPDMDRVINS pDrvIns, PFNPDMHOSTAUDIOCALLBACK pfnCallback)
92{
93 this->m_pDrvIns = pDrvIns;
94 this->m_pfnCallback = pfnCallback;
95
96 return VINF_SUCCESS;
97}
98
99/**
100 * Unregistration callback implementation for cleaning up our mess when we're done handling
101 * with notifications.
102 */
103void VBoxMMNotificationClient::UnregisterCallback(void)
104{
105 this->m_pDrvIns = NULL;
106 this->m_pfnCallback = NULL;
107}
108
109/**
110 * Stub being called when attaching to the default audio endpoint.
111 * Does nothing at the moment.
112 */
113HRESULT VBoxMMNotificationClient::AttachToDefaultEndpoint(void)
114{
115 return S_OK;
116}
117
118/**
119 * Stub being called when detaching from the default audio endpoint.
120 * Does nothing at the moment.
121 */
122void VBoxMMNotificationClient::DetachFromEndpoint(void)
123{
124
125}
126
127/**
128 * Handler implementation which is called when an audio device state
129 * has been changed.
130 *
131 * @return HRESULT
132 * @param pwstrDeviceId Device ID the state is announced for.
133 * @param dwNewState New state the device is now in.
134 */
135STDMETHODIMP VBoxMMNotificationClient::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState)
136{
137 char *pszState = "unknown";
138
139 switch (dwNewState)
140 {
141 case DEVICE_STATE_ACTIVE:
142 pszState = "active";
143 break;
144 case DEVICE_STATE_DISABLED:
145 pszState = "disabled";
146 break;
147 case DEVICE_STATE_NOTPRESENT:
148 pszState = "not present";
149 break;
150 case DEVICE_STATE_UNPLUGGED:
151 pszState = "unplugged";
152 break;
153 default:
154 break;
155 }
156
157 LogRel2(("Audio: Device '%ls' has changed state to '%s'\n", pwstrDeviceId, pszState));
158
159#ifdef VBOX_WITH_AUDIO_CALLBACKS
160 AssertPtr(this->m_pDrvIns);
161 AssertPtr(this->m_pfnCallback);
162
163 if (this->m_pfnCallback)
164 /* Ignore rc */ this->m_pfnCallback(this->m_pDrvIns, PDMAUDIOBACKENDCBTYPE_DEVICES_CHANGED, NULL, 0);
165#endif
166
167 return S_OK;
168}
169
170/**
171 * Handler implementation which is called when a new audio device has been added.
172 *
173 * @return HRESULT
174 * @param pwstrDeviceId Device ID which has been added.
175 */
176STDMETHODIMP VBoxMMNotificationClient::OnDeviceAdded(LPCWSTR pwstrDeviceId)
177{
178 RT_NOREF(pwstrDeviceId);
179 LogFunc(("%ls\n", pwstrDeviceId));
180 return S_OK;
181}
182
183/**
184 * Handler implementation which is called when an audio device has been removed.
185 *
186 * @return HRESULT
187 * @param pwstrDeviceId Device ID which has been removed.
188 */
189STDMETHODIMP VBoxMMNotificationClient::OnDeviceRemoved(LPCWSTR pwstrDeviceId)
190{
191 RT_NOREF(pwstrDeviceId);
192 LogFunc(("%ls\n", pwstrDeviceId));
193 return S_OK;
194}
195
196/**
197 * Handler implementation which is called when the device audio device has been
198 * changed.
199 *
200 * @return HRESULT
201 * @param eFlow Flow direction of the new default device.
202 * @param eRole Role of the new default device.
203 * @param pwstrDefaultDeviceId ID of the new default device.
204 */
205STDMETHODIMP VBoxMMNotificationClient::OnDefaultDeviceChanged(EDataFlow eFlow, ERole eRole, LPCWSTR pwstrDefaultDeviceId)
206{
207 RT_NOREF(eFlow, eRole, pwstrDefaultDeviceId);
208
209 if (eFlow == eRender)
210 {
211
212 }
213
214 return S_OK;
215}
216
217STDMETHODIMP VBoxMMNotificationClient::QueryInterface(REFIID interfaceID, void **ppvInterface)
218{
219 const IID IID_IMMNotificationClient = __uuidof(IMMNotificationClient);
220
221 if ( IsEqualIID(interfaceID, IID_IUnknown)
222 || IsEqualIID(interfaceID, IID_IMMNotificationClient))
223 {
224 *ppvInterface = static_cast<IMMNotificationClient*>(this);
225 AddRef();
226 return S_OK;
227 }
228
229 *ppvInterface = NULL;
230 return E_NOINTERFACE;
231}
232
233STDMETHODIMP_(ULONG) VBoxMMNotificationClient::AddRef(void)
234{
235 return InterlockedIncrement(&m_cRef);
236}
237
238STDMETHODIMP_(ULONG) VBoxMMNotificationClient::Release(void)
239{
240 long lRef = InterlockedDecrement(&m_cRef);
241 if (lRef == 0)
242 delete this;
243
244 return lRef;
245}
246
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