diff --git a/Classes/DevicesListView.m b/Classes/DevicesListView.m index 60e005dc9..5238673f2 100644 --- a/Classes/DevicesListView.m +++ b/Classes/DevicesListView.m @@ -151,7 +151,7 @@ static UICompositeViewDescription *compositeDescription = nil; [_tableView reloadData]; } else { const LinphoneAddress *addr = linphone_participant_device_get_address(entry->device); - [CallManager.instance startCallWithAddr:(LinphoneAddress *)addr isSas:TRUE]; + [CallManager.instance startCallWithAddr:(LinphoneAddress *)addr isSas:TRUE isVideo:false isConference:false]; } } else { bctbx_list_t *devices = linphone_participant_get_devices(entry->participant); diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index afcd795e0..a6821ad70 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -1862,7 +1862,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) { } [self checkLocalNetworkPermission]; // For OutgoingCall, show CallOutgoingView - [CallManager.instance startCallWithAddr:iaddr isSas:FALSE]; + [CallManager.instance startCallWithAddr:iaddr isSas:FALSE isVideo:false isConference:false]; } #pragma mark - Misc Functions diff --git a/Classes/PhoneMainView.m b/Classes/PhoneMainView.m index 49f6aa3f8..1d3393bd6 100644 --- a/Classes/PhoneMainView.m +++ b/Classes/PhoneMainView.m @@ -378,9 +378,12 @@ static RootViewManager *rootViewManagerInstance = nil; case LinphoneCallOutgoingEarlyMedia: case LinphoneCallOutgoingProgress: case LinphoneCallOutgoingRinging: { - OutgoingCallView *v = VIEW(OutgoingCallView); - [self changeCurrentView:OutgoingCallView.compositeViewDescription]; - [v setCallWithCall:call]; + CallAppData *data = [CallManager getAppDataWithCall:call]; + if (!data.isConference) { + OutgoingCallView *v = VIEW(OutgoingCallView); + [self changeCurrentView:OutgoingCallView.compositeViewDescription]; + [v setCallWithCall:call]; + } break; } case LinphoneCallPausedByRemote: diff --git a/Classes/Swift/CallManager.swift b/Classes/Swift/CallManager.swift index ef52ebe34..7d3a0eec4 100644 --- a/Classes/Swift/CallManager.swift +++ b/Classes/Swift/CallManager.swift @@ -27,6 +27,8 @@ import AVFoundation @objc class CallAppData: NSObject { @objc var batteryWarningShown = false @objc var videoRequested = false /*set when user has requested for video*/ + @objc var isConference = true + } /* @@ -207,7 +209,7 @@ import AVFoundation } // for outgoing call. There is not yet callId - @objc func startCall(addr: OpaquePointer?, isSas: Bool) { + @objc func startCall(addr: OpaquePointer?, isSas: Bool, isVideo: Bool, isConference: Bool = false) { if (addr == nil) { print("Can not start a call with null address!") return @@ -221,27 +223,27 @@ import AVFoundation let startCallAction = CXStartCallAction(call: uuid, handle: handle) let transaction = CXTransaction(action: startCallAction) - let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas, displayName: name) + let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas, displayName: name, isVideo: isVideo, isConference:isConference) providerDelegate.callInfos.updateValue(callInfo, forKey: uuid) providerDelegate.uuids.updateValue(uuid, forKey: "") setHeldOtherCalls(exceptCallid: "") requestTransaction(transaction, action: "startCall") }else { - try? doCall(addr: sAddr, isSas: isSas) + try? doCall(addr: sAddr, isSas: isSas, isVideo:isVideo, isConference:isConference) } } - func startCall(addr:String, isSas: Bool = false) { + func startCall(addr:String, isSas: Bool = false, isVideo: Bool, isConference: Bool = false) { do { let address = try Factory.Instance.createAddress(addr: addr) - startCall(addr: address.getCobject,isSas: isSas) + startCall(addr: address.getCobject,isSas: isSas, isVideo: isVideo, isConference:isConference) } catch { Log.e("[CallManager] unable to create address for a new outgoing call : \(addr) \(error) ") } } - func doCall(addr: Address, isSas: Bool) throws { + func doCall(addr: Address, isSas: Bool, isVideo: Bool, isConference:Bool = false) throws { let displayName = FastAddressBook.displayName(for: addr.getCobject) let lcallParams = try CallManager.instance().core!.createCallParams(call: nil) @@ -270,6 +272,13 @@ import AVFoundation if (isSas) { lcallParams.mediaEncryption = .ZRTP } + if (isConference) { + lcallParams.videoEnabled = true + lcallParams.videoDirection = isVideo ? .SendRecv : .RecvOnly + } else { + lcallParams.videoEnabled = isVideo + } + let call = CallManager.instance().core!.inviteAddressWithParams(addr: addr, params: lcallParams) if (call != nil) { // The LinphoneCallAppData object should be set on call creation with callback @@ -280,6 +289,7 @@ import AVFoundation Log.directLog(BCTBX_LOG_ERROR, text: "New call instanciated but app data was not set. Expect it to crash.") /* will be used later to notify user if video was not activated because of the linphone core*/ } else { + data!.isConference = isConference data!.videoRequested = lcallParams.videoEnabled CallManager.setAppData(sCall: call!, appData: data) } diff --git a/Classes/Swift/Conference/views/ConferenceWaitingRoomFragment.swift b/Classes/Swift/Conference/views/ConferenceWaitingRoomFragment.swift index 690338032..ea3ba9852 100644 --- a/Classes/Swift/Conference/views/ConferenceWaitingRoomFragment.swift +++ b/Classes/Swift/Conference/views/ConferenceWaitingRoomFragment.swift @@ -84,7 +84,7 @@ import linphonesw } start.onClick { - self.conferenceUrl.map{ CallManager.instance().startCall(addr: $0, isSas: false) } + self.conferenceUrl.map{ CallManager.instance().startCall(addr: $0, isSas: false, isVideo: true, isConference: true) } } diff --git a/Classes/Swift/ProviderDelegate.swift b/Classes/Swift/ProviderDelegate.swift index 5f4ecd512..f3e1f4e96 100644 --- a/Classes/Swift/ProviderDelegate.swift +++ b/Classes/Swift/ProviderDelegate.swift @@ -32,6 +32,8 @@ import os var connected = false var reason: Reason = Reason.None var displayName: String? + var videoEnabled = false + var isConference = false static func newIncomingCallInfo(callId: String) -> CallInfo { let callInfo = CallInfo() @@ -39,12 +41,14 @@ import os return callInfo } - static func newOutgoingCallInfo(addr: Address, isSas: Bool, displayName: String) -> CallInfo { + static func newOutgoingCallInfo(addr: Address, isSas: Bool, displayName: String, isVideo: Bool, isConference:Bool) -> CallInfo { let callInfo = CallInfo() callInfo.isOutgoing = true callInfo.sasEnabled = isSas callInfo.toAddr = addr callInfo.displayName = displayName + callInfo.videoEnabled = isVideo + callInfo.isConference = isConference return callInfo } } @@ -252,7 +256,7 @@ extension ProviderDelegate: CXProviderDelegate { } CallManager.instance().core?.configureAudioSession() - try CallManager.instance().doCall(addr: addr!, isSas: callInfo?.sasEnabled ?? false) + try CallManager.instance().doCall(addr: addr!, isSas: callInfo?.sasEnabled ?? false, isVideo: callInfo?.videoEnabled ?? false, isConference: callInfo?.isConference ?? false) } catch { Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: Call started failed because \(error)") action.fail() diff --git a/Classes/Swift/Voip/Models/CallData.swift b/Classes/Swift/Voip/ViewModels/CallData.swift similarity index 98% rename from Classes/Swift/Voip/Models/CallData.swift rename to Classes/Swift/Voip/ViewModels/CallData.swift index 7d97fdec4..988c79729 100644 --- a/Classes/Swift/Voip/Models/CallData.swift +++ b/Classes/Swift/Voip/ViewModels/CallData.swift @@ -88,7 +88,7 @@ class CallData { isRemotelyPaused.value = isCallRemotelyPaused() canBePaused.value = canCallBePaused() let conference = call.conference - isInRemoteConference.value = conference != nil + isInRemoteConference.value = conference != nil || CallManager.getAppData(call: call.getCobject!)?.isConference == true if (conference != nil) { remoteConferenceSubject.value = conference?.subject != nil && (conference?.subject.count)! > 0 ? conference!.subject : VoipTexts.conference_default_title } diff --git a/Classes/Swift/Voip/Models/CallStatisticsData.swift b/Classes/Swift/Voip/ViewModels/CallStatisticsData.swift similarity index 100% rename from Classes/Swift/Voip/Models/CallStatisticsData.swift rename to Classes/Swift/Voip/ViewModels/CallStatisticsData.swift diff --git a/Classes/Swift/Voip/Models/CallsViewModel.swift b/Classes/Swift/Voip/ViewModels/CallsViewModel.swift similarity index 99% rename from Classes/Swift/Voip/Models/CallsViewModel.swift rename to Classes/Swift/Voip/ViewModels/CallsViewModel.swift index b68707700..294491b9e 100644 --- a/Classes/Swift/Voip/Models/CallsViewModel.swift +++ b/Classes/Swift/Voip/ViewModels/CallsViewModel.swift @@ -33,6 +33,7 @@ class CallsViewModel { let callConnectedEvent = MutableLiveData() let callUpdateEvent = MutableLiveData() let noMoreCallEvent = MutableLiveData(false) + var core : Core { get { Core.get() } } static let shared = CallsViewModel() diff --git a/Classes/Swift/Voip/Models/ConferenceParticipantData.swift b/Classes/Swift/Voip/ViewModels/ConferenceParticipantData.swift similarity index 100% rename from Classes/Swift/Voip/Models/ConferenceParticipantData.swift rename to Classes/Swift/Voip/ViewModels/ConferenceParticipantData.swift diff --git a/Classes/Swift/Voip/Models/ConferenceParticipantDeviceData.swift b/Classes/Swift/Voip/ViewModels/ConferenceParticipantDeviceData.swift similarity index 100% rename from Classes/Swift/Voip/Models/ConferenceParticipantDeviceData.swift rename to Classes/Swift/Voip/ViewModels/ConferenceParticipantDeviceData.swift diff --git a/Classes/Swift/Voip/Models/ConferenceViewModel.swift b/Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift similarity index 100% rename from Classes/Swift/Voip/Models/ConferenceViewModel.swift rename to Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift diff --git a/Classes/Swift/Voip/Models/ControlsViewModel.swift b/Classes/Swift/Voip/ViewModels/ControlsViewModel.swift similarity index 100% rename from Classes/Swift/Voip/Models/ControlsViewModel.swift rename to Classes/Swift/Voip/ViewModels/ControlsViewModel.swift diff --git a/Classes/Swift/Voip/Views/CompositeViewControllers/ActiveCallOrConferenceView.swift b/Classes/Swift/Voip/Views/CompositeViewControllers/ActiveCallOrConferenceView.swift index adb32ae1f..e75519c6f 100644 --- a/Classes/Swift/Voip/Views/CompositeViewControllers/ActiveCallOrConferenceView.swift +++ b/Classes/Swift/Voip/Views/CompositeViewControllers/ActiveCallOrConferenceView.swift @@ -33,6 +33,8 @@ import linphonesw var currentCallView : ActiveCallView? = nil var conferenceGridView: VoipConferenceGridView? = nil var conferenceActiveSpeakerView: VoipConferenceActiveSpeakerView? = nil + let conferenceJoinSpinner = RotatingSpinner() + let extraButtonsView = VoipExtraButtonsView() var numpadView : NumpadView? = nil @@ -128,6 +130,17 @@ import linphonesw } } + ConferenceViewModel.shared.conferenceCreationPending.readCurrentAndObserve { isCreationPending in + if (ConferenceViewModel.shared.conferenceExists.value == true && isCreationPending == true) { + fullScreenMutableContainerView.addSubview(self.conferenceJoinSpinner) + self.conferenceJoinSpinner.square(IncomingOutgoingCommonView.spinner_size).center().done() + self.conferenceJoinSpinner.startRotation() + } else { + self.conferenceJoinSpinner.removeFromSuperview() + self.conferenceJoinSpinner.stopRotation() + } + } + // Conference active speaker conferenceActiveSpeakerView = VoipConferenceActiveSpeakerView() fullScreenMutableContainerView.addSubview(conferenceActiveSpeakerView!)