Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add audio device changes detect for windows. #41

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions modules/audio_device/audio_device_generic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,4 @@ int AudioDeviceGeneric::GetRecordAudioParameters(
}
#endif // WEBRTC_IOS

int32_t AudioDeviceGeneric::SetAudioDeviceSink(AudioDeviceSink* sink) {
RTC_LOG(LS_INFO) << __FUNCTION__ << "(" << sink << ")";
audio_device_module_sink_ = sink;
return 0;
}

} // namespace webrtc
5 changes: 1 addition & 4 deletions modules/audio_device/audio_device_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,11 @@ class AudioDeviceGeneric {
virtual int GetRecordAudioParameters(AudioParameters* params) const;
#endif // WEBRTC_IOS

int32_t SetAudioDeviceSink(AudioDeviceSink* sink);
virtual int32_t SetAudioDeviceSink(AudioDeviceSink* sink) = 0;

virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) = 0;

virtual ~AudioDeviceGeneric() {}

protected:
AudioDeviceSink* audio_device_module_sink_ = nullptr;
};

} // namespace webrtc
Expand Down
4 changes: 4 additions & 0 deletions modules/audio_device/dummy/audio_device_dummy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,5 +222,9 @@ int32_t AudioDeviceDummy::PlayoutDelay(uint16_t& delayMS) const {
return -1;
}

int32_t AudioDeviceDummy::SetAudioDeviceSink(AudioDeviceSink* sink) {
return -1;
}

void AudioDeviceDummy::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {}
} // namespace webrtc
3 changes: 3 additions & 0 deletions modules/audio_device/dummy/audio_device_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ class AudioDeviceDummy : public AudioDeviceGeneric {
// Delay information and control
int32_t PlayoutDelay(uint16_t& delayMS) const override;

int32_t SetAudioDeviceSink(AudioDeviceSink* sink) override;

void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;

};

} // namespace webrtc
Expand Down
4 changes: 4 additions & 0 deletions modules/audio_device/dummy/file_audio_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ int32_t FileAudioDevice::PlayoutDelay(uint16_t& delayMS) const {
return 0;
}

int32_t FileAudioDevice::SetAudioDeviceSink(AudioDeviceSink* sink) {
return -1;
}

void FileAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
MutexLock lock(&mutex_);

Expand Down
2 changes: 2 additions & 0 deletions modules/audio_device/dummy/file_audio_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class FileAudioDevice : public AudioDeviceGeneric {
// Delay information and control
int32_t PlayoutDelay(uint16_t& delayMS) const override;

int32_t SetAudioDeviceSink(AudioDeviceSink* sink) override;

void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;

private:
Expand Down
70 changes: 70 additions & 0 deletions modules/audio_device/win/audio_device_core_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ AudioDeviceWindowsCore::AudioDeviceWindowsCore()
_playChannelsPrioList[0] = 2; // stereo is prio 1
_playChannelsPrioList[1] = 1; // mono is prio 2

_deviceStateListener = new DeviceStateListener();

HRESULT hr;

// We know that this API will work since it has already been verified in
Expand All @@ -475,6 +477,8 @@ AudioDeviceWindowsCore::AudioDeviceWindowsCore()
reinterpret_cast<void**>(&_ptrEnumerator));
RTC_DCHECK(_ptrEnumerator);

_ptrEnumerator->RegisterEndpointNotificationCallback(_deviceStateListener);

