summaryrefslogtreecommitdiff
path: root/indra/llwebrtc/llwebrtc.cpp
diff options
context:
space:
mode:
authorRoxie Linden <roxie@lindenlab.com>2024-04-01 21:39:17 -0700
committerRoxie Linden <roxie@lindenlab.com>2024-04-01 21:39:17 -0700
commitc826aea079c59950a4064a94825534884fed8bf8 (patch)
tree3267543b3ee11002e6862388135327171917b782 /indra/llwebrtc/llwebrtc.cpp
parentc6e673cda139f5faaa52ccd03a372e7ffa9f5716 (diff)
Fix "default" audio device handling.
Windows and Mac/Linux behave slightly differently with respect to Default devices, in that mac/linux (I think) simply assumes the device at index 0 is the default one, and windows has a separate API for enabling the default device.
Diffstat (limited to 'indra/llwebrtc/llwebrtc.cpp')
-rw-r--r--indra/llwebrtc/llwebrtc.cpp230
1 files changed, 136 insertions, 94 deletions
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index 074b037529..75b2332bed 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -40,6 +40,11 @@
namespace llwebrtc
{
+static int16_t PLAYOUT_DEVICE_DEFAULT = -1;
+static int16_t PLAYOUT_DEVICE_BAD = -2;
+static int16_t RECORD_DEVICE_DEFAULT = -1;
+static int16_t RECORD_DEVICE_BAD = -2;
+
LLAudioDeviceObserver::LLAudioDeviceObserver() : mSumVector {0}, mMicrophoneEnergy(0.0) {}
float LLAudioDeviceObserver::getMicrophoneEnergy() { return mMicrophoneEnergy; }
@@ -189,10 +194,16 @@ void LLWebRTCImpl::init()
std::unique_ptr<webrtc::AudioDeviceDataObserver>(mTuningAudioDeviceObserver));
mTuningDeviceModule->Init();
- mTuningDeviceModule->SetStereoRecording(true);
- mTuningDeviceModule->SetStereoPlayout(true);
+ mTuningDeviceModule->SetPlayoutDevice(mPlayoutDevice);
+ mTuningDeviceModule->SetRecordingDevice(mRecordingDevice);
mTuningDeviceModule->EnableBuiltInAEC(false);
mTuningDeviceModule->SetAudioDeviceSink(this);
+ mTuningDeviceModule->InitMicrophone();
+ mTuningDeviceModule->InitSpeaker();
+ mTuningDeviceModule->InitRecording();
+ mTuningDeviceModule->InitPlayout();
+ mTuningDeviceModule->SetStereoRecording(true);
+ mTuningDeviceModule->SetStereoPlayout(true);
updateDevices();
});
@@ -207,13 +218,13 @@ void LLWebRTCImpl::init()
mPeerDeviceModule->Init();
mPeerDeviceModule->SetPlayoutDevice(mPlayoutDevice);
mPeerDeviceModule->SetRecordingDevice(mRecordingDevice);
- mPeerDeviceModule->SetStereoRecording(true);
- mPeerDeviceModule->SetStereoPlayout(true);
mPeerDeviceModule->EnableBuiltInAEC(false);
mPeerDeviceModule->InitMicrophone();
mPeerDeviceModule->InitSpeaker();
mPeerDeviceModule->InitRecording();
mPeerDeviceModule->InitPlayout();
+ mPeerDeviceModule->SetStereoRecording(true);
+ mPeerDeviceModule->SetStereoPlayout(true);
});
// The custom processor allows us to retrieve audio data (and levels)
@@ -375,145 +386,169 @@ void LLWebRTCImpl::unsetDevicesObserver(LLWebRTCDevicesObserver *observer)
}
}
-static int16_t ll_get_device_module_capture_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, const std::string &id)
-{
- int16_t recordingDevice = 0;
- int16_t captureDeviceCount = device_module->RecordingDevices();
- for (int16_t i = 0; i < captureDeviceCount; i++)
- {
- char name[webrtc::kAdmMaxDeviceNameSize];
- char guid[webrtc::kAdmMaxGuidSize];
- device_module->RecordingDeviceName(i, name, guid);
- if (id == guid || id == "Default") // first one in list is default
- {
- RTC_LOG(LS_INFO) << __FUNCTION__ << "Set recording device to " << name << " " << guid << " " << i;
- recordingDevice = i;
- break;
- }
- }
- return recordingDevice;
-}
-
void ll_set_device_module_capture_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, int16_t device)
{
device_module->StopRecording();
- device_module->SetRecordingDevice(device);
+#if LL_WINDOWS
+ if (device < 0)
+ {
+ device_module->SetRecordingDevice(webrtc::AudioDeviceModule::kDefaultDevice);
+ }
+ else
+ {
+ device_module->SetRecordingDevice(device);
+ }
+#else
+ // passed in default is -1, but the device list
+ // has it at 0
+ device_module->SetPlayoutDevice(device + 1);
+#endif
device_module->InitMicrophone();
- device_module->SetStereoRecording(false);
device_module->InitRecording();
+ device_module->SetStereoRecording(false);
device_module->StartRecording();
}
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
{
-
- mWorkerThread->PostTask(
- [this, id]()
+ int16_t recordingDevice = RECORD_DEVICE_DEFAULT;
+ if (id != "Default")
+ {
+ for (int16_t i = 0; i < mRecordingDeviceList.size(); i++)
{
- int16_t recordingDevice = ll_get_device_module_capture_device(mTuningDeviceModule, id);
- if (recordingDevice != mRecordingDevice)
+ if (mRecordingDeviceList[i].mID == id)
{
- mRecordingDevice = recordingDevice;
- if (mTuningMode)
- {
- ll_set_device_module_capture_device(mTuningDeviceModule, recordingDevice);
- }
- else
- {
- ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice);
- }
+ recordingDevice = i;
+ break;
}
- });
-}
-
-static int16_t ll_get_device_module_render_device(
- rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module,
- const std::string &id)
-{
- int16_t playoutDevice = 0;
- int16_t playoutDeviceCount = device_module->PlayoutDevices();
- for (int16_t i = 0; i < playoutDeviceCount; i++)
- {
- char name[webrtc::kAdmMaxDeviceNameSize];
- char guid[webrtc::kAdmMaxGuidSize];
- device_module->PlayoutDeviceName(i, name, guid);
- if (id == guid || id == "Default") // first one in list is default
- {
- RTC_LOG(LS_INFO) << __FUNCTION__ << "Set recording device to " << name << " " << guid << " " << i;
- playoutDevice = i;
- break;
}
}
- return playoutDevice;
+ if (recordingDevice == mRecordingDevice)
+ {
+ return;
+ }
+ mRecordingDevice = recordingDevice;
+ if (mTuningMode)
+ {
+ mWorkerThread->PostTask([this, recordingDevice]() { ll_set_device_module_capture_device(mTuningDeviceModule, recordingDevice); });
+ }
+ else
+ {
+ mWorkerThread->PostTask([this, recordingDevice]() { ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice); });
+ }
}
void ll_set_device_module_render_device(rtc::scoped_refptr<webrtc::AudioDeviceModule> device_module, int16_t device)
{
device_module->StopPlayout();
- device_module->SetPlayoutDevice(device);
+#if LL_WINDOWS
+ if (device < 0)
+ {
+ device_module->SetPlayoutDevice(webrtc::AudioDeviceModule::kDefaultDevice);
+ }
+ else
+ {
+ device_module->SetPlayoutDevice(device);
+ }
+#else
+ device_module->SetPlayoutDevice(device + 1);
+#endif
device_module->InitSpeaker();
- device_module->SetStereoPlayout(false);
device_module->InitPlayout();
- device_module->StartPlayout();
+ device_module->SetStereoPlayout(true);
}
void LLWebRTCImpl::setRenderDevice(const std::string &id)
{
- mWorkerThread->PostTask(
- [this, id]()
- {
- int16_t playoutDevice = ll_get_device_module_render_device(mTuningDeviceModule, id);
- if (playoutDevice != mPlayoutDevice)
+ int16_t playoutDevice = PLAYOUT_DEVICE_DEFAULT;
+ if (id != "Default")
+ {
+ for (int16_t i = 0; i < mPlayoutDeviceList.size(); i++)
+ {
+ if (mPlayoutDeviceList[i].mID == id)
{
- mPlayoutDevice = playoutDevice;
- if (mTuningMode)
- {
- ll_set_device_module_render_device(mTuningDeviceModule, playoutDevice);
- }
- else
- {
- ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
- }
+ playoutDevice = i;
+ break;
}
- });
+ }
+ }
+ if (playoutDevice == mPlayoutDevice)
+ {
+ return;
+ }
+ mPlayoutDevice = playoutDevice;
+
+ if (mTuningMode)
+ {
+ mWorkerThread->PostTask(
+ [this, playoutDevice]()
+ {
+ ll_set_device_module_render_device(mTuningDeviceModule, playoutDevice);
+ });
+ }
+ else
+ {
+ mWorkerThread->PostTask(
+ [this, playoutDevice]()
+ {
+ ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
+ mPeerDeviceModule->StartPlayout();
+ });
+ }
}
// updateDevices needs to happen on the worker thread.
void LLWebRTCImpl::updateDevices()
{
- int16_t renderDeviceCount = mTuningDeviceModule->PlayoutDevices();
- int16_t currentRenderDeviceIndex = mTuningDeviceModule->GetPlayoutDevice();
-
- LLWebRTCVoiceDeviceList renderDeviceList;
- for (int16_t index = 0; index < renderDeviceCount; index++)
+ int16_t renderDeviceCount = mTuningDeviceModule->PlayoutDevices();
+
+ mPlayoutDeviceList.clear();
+#if LL_WINDOWS
+ int16_t index = 0;
+#else
+ // index zero is always "Default" for darwin/linux,
+ // which is a special case, so skip it.
+ int16_t index = 1;
+#endif
+ for (; index < renderDeviceCount; index++)
{
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mTuningDeviceModule->PlayoutDeviceName(index, name, guid);
- renderDeviceList.emplace_back(name, guid);
+ mPlayoutDeviceList.emplace_back(name, guid);
}
- int16_t captureDeviceCount = mTuningDeviceModule->RecordingDevices();
- int16_t currentCaptureDeviceIndex = mTuningDeviceModule->GetRecordingDevice();
-
- LLWebRTCVoiceDeviceList captureDeviceList;
- for (int16_t index = 0; index < captureDeviceCount; index++)
+ int16_t captureDeviceCount = mTuningDeviceModule->RecordingDevices();
+
+ mRecordingDeviceList.clear();
+#if LL_WINDOWS
+ index = 0;
+#else
+ // index zero is always "Default" for darwin/linux,
+ // which is a special case, so skip it.
+ index = 1;
+#endif
+ for (; index < captureDeviceCount; index++)
{
char name[webrtc::kAdmMaxDeviceNameSize];
char guid[webrtc::kAdmMaxGuidSize];
mTuningDeviceModule->RecordingDeviceName(index, name, guid);
- captureDeviceList.emplace_back(name, guid);
+ mRecordingDeviceList.emplace_back(name, guid);
}
+
for (auto &observer : mVoiceDevicesObserverList)
{
- observer->OnDevicesChanged(renderDeviceList,
- captureDeviceList);
+ observer->OnDevicesChanged(mPlayoutDeviceList, mRecordingDeviceList);
}
}
void LLWebRTCImpl::OnDevicesUpdated()
{
+ // reset these to a bad value so an update is forced
+ mRecordingDevice = RECORD_DEVICE_BAD;
+ mPlayoutDevice = PLAYOUT_DEVICE_BAD;
+
updateDevices();
}
@@ -529,17 +564,24 @@ void LLWebRTCImpl::setTuningMode(bool enable)
mPeerDeviceModule->StopPlayout();
ll_set_device_module_render_device(mTuningDeviceModule, mPlayoutDevice);
ll_set_device_module_capture_device(mTuningDeviceModule, mRecordingDevice);
+ mTuningDeviceModule->InitPlayout();
+ mTuningDeviceModule->InitRecording();
mTuningDeviceModule->StartRecording();
- mTuningDeviceModule->StartPlayout();
+ // TODO: Starting Playout on the TDM appears to create an audio artifact (click)
+ // in this case, so disabling it for now. We may have to do something different
+ // if we enable 'echo playback' via the TDM when tuning.
+ //mTuningDeviceModule->StartPlayout();
}
else
{
mTuningDeviceModule->StopRecording();
- mTuningDeviceModule->StopPlayout();
+ //mTuningDeviceModule->StopPlayout();
ll_set_device_module_render_device(mPeerDeviceModule, mPlayoutDevice);
ll_set_device_module_capture_device(mPeerDeviceModule, mRecordingDevice);
- mPeerDeviceModule->StartRecording();
+ mPeerDeviceModule->InitPlayout();
+ mPeerDeviceModule->InitRecording();
mPeerDeviceModule->StartPlayout();
+ mPeerDeviceModule->StartRecording();
}
}
);