Merge pull request #20978 from prlanzarin/u30/fix/audio-ff-perm-api
fix(audio): ensure correct audio device labels in Firefox
This commit is contained in:
commit
a0fb450522
@ -280,6 +280,9 @@ class AudioSettings extends React.Component {
|
||||
// Only generate input streams if they're going to be used with something
|
||||
// In this case, the volume meter or local echo test.
|
||||
if (produceStreams) {
|
||||
this.setState({
|
||||
producingStreams: true,
|
||||
});
|
||||
this.generateInputStream(deviceId).then((stream) => {
|
||||
// Extract the deviceId again from the stream to guarantee consistency
|
||||
// between stream DID vs chosen DID. That's necessary in scenarios where,
|
||||
@ -302,8 +305,13 @@ class AudioSettings extends React.Component {
|
||||
this.setState({
|
||||
inputDeviceId: extractedDeviceId,
|
||||
stream,
|
||||
producingStreams: false,
|
||||
});
|
||||
|
||||
// Update the device list after the stream has been generated.
|
||||
// This is necessary to guarantee the device list is up-to-date, mainly
|
||||
// in Firefox as it omit labels if no active stream is present (even if
|
||||
// gUM permission is flagged as granted).
|
||||
this.updateDeviceList();
|
||||
}).catch((error) => {
|
||||
logger.warn({
|
||||
logCode: 'audiosettings_gum_failed',
|
||||
@ -314,6 +322,13 @@ class AudioSettings extends React.Component {
|
||||
},
|
||||
}, `Audio settings gUM failed: ${error.name}`);
|
||||
handleGUMFailure(error);
|
||||
}).finally(() => {
|
||||
// Component unmounted after gUM resolution -> skip echo rendering
|
||||
if (!this._isMounted) return;
|
||||
|
||||
this.setState({
|
||||
producingStreams: false,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
@ -378,6 +393,15 @@ class AudioSettings extends React.Component {
|
||||
audioInputDevices,
|
||||
audioOutputDevices,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.warn({
|
||||
logCode: 'audiosettings_enumerate_devices_error',
|
||||
extraInfo: {
|
||||
errorName: error.name,
|
||||
errorMessage: error.message,
|
||||
},
|
||||
}, `Audio settings: error enumerating devices - {${error.name}: ${error.message}}`);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -73,10 +73,45 @@ const useIsUsingAudio = () => {
|
||||
return Boolean(isConnected || isConnecting || isHangingUp || isEchoTest);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the user has granted permission to use the microphone.
|
||||
*
|
||||
* @param {Object} options - Options object.
|
||||
* @param {string} options.permissionStatus - The current permission status.
|
||||
* @param {boolean} options.gumOnPrompt - Whether to check microphone permission by attempting to
|
||||
* get a media stream.
|
||||
* @returns {Promise<boolean|null>} - A promise that resolves to a boolean indicating whether the
|
||||
* user has granted permission to use the microphone. If the permission status is unknown, the
|
||||
* promise resolves to null.
|
||||
*/
|
||||
const hasMicrophonePermission = async ({
|
||||
permissionStatus,
|
||||
permissionStatus = null,
|
||||
gumOnPrompt = false,
|
||||
}) => {
|
||||
const checkWithGUM = () => {
|
||||
if (!gumOnPrompt) return Promise.resolve(null);
|
||||
|
||||
return doGUM({ audio: getAudioConstraints() })
|
||||
.then((stream) => {
|
||||
// Close the stream and remove all tracks - this is just a permission check
|
||||
stream.getTracks().forEach((track) => {
|
||||
track.stop();
|
||||
stream.removeTrack(track);
|
||||
});
|
||||
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.name === 'NotAllowedError') return false;
|
||||
|
||||
// Give it the benefit of the doubt. It might be a device mismatch
|
||||
// or something else that's not a permissions issue, so let's try
|
||||
// to proceed. Rollbacks that happen downstream might fix the issue,
|
||||
// otherwise we'll land on the Help screen anyways
|
||||
return null;
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
let status = permissionStatus;
|
||||
|
||||
@ -91,36 +126,19 @@ const hasMicrophonePermission = async ({
|
||||
switch (status) {
|
||||
case 'denied':
|
||||
return false;
|
||||
case 'prompt':
|
||||
// Prompt without any subsequent action is considered unknown
|
||||
if (!gumOnPrompt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return doGUM({ audio: getAudioConstraints() }).then((stream) => {
|
||||
stream.getTracks().forEach((track) => {
|
||||
track.stop();
|
||||
stream.removeTrack(track);
|
||||
});
|
||||
return true;
|
||||
}).catch((error) => {
|
||||
if (error.name === 'NotAllowedError') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Give it the benefit of the doubt. It might be a device mismatch
|
||||
// or something else that's not a permissions issue, so let's try
|
||||
// to proceed. Rollbacks that happen downstream might fix the issue,
|
||||
// otherwise we'll land on the Help screen anyways
|
||||
return null;
|
||||
});
|
||||
|
||||
case 'granted':
|
||||
default:
|
||||
return true;
|
||||
|
||||
case null:
|
||||
case 'prompt':
|
||||
return checkWithGUM();
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
logger.warn({
|
||||
logCode: 'audio_check_microphone_permission_error',
|
||||
extraInfo: {
|
||||
errorName: error.name,
|
||||
@ -128,8 +146,7 @@ const hasMicrophonePermission = async ({
|
||||
},
|
||||
}, `Error checking microphone permission: ${error.message}`);
|
||||
|
||||
// Null = could not determine permission status
|
||||
return null;
|
||||
return checkWithGUM();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user