// DMO initialization for built-in WASAPI AEC.
{
IMediaObject* ptrDMO = NULL;
Expand All @@ -500,6 +504,8 @@ AudioDeviceWindowsCore::~AudioDeviceWindowsCore() {

Terminate();

_ptrEnumerator->UnregisterEndpointNotificationCallback(_deviceStateListener);

// The IMMDeviceEnumerator is created during construction. Must release
// it here and not in Terminate() since we don't recreate it in Init().
SAFE_RELEASE(_ptrEnumerator);
Expand Down Expand Up @@ -536,6 +542,11 @@ AudioDeviceWindowsCore::~AudioDeviceWindowsCore() {
_hShutdownCaptureEvent = NULL;
}

if(NULL != _deviceStateListener) {
delete _deviceStateListener;
_deviceStateListener = NULL;
}

if (_avrtLibrary) {
BOOL freeOK = FreeLibrary(_avrtLibrary);
if (!freeOK) {
Expand Down Expand Up @@ -3894,6 +3905,65 @@ int32_t AudioDeviceWindowsCore::_GetDeviceID(IMMDevice* pDevice,
return 0;
}

int32_t AudioDeviceWindowsCore::SetAudioDeviceSink(AudioDeviceSink* sink) {
_deviceStateListener->SetAudioDeviceSink(sink);
return 0;
}

void AudioDeviceWindowsCore::DeviceStateListener::SetAudioDeviceSink(AudioDeviceSink *sink) {
callback_ = sink;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceStateChanged => " << pwstrDeviceId << ", NewState => " << dwNewState;
if(callback_) callback_->OnDevicesUpdated();
return S_OK;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceAdded(LPCWSTR pwstrDeviceId) {
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceAdded => " << pwstrDeviceId;
return S_OK;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDeviceRemoved => " << pwstrDeviceId;
return S_OK;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) {
RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnDefaultDeviceChanged => " << pwstrDefaultDeviceId;
return S_OK;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
//RTC_DLOG(LS_INFO) << "AudioDeviceWindowsCore::OnPropertyValueChanged => " << pwstrDeviceId;
return S_OK;
}

ULONG AudioDeviceWindowsCore::DeviceStateListener::AddRef() {
ULONG new_ref = InterlockedIncrement(&ref_count_);
// RTC_DLOG(LS_INFO) << "__AddRef => " << new_ref;
return new_ref;
}

ULONG AudioDeviceWindowsCore::DeviceStateListener::Release() {
ULONG new_ref = InterlockedDecrement(&ref_count_);
// RTC_DLOG(LS_INFO) << "__Release => " << new_ref;
return new_ref;
}

HRESULT AudioDeviceWindowsCore::DeviceStateListener::QueryInterface(REFIID iid, void** object) {
if (object == nullptr) {
return E_POINTER;
}
if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) {
*object = static_cast<IMMNotificationClient*>(this);
return S_OK;
}
*object = nullptr;
return E_NOINTERFACE;
}

// ----------------------------------------------------------------------------
// _GetDefaultDevice
// ----------------------------------------------------------------------------
Expand Down
32 changes: 32 additions & 0 deletions modules/audio_device/win/audio_device_core_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <endpointvolume.h>
#include <mediaobj.h> // IMediaObject
#include <mmdeviceapi.h> // MMDevice
#include <comdef.h>
#include <objbase.h>

#include "api/scoped_refptr.h"
#include "rtc_base/synchronization/mutex.h"
Expand All @@ -51,6 +53,33 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
AudioDeviceWindowsCore();
~AudioDeviceWindowsCore();

class DeviceStateListener : public IMMNotificationClient {
public:
virtual ~DeviceStateListener() = default;
HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId,
DWORD dwNewState) override;
HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override;

HRESULT __stdcall OnDeviceRemoved(LPCWSTR pwstrDeviceId) override;

HRESULT
__stdcall OnDefaultDeviceChanged(EDataFlow flow,
ERole role,
LPCWSTR pwstrDefaultDeviceId) override;

HRESULT __stdcall OnPropertyValueChanged(LPCWSTR pwstrDeviceId,
const PROPERTYKEY key) override;
// IUnknown (required by IMMNotificationClient).
ULONG __stdcall AddRef() override;
ULONG __stdcall Release() override;
HRESULT __stdcall QueryInterface(REFIID iid, void** object) override;
void SetAudioDeviceSink(AudioDeviceSink *sink);

private:
LONG ref_count_ = 1;
AudioDeviceSink *callback_ = nullptr;
};

static bool CoreAudioIsSupported();

// Retrieve the currently utilized audio layer
Expand Down Expand Up @@ -151,6 +180,8 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {

virtual int32_t EnableBuiltInAEC(bool enable);

virtual int32_t SetAudioDeviceSink(AudioDeviceSink* sink);

public:
virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);

Expand Down Expand Up @@ -238,6 +269,7 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
IAudioEndpointVolume* _ptrCaptureVolume;
ISimpleAudioVolume* _ptrRenderSimpleVolume;

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