Fix call mute failures, stale session writes, and leaked audio elements
This commit is contained in:
parent
eae644ab3c
commit
fe90a9f0ba
1 changed files with 30 additions and 19 deletions
|
|
@ -214,9 +214,7 @@ export const joinVoiceRoom = async (
|
||||||
whenAborted(signal),
|
whenAborted(signal),
|
||||||
])
|
])
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (activeRoom === liveKitRoom) activeRoom = undefined
|
teardownRoom(liveKitRoom)
|
||||||
liveKitRoom.removeAllListeners()
|
|
||||||
liveKitRoom.disconnect()
|
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,9 +237,7 @@ export const joinVoiceRoom = async (
|
||||||
// A cancel during the mic step must tear down the connected room rather
|
// A cancel during the mic step must tear down the connected room rather
|
||||||
// than leaking it.
|
// than leaking it.
|
||||||
if (signal.aborted) {
|
if (signal.aborted) {
|
||||||
if (activeRoom === liveKitRoom) activeRoom = undefined
|
teardownRoom(liveKitRoom)
|
||||||
liveKitRoom.removeAllListeners()
|
|
||||||
liveKitRoom.disconnect()
|
|
||||||
throw new AbortError()
|
throw new AbortError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,9 +290,7 @@ export const leaveVoiceRoom = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always tear down this room's connection and listeners.
|
// Always tear down this room's connection and listeners.
|
||||||
if (activeRoom === session.livekit) activeRoom = undefined
|
teardownRoom(session.livekit)
|
||||||
session.livekit.removeAllListeners()
|
|
||||||
session.livekit.disconnect()
|
|
||||||
|
|
||||||
// Only reset shared UI state if this session is still current. A slow leave
|
// Only reset shared UI state if this session is still current. A slow leave
|
||||||
// that was superseded by a new join (bounded by a timeout in joinVoiceRoom)
|
// that was superseded by a new join (bounded by a timeout in joinVoiceRoom)
|
||||||
|
|
@ -320,16 +314,16 @@ export const toggleMute = async () => {
|
||||||
if (!session) return
|
if (!session) return
|
||||||
|
|
||||||
callMicMuted.update(not)
|
callMicMuted.update(not)
|
||||||
if (get(callMicMuted)) {
|
|
||||||
session.livekit.localParticipant.setMicrophoneEnabled(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const muted = get(callMicMuted)
|
||||||
try {
|
try {
|
||||||
await session.livekit.localParticipant.setMicrophoneEnabled(true)
|
await session.livekit.localParticipant.setMicrophoneEnabled(!muted)
|
||||||
} catch (e) {
|
} catch {
|
||||||
callMicMuted.set(true)
|
callMicMuted.set(!muted)
|
||||||
pushToast({theme: "error", message: "Could not access microphone"})
|
pushToast({
|
||||||
|
theme: "error",
|
||||||
|
message: muted ? "Could not mute microphone" : "Could not access microphone",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,7 +334,7 @@ export const toggleCamera = async () => {
|
||||||
const cameraOn = !session.cameraOn
|
const cameraOn = !session.cameraOn
|
||||||
try {
|
try {
|
||||||
await session.livekit.localParticipant.setCameraEnabled(cameraOn)
|
await session.livekit.localParticipant.setCameraEnabled(cameraOn)
|
||||||
currentCallSession.set({...session, cameraOn})
|
currentCallSession.update(s => s && {...s, cameraOn})
|
||||||
} catch {
|
} catch {
|
||||||
pushToast({
|
pushToast({
|
||||||
theme: "error",
|
theme: "error",
|
||||||
|
|
@ -356,7 +350,7 @@ export const toggleScreenShare = async () => {
|
||||||
const screenShareOn = !session.screenShareOn
|
const screenShareOn = !session.screenShareOn
|
||||||
try {
|
try {
|
||||||
await session.livekit.localParticipant.setScreenShareEnabled(screenShareOn)
|
await session.livekit.localParticipant.setScreenShareEnabled(screenShareOn)
|
||||||
currentCallSession.set({...session, screenShareOn})
|
currentCallSession.update(s => s && {...s, screenShareOn})
|
||||||
} catch {
|
} catch {
|
||||||
pushToast({
|
pushToast({
|
||||||
theme: "error",
|
theme: "error",
|
||||||
|
|
@ -463,6 +457,21 @@ currentCallSession.subscribe(session => {
|
||||||
resetVideoCallLayout()
|
resetVideoCallLayout()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const teardownRoom = (livekit: LiveKitRoom) => {
|
||||||
|
if (activeRoom === livekit) activeRoom = undefined
|
||||||
|
|
||||||
|
// Dropping the listeners keeps TrackUnsubscribed from removing the hidden
|
||||||
|
// audio elements onTrackSubscribed appended, so detach them here instead.
|
||||||
|
for (const participant of livekit.remoteParticipants.values()) {
|
||||||
|
for (const publication of participant.audioTrackPublications.values()) {
|
||||||
|
publication.track?.detach().forEach(el => el.remove())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
livekit.removeAllListeners()
|
||||||
|
livekit.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
const countLiveVisualFeeds = (session: CallSession): number => {
|
const countLiveVisualFeeds = (session: CallSession): number => {
|
||||||
const livekit = session.livekit
|
const livekit = session.livekit
|
||||||
let n = 0
|
let n = 0
|
||||||
|
|
@ -639,6 +648,8 @@ const makeOnRoomDisconnected = (livekit: LiveKitRoom) => (reason?: DisconnectRea
|
||||||
// Ignore disconnects from rooms that are no longer the active session.
|
// Ignore disconnects from rooms that are no longer the active session.
|
||||||
if (livekit !== activeRoom) return
|
if (livekit !== activeRoom) return
|
||||||
|
|
||||||
|
// Livekit unsubscribes remote tracks before emitting Disconnected, so
|
||||||
|
// onTrackUnsubscribed has already removed their audio elements by now.
|
||||||
activeRoom = undefined
|
activeRoom = undefined
|
||||||
livekit.removeAllListeners()
|
livekit.removeAllListeners()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue