Detect guest audio from MediaStream tracks instead of relying on Video/Data channel#6039
Detect guest audio from MediaStream tracks instead of relying on Video/Data channel#6039tareko wants to merge 1 commit into
Conversation
…ing on DataChannel Guest users whose DataChannel never establishes would have isAudioEnabled stay false even though audio tracks exist in the MediaStream. This caused guests to appear as 'connecting' with no audio on mobile while working on desktop. - handleStreamChange() now sets isAudioEnabled based on audio track presence - handleIceConnectionStateChange() preserves audio/video state during ICE CHECKING/NEW if tracks are still present in the peer connection - Add enhanced diagnostic logging for guest participant debugging - Add GuestAudioDetectionTest documenting the expected behavior Signed-off-by: Tarek Loubani <tarek@tarek.org>
|
Hi @tareko |
|
Review is planned for this week |
|
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
|
Please excuse the current delays in pull request reviews. |
|
still on our list. Review is not forgotten |
|
We are now trying to catch up with the pull request reviews. The PR is not forgotten and should be picked up soon. |
|
Apologies for the delay, i was out sick for a week and now try to catch up |
This commit contains the code from #6039 (thank you tareko!) as it needed to be combined with more fixes during it's review. PeerConnectionWrapper — native crash fixes: - Call peerConnection.close() before dataChannel.dispose() so the WebRTC signaling thread stops dispatching callbacks before native objects are freed - Call peerConnection.close() outside the synchronized lock; holding the lock deadlocks because close() blocks waiting for the signaling thread, which itself needs the lock to run its callbacks - Null out peerConnection before calling close() so in-flight callbacks see null and return early instead of NPE-ing on peerConnection.hashCode() in onIceConnectionChange, onCreateFailure, and onSetFailure - Call dataChannel.unregisterObserver() before dispose() in both removePeerConnection() and onDataChannel() to prevent the native observer from calling back into a disposed Java DataChannel object LocalStateBroadcasterNoMcu — initial mute state not sent to peers: - IceConnectionStateObserver.job was never started, so local audio/video/ speaking state was never sent to newly connected participants; only a manual mute+unmute triggered a broadcast - handleCallParticipantAdded now accepts the live StateFlow<ParticipantUiState> and uses first { it.isConnected } to send initial state exactly once when ICE connects; base class gets a concrete StateFlow overload that defaults to the existing snapshot path so MCU behaviour is unchanged - Fix ParticipantHandler initial isConnected = false (was true), which caused retrying when ICE actually connected ParticipantHandler — guest audio not detected (cherry-pick of PR #6039): - handleStreamChange() now sets isAudioEnabled from audio track presence, not only isStreamEnabled from video tracks; guests whose DataChannel never opens were permanently shown as muted despite having an active audio track - handleIceConnectionStateChange() preserves audio/video state during ICE NEW/CHECKING if tracks are still present, rather than resetting to false unconditionally and relying on a DataChannel message to restore it - Add GuestAudioDetectionTest and diagnostic logging AI-assistant: Claude Code v2.1.142 (Claude Sonnet 4.6) Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
|
Thank you @tareko ! During the review i encountered other bugs/crashes and in the end i ended up with another branch where I've incorporated your changes. See #6261 Thank you very much for your good contributions and please excuse the long delay for reviews! We will try to improve in this regard! |
This commit contains the code from #6039 (thank you tareko!) as it needed to be combined with more fixes during it's review. PeerConnectionWrapper — native crash fixes: - Call peerConnection.close() before dataChannel.dispose() so the WebRTC signaling thread stops dispatching callbacks before native objects are freed - Call peerConnection.close() outside the synchronized lock; holding the lock deadlocks because close() blocks waiting for the signaling thread, which itself needs the lock to run its callbacks - Null out peerConnection before calling close() so in-flight callbacks see null and return early instead of NPE-ing on peerConnection.hashCode() in onIceConnectionChange, onCreateFailure, and onSetFailure - Call dataChannel.unregisterObserver() before dispose() in both removePeerConnection() and onDataChannel() to prevent the native observer from calling back into a disposed Java DataChannel object LocalStateBroadcasterNoMcu — initial mute state not sent to peers: - IceConnectionStateObserver.job was never started, so local audio/video/ speaking state was never sent to newly connected participants; only a manual mute+unmute triggered a broadcast - handleCallParticipantAdded now accepts the live StateFlow<ParticipantUiState> and uses first { it.isConnected } to send initial state exactly once when ICE connects; base class gets a concrete StateFlow overload that defaults to the existing snapshot path so MCU behaviour is unchanged - Fix ParticipantHandler initial isConnected = false (was true), which caused retrying when ICE actually connected ParticipantHandler — guest audio not detected (cherry-pick of PR #6039): - handleStreamChange() now sets isAudioEnabled from audio track presence, not only isStreamEnabled from video tracks; guests whose DataChannel never opens were permanently shown as muted despite having an active audio track - handleIceConnectionStateChange() preserves audio/video state during ICE NEW/CHECKING if tracks are still present, rather than resetting to false unconditionally and relying on a DataChannel message to restore it - Add GuestAudioDetectionTest and diagnostic logging AI-assistant: Claude Code v2.1.142 (Claude Sonnet 4.6) Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Guest users whose DataChannel never establishes would have isAudioEnabled stay false even though audio tracks exist in the MediaStream. This caused guests to appear as 'connecting' with no audio on mobile while working on desktop.
This PR resolves issue #6037 . The debugging and code was done with the help of OpenCode using GLM-5.1 and Qwen-3.6 Plus.
🏁 Checklist
/backport to stable-xx.x