Skip to content

Commit 335be94

Browse files
committed
feat: add audio device changes detect for windows. (#41)
* feat: add audio device changes detect for windows. * Update audio_device_core_win.cc
1 parent c62ce62 commit 335be94

File tree

7 files changed

+117
-0
lines changed

7 files changed

+117
-0
lines changed

modules/audio_device/audio_device_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class AudioDeviceGeneric {
135135
virtual int GetRecordAudioParameters(AudioParameters* params) const;
136136
#endif // WEBRTC_IOS
137137

138+
virtual int32_t SetAudioDeviceSink(AudioDeviceSink* sink) = 0;
139+
138140
virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) = 0;
139141

140142
virtual ~AudioDeviceGeneric() {}

modules/audio_device/dummy/audio_device_dummy.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,5 +222,9 @@ int32_t AudioDeviceDummy::PlayoutDelay(uint16_t& delayMS) const {
222222
return -1;
223223
}
224224

225+
int32_t AudioDeviceDummy::SetAudioDeviceSink(AudioDeviceSink* sink) {
226+
return -1;
227+
}
228+
225229
void AudioDeviceDummy::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {}
226230
} // namespace webrtc

modules/audio_device/dummy/audio_device_dummy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,10 @@ class AudioDeviceDummy : public AudioDeviceGeneric {
109109
// Delay information and control
110110
int32_t PlayoutDelay(uint16_t& delayMS) const override;
111111

112+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink) override;
113+
112114
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
115+
113116
};
114117

115118
} // namespace webrtc

modules/audio_device/dummy/file_audio_device.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,10 @@ int32_t FileAudioDevice::PlayoutDelay(uint16_t& delayMS) const {
427427
return 0;
428428
}
429429

430+
int32_t FileAudioDevice::SetAudioDeviceSink(AudioDeviceSink* sink) {
431+
return -1;
432+
}
433+
430434
void FileAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
431435
MutexLock lock(&mutex_);
432436

modules/audio_device/dummy/file_audio_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class FileAudioDevice : public AudioDeviceGeneric {
123123
// Delay information and control
124124
int32_t PlayoutDelay(uint16_t& delayMS) const override;
125125

126+
int32_t SetAudioDeviceSink(AudioDeviceSink* sink) override;
127+
126128
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
127129

128130
private:

modules/audio_device/win/audio_device_core_win.cc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@ AudioDeviceWindowsCore::AudioDeviceWindowsCore()
461461
_playChannelsPrioList[0] = 2; // stereo is prio 1
462462
_playChannelsPrioList[1] = 1; // mono is prio 2
463463

464+
_deviceStateListener = new DeviceStateListener();
465+
464466
HRESULT hr;
465467

466468
// We know that this API will work since it has already been verified in
@@ -474,6 +476,8 @@ AudioDeviceWindowsCore::AudioDeviceWindowsCore()
474476
reinterpret_cast<void**>(&_ptrEnumerator));
475477
RTC_DCHECK(_ptrEnumerator);
476478

