flutter-webrtc / dart-sip-ua

A dart-lang version of the SIP UA stack.
MIT License
338 stars 262 forks source link

Speakerphone Defaults to On in iOS (Workaround found) #259

Open Ant-Pinto opened 2 years ago

Ant-Pinto commented 2 years ago

Describe the bug

When starting a call in iOS, around 98% of the time the call would start in speakerphone even when the enableSpeakerphone(false) function was called as it is in the example. This does not seem to be an issue with the actual native code of enabling or disabling the speakerphone, as this function does work when you call it manually on a button. The issue is specifically happening when attempting to set the device speakerphone to off as a call starts.

Reason for bug?

It seems like this bug may be due to some kind of race condition or somewhere in the code is not awaiting for the call to actually connect before setting the speakerphone value. In the example, it's being called in the callStateChanged function when a stream state is received, maybe once we receive the stream we need to wait for some connection to happen first? The reason I think this is shown in the temporary workaround I put together.

Temporary Workaround

Due to what seemed like a race condition with toggling the speaker executing too early, i used a Future.delayed to ensure the call was connected before triggering the speaker toggle function.

Highly simplified version of whats working:

  @override
  void callStateChanged(Call call, CallState state) {
    switch (state.state) {
      case CallStateEnum.STREAM:
        Future.delayed(Duration(seconds: 1), () {
          _localStream!.getAudioTracks()[0].enableSpeakerphone(_speakerOn);
        });
        break;

This allows the call to connect properly before trying to set the value and makes the speakerphone set to off consistently.

To Reproduce

In the example: https://github.com/flutter-webrtc/dart-sip-ua/blob/5758d2f65bf4ce823bab2fe4ecc38070c7003a8c/example/lib/src/callscreen.dart#L127-L129

  1. Start a call via a physical iOS device where you have set enableSpeakerphone to false
  2. It should start ringing, but it will be on speakerphone
  3. Toggling speakerphone on and off manually after on the call should work fine

Expected behavior

The call will have the audio come from the earpiece instead of speakerphone

System Infomation()

Flutter SDK Version: 2.5.3 Target OS and Version: iOS 12+ & Android Sdk min21 target30+ Host OS and Version: macOS 12.0.1 Apple Silicon Running on Physical device: iPhone 13 Pro

a42279395 commented 2 years ago

你好,第一次通话时遇到超时问题吗? flutter: \^[[38;5;196m[2022-04-07 14:58:14.484] Level.error rtc_session.dart:1416 ::: onRequestTimeout()<…> flutter: [2022-04-07 14:58:14.493] Level.debug rtc_session.dart:720 ::: terminate() flutter: [2022-04-07 14:58:14.496] Level.debug rtc_session.dart:745 ::: canceling session flutter: [2022-04-07 14:58:14.500] Level.debug rtc_session.dart:2966 ::: session failed flutter: [2022-04-07 14:58:14.502] Level.debug rtc_session.dart:2969 ::: emit "_failed" flutter: [2022-04-07 14:58:14.508] Level.debug rtc_session.dart:1483 ::: close() flutter: [2022-04-07 14:58:14.512] Level.debug rtc_session.dart:2980 ::: emit "failed" flutter: [2022-04-07 14:58:14.516] Level.debug sip_ua_helper.dart:214 ::: call failed with cause: Code: [408], Cause: Canceled, Reason: SIP ;cause=408 ;text="Request Timeout"

jackeychina commented 2 years ago

Any solution for this ?

jackeychina commented 2 years ago

@Ant-Pinto Tried your code Future.delayed(Duration(seconds: 1), () { _localStream!.getAudioTracks()[0].enableSpeakerphone(false); }); but not working.

I have flutter SDK version 2.5.0

EduardoAlberti commented 1 year ago

check this for more info https://github.com/flutter-webrtc/flutter-webrtc/issues/1290#issuecomment-1527925363

EliasBarrera commented 1 year ago

I have this error with the package sip_ua: ^0.5.8, any solution ?

berger89 commented 1 year ago

We have the same problem of not being able to switch to the earpiece on iOS. We have created a fork of the flutter-webrtc lib and changed the config.mode to AVAudioSessionModeVoiceChat (in AudioUtils.m). Nevertheless, the output via the speakers remains. Only with the addition of @Ant-Pinto workaround with the delay we were able to set the output to the earpiece.

@cloudwebrtc Do you have any idea where the problem with the possible race condition is?