From 2127c7dccebc4873aca1186117e1a85438c1a848 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:37:36 +0700 Subject: [PATCH] android, desktop: don't stop audio track on Android in calls (#5024) * android, desktop: don't stop audio track on Android in calls There is a problem related to managing selected audio output device in call. When microphone is disabled, WebView turns speaker on without need. No way to prevent it was found yet. This is temporary workaround that makes everything work except it makes microphone icon visible in status bar (microphone is not used actually in that moment) * enabled=false --- .../src/commonMain/resources/assets/www/call.js | 13 ++++++++++--- packages/simplex-chat-webrtc/src/call.ts | 13 +++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/resources/assets/www/call.js b/apps/multiplatform/common/src/commonMain/resources/assets/www/call.js index 32f014e622..4dae487d03 100644 --- a/apps/multiplatform/common/src/commonMain/resources/assets/www/call.js +++ b/apps/multiplatform/common/src/commonMain/resources/assets/www/call.js @@ -63,6 +63,7 @@ const allowSendScreenAudio = false; // When one side of a call sends candidates tot fast (until local & remote descriptions are set), that candidates // will be stored here and then set when the call will be ready to process them let afterCallInitializedCandidates = []; +const stopTrackOnAndroid = false; const processCommand = (function () { const defaultIceServers = [ { urls: ["stuns:stun.simplex.im:443"] }, @@ -844,7 +845,10 @@ const processCommand = (function () { // doing it vice versa gives an error like "too many cameras were open" on some Android devices or webViews // which means the second camera will never be opened for (const t of source == CallMediaSource.Mic ? call.localStream.getAudioTracks() : call.localStream.getVideoTracks()) { - t.stop(); + if (isDesktop || source != CallMediaSource.Mic || stopTrackOnAndroid) + t.stop(); + else + t.enabled = false; call.localStream.removeTrack(t); } let localStream; @@ -894,7 +898,7 @@ const processCommand = (function () { if (!localStream || !oldCamera || !videos) return; if (!inactiveCallMediaSources.mic) { - localStream.getAudioTracks().forEach((elem) => elem.stop()); + localStream.getAudioTracks().forEach((elem) => (isDesktop || stopTrackOnAndroid ? elem.stop() : (elem.enabled = false))); localStream.getAudioTracks().forEach((elem) => localStream.removeTrack(elem)); } if (!inactiveCallMediaSources.camera || oldCamera != newCamera) { @@ -1157,7 +1161,10 @@ const processCommand = (function () { transceiver.sender.replaceTrack(t); } else { - t.stop(); + if (isDesktop || t.kind == CallMediaType.Video || stopTrackOnAndroid) + t.stop(); + else + t.enabled = false; s.removeTrack(t); transceiver.sender.replaceTrack(null); } diff --git a/packages/simplex-chat-webrtc/src/call.ts b/packages/simplex-chat-webrtc/src/call.ts index eda535cfa7..693ad6bbe5 100644 --- a/packages/simplex-chat-webrtc/src/call.ts +++ b/packages/simplex-chat-webrtc/src/call.ts @@ -246,7 +246,7 @@ const callCrypto = callCryptoFunction() declare var RTCRtpScriptTransform: { prototype: RTCRtpScriptTransform - new (worker: Worker, options?: any): RTCRtpScriptTransform + new (worker: Worker, options?: any, transfer?: any[] | undefined): RTCRtpScriptTransform } enum TransformOperation { @@ -316,6 +316,8 @@ const allowSendScreenAudio = false // will be stored here and then set when the call will be ready to process them let afterCallInitializedCandidates: RTCIceCandidateInit[] = [] +const stopTrackOnAndroid = false + const processCommand = (function () { type RTCRtpSenderWithEncryption = RTCRtpSender & { createEncodedStreams: () => TransformStream @@ -1141,7 +1143,8 @@ const processCommand = (function () { // doing it vice versa gives an error like "too many cameras were open" on some Android devices or webViews // which means the second camera will never be opened for (const t of source == CallMediaSource.Mic ? call.localStream.getAudioTracks() : call.localStream.getVideoTracks()) { - t.stop() + if (isDesktop || source != CallMediaSource.Mic || stopTrackOnAndroid) t.stop() + else t.enabled = false call.localStream.removeTrack(t) } let localStream: MediaStream @@ -1200,7 +1203,7 @@ const processCommand = (function () { if (!localStream || !oldCamera || !videos) return if (!inactiveCallMediaSources.mic) { - localStream.getAudioTracks().forEach((elem) => elem.stop()) + localStream.getAudioTracks().forEach((elem) => (isDesktop || stopTrackOnAndroid ? elem.stop() : (elem.enabled = false))) localStream.getAudioTracks().forEach((elem) => localStream.removeTrack(elem)) } if (!inactiveCallMediaSources.camera || oldCamera != newCamera) { @@ -1474,7 +1477,9 @@ const processCommand = (function () { if (enable) { transceiver.sender.replaceTrack(t) } else { - t.stop() + if (isDesktop || t.kind == CallMediaType.Video || stopTrackOnAndroid) t.stop() + else t.enabled = false + s.removeTrack(t) transceiver.sender.replaceTrack(null) }