479+
_ptrEnumerator->RegisterEndpointNotificationCallback(_deviceStateListener);
480+
477481
// DMO initialization for built-in WASAPI AEC.
478482
{
479483
IMediaObject* ptrDMO = NULL;
@@ -499,6 +503,8 @@ AudioDeviceWindowsCore::~AudioDeviceWindowsCore() {
499503

500504
Terminate();
501505

506+
_ptrEnumerator->UnregisterEndpointNotificationCallback(_deviceStateListener);
507+
502508
// The IMMDeviceEnumerator is created during construction. Must release
503509
// it here and not in Terminate() since we don't recreate it in Init().
504510
SAFE_RELEASE(_ptrEnumerator);
@@ -535,6 +541,11 @@ AudioDeviceWindowsCore::~AudioDeviceWindowsCore() {
535541
_hShutdownCaptureEvent = NULL;
536542
}
537543

544+
if(NULL != _deviceStateListener) {
545+
delete _deviceStateListener;
546+
_deviceStateListener = NULL;
547+
}
548+
538549
if (_avrtLibrary) {
539550
BOOL freeOK = FreeLibrary(_avrtLibrary);
540551
if (!freeOK) {
@@ -3894,6 +3905,65 @@ int32_t AudioDeviceWindowsCore::_GetDeviceID(IMMDevice* pDevice,
38943905
return 0;
38953906
}
38963907

3908+
int32_t AudioDeviceWindowsCore::SetAudioDeviceSink(AudioDeviceSink* sink) {
3909+
_deviceStateListener->SetAudioDeviceSink(sink);
3910+
return 0;
3911+
}
3912+
3913+
void AudioDeviceWindowsCore::DeviceStateListener::SetAudioDeviceSink(AudioDeviceSink *sink) {
3914+
callback_ = sink;
3915+
}
3916+
3917+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
3918+
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceStateChanged => " << pwstrDeviceId << ", NewState => " << dwNewState;
3919+
if(callback_) callback_->OnDevicesUpdated();
3920+
return S_OK;
3921+
}
3922+
3923+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
3924+
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceAdded => " << pwstrDeviceId;
3925+
return S_OK;
3926+
}
3927+
3928+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
3929+
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceRemoved => " << pwstrDeviceId;
3930+
return S_OK;
3931+
}
3932+
3933+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) {
3934+
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDefaultDeviceChanged => " << pwstrDefaultDeviceId;
3935+
return S_OK;
3936+
}
3937+
3938+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
3939+
//RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnPropertyValueChanged => " << pwstrDeviceId;
3940+
return S_OK;
3941+
}
3942+
3943+
ULONG AudioDeviceWindowsCore::DeviceStateListener::AddRef() {
3944+
ULONG new_ref = InterlockedIncrement(&ref_count_);
3945+
// RTC_DLOG(LS_INFO) << "__AddRef => " << new_ref;
3946+
return new_ref;
3947+
}
3948+
3949+
ULONG AudioDeviceWindowsCore::DeviceStateListener::Release() {
3950+
ULONG new_ref = InterlockedDecrement(&ref_count_);
3951+
// RTC_DLOG(LS_INFO) << "__Release => " << new_ref;
3952+
return new_ref;
3953+
}
3954+
3955+
HRESULT AudioDeviceWindowsCore::DeviceStateListener::QueryInterface(REFIID iid, void** object) {
3956+
if (object == nullptr) {
3957+
return E_POINTER;
3958+
}
3959+
if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) {
3960+
*object = static_cast<IMMNotificationClient*>(this);
3961+
return S_OK;
3962+
}
3963+
*object = nullptr;
3964+
return E_NOINTERFACE;
3965+
}
3966+
38973967
// ----------------------------------------------------------------------------
38983968
// _GetDefaultDevice
38993969
// ----------------------------------------------------------------------------

modules/audio_device/win/audio_device_core_win.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <endpointvolume.h>
2323
#include <mediaobj.h> // IMediaObject
2424
#include <mmdeviceapi.h> // MMDevice
25+
#include <comdef.h>
26+
#include <objbase.h>
2527

2628
#include "api/scoped_refptr.h"
2729
#include "modules/audio_device/audio_device_generic.h"
@@ -50,6 +52,33 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
5052
AudioDeviceWindowsCore();
5153
~AudioDeviceWindowsCore();
5254

55+
class DeviceStateListener : public IMMNotificationClient {
56+
public:
57+
virtual ~DeviceStateListener() = default;
58+
HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId,
59+
DWORD dwNewState) override;
60+
HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override;
61+
62+
HRESULT __stdcall OnDeviceRemoved(LPCWSTR pwstrDeviceId) override;
63+
64+
HRESULT
65+
__stdcall OnDefaultDeviceChanged(EDataFlow flow,
66+
ERole role,
67+
LPCWSTR pwstrDefaultDeviceId) override;
68+
69+
HRESULT __stdcall OnPropertyValueChanged(LPCWSTR pwstrDeviceId,
70+
const PROPERTYKEY key) override;
71+
// IUnknown (required by IMMNotificationClient).
72+
ULONG __stdcall AddRef() override;
73+
ULONG __stdcall Release() override;
74+
HRESULT __stdcall QueryInterface(REFIID iid, void** object) override;
75+
void SetAudioDeviceSink(AudioDeviceSink *sink);
76+
77+
private:
78+
LONG ref_count_ = 1;
79+
AudioDeviceSink *callback_ = nullptr;
80+
};
81+
5382
static bool CoreAudioIsSupported();
5483

5584
// Retrieve the currently utilized audio layer
@@ -150,6 +179,8 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
150179

151180
virtual int32_t EnableBuiltInAEC(bool enable);
152181

182+
virtual int32_t SetAudioDeviceSink(AudioDeviceSink* sink);
183+
153184
public:
154185
virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
155186

@@ -237,6 +268,7 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
237268
IAudioEndpointVolume* _ptrCaptureVolume;
238269
ISimpleAudioVolume* _ptrRenderSimpleVolume;
239270

271+
DeviceStateListener *_deviceStateListener = nullptr;
240272
// DirectX Media Object (DMO) for the built-in AEC.
241273
rtc::scoped_refptr<IMediaObject> _dmo;
242274
rtc::scoped_refptr<IMediaBuffer> _mediaBuffer;

0 commit comments

Comments
 (0)