forked from mirrors/linphone-iphone
Add audio only mode to conference call view
Enable FEC Fix active speaker video
This commit is contained in:
parent
5c5fd2ad8d
commit
f6e935c65f
5 changed files with 151 additions and 5 deletions
|
|
@ -111,6 +111,8 @@ final class CoreContext: ObservableObject {
|
|||
self.mCore.videoDisplayEnabled = true
|
||||
self.mCore.videoPreviewEnabled = false
|
||||
|
||||
self.mCore.fecEnabled = true
|
||||
|
||||
self.mCoreSuscriptions.insert(self.mCore.publisher?.onGlobalStateChanged?.postOnMainQueue { (cbVal: (core: Core, state: GlobalState, message: String)) in
|
||||
if cbVal.state == GlobalState.On {
|
||||
self.hasDefaultAccount = true
|
||||
|
|
|
|||
|
|
@ -40,4 +40,7 @@ version_check_url_root=https://www.linphone.org/releases
|
|||
max_calls=10
|
||||
conference_layout=1
|
||||
|
||||
[fec]
|
||||
fec_enabled=1
|
||||
|
||||
## End of default rc
|
||||
|
|
|
|||
|
|
@ -385,15 +385,25 @@ class TelecomManager: ObservableObject {
|
|||
if call.conference != nil {
|
||||
if call.conference!.activeSpeakerParticipantDevice != nil {
|
||||
let direction = call.conference?.activeSpeakerParticipantDevice!.getStreamCapability(streamType: StreamType.Video)
|
||||
self.remoteConfVideo = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly
|
||||
self.remoteConfVideo = direction == .SendRecv || direction == .SendOnly
|
||||
} else if call.conference!.participantList.first != nil
|
||||
&& call.conference!.participantList.first?.address != nil
|
||||
&& call.conference!.participantList.first!.address!.clone()!.equal(address2: (call.conference!.me?.address)!) {
|
||||
let direction = call.conference!.participantDeviceList.first!.getStreamCapability(streamType: StreamType.Video)
|
||||
self.remoteConfVideo = direction == .SendRecv || direction == .SendOnly
|
||||
} else if call.conference!.participantList.last != nil
|
||||
&& call.conference!.participantList.last?.address != nil {
|
||||
let direction = call.conference!.participantDeviceList.last!.getStreamCapability(streamType: StreamType.Video)
|
||||
self.remoteConfVideo = direction == .SendRecv || direction == .SendOnly
|
||||
} else {
|
||||
self.remoteConfVideo = true
|
||||
self.remoteConfVideo = false
|
||||
}
|
||||
|
||||
} else {
|
||||
self.remoteConfVideo = false
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.remoteConfVideo = call.currentParams!.videoEnabled && call.currentParams!.videoDirection == MediaDirection.SendRecv || call.currentParams!.videoDirection == MediaDirection.SendOnly
|
||||
self.remoteConfVideo = call.currentParams!.videoEnabled && call.currentParams!.videoDirection == .SendRecv || call.currentParams!.videoDirection == .SendOnly
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,6 +283,7 @@ struct CallView: View {
|
|||
VStack(spacing: 0) {
|
||||
Button(action: {
|
||||
optionsChangeLayout = 1
|
||||
callViewModel.toggleVideoMode(isAudioOnlyMode: false)
|
||||
changeLayoutSheet = false
|
||||
}, label: {
|
||||
HStack {
|
||||
|
|
@ -312,6 +313,7 @@ struct CallView: View {
|
|||
|
||||
Button(action: {
|
||||
optionsChangeLayout = 2
|
||||
callViewModel.toggleVideoMode(isAudioOnlyMode: false)
|
||||
changeLayoutSheet = false
|
||||
}, label: {
|
||||
HStack {
|
||||
|
|
@ -339,6 +341,10 @@ struct CallView: View {
|
|||
|
||||
Button(action: {
|
||||
optionsChangeLayout = 3
|
||||
if callViewModel.videoDisplayed {
|
||||
callViewModel.displayMyVideo()
|
||||
}
|
||||
callViewModel.toggleVideoMode(isAudioOnlyMode: true)
|
||||
changeLayoutSheet = false
|
||||
}, label: {
|
||||
HStack {
|
||||
|
|
@ -509,6 +515,10 @@ struct CallView: View {
|
|||
currentOffset = (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78)
|
||||
pointingUp = -(((currentOffset - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78)) / ((maxBottomSheetHeight * geometry.size.height) - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78))) - 0.5) * 2
|
||||
}
|
||||
.onChange(of: optionsChangeLayout) { optionsChangeLayoutValue in
|
||||
currentOffset = (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78)
|
||||
pointingUp = -(((currentOffset - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78)) / ((maxBottomSheetHeight * geometry.size.height) - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78))) - 0.5) * 2
|
||||
}
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
}
|
||||
|
|
@ -674,8 +684,11 @@ struct CallView: View {
|
|||
)
|
||||
}
|
||||
} else if callViewModel.isConference && !telecomManager.outgoingCallStarted && callViewModel.activeSpeakerParticipant != nil {
|
||||
let heightValue = (fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom : geometry.size.height - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78) - 40 - 20 + geometry.safeAreaInsets.bottom)
|
||||
if optionsChangeLayout == 1 && callViewModel.participantList.count <= 5 {
|
||||
mosaicMode(geometry: geometry, height: (fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom : geometry.size.height - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78) - 40 - 20 + geometry.safeAreaInsets.bottom))
|
||||
mosaicMode(geometry: geometry, height: heightValue)
|
||||
} else if optionsChangeLayout == 3 {
|
||||
audioOnlyMode(geometry: geometry, height: heightValue)
|
||||
} else {
|
||||
activeSpeakerMode(geometry: geometry)
|
||||
}
|
||||
|
|
@ -1645,6 +1658,103 @@ struct CallView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func audioOnlyMode(geometry: GeometryProxy, height: Double) -> some View {
|
||||
VStack {
|
||||
let layout = [
|
||||
GridItem(.fixed((geometry.size.width/2)-10)),
|
||||
GridItem(.fixed((geometry.size.width/2)-10))
|
||||
]
|
||||
ScrollView {
|
||||
LazyVGrid(columns: layout) {
|
||||
if callViewModel.myParticipantModel != nil {
|
||||
HStack {
|
||||
Avatar(contactAvatarModel: callViewModel.myParticipantModel!.avatarModel, avatarSize: 50, hidePresence: true)
|
||||
|
||||
Text(callViewModel.myParticipantModel!.name)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundStyle(Color.white)
|
||||
.default_text_style_500(styleSize: 14)
|
||||
.lineLimit(1)
|
||||
.padding(.horizontal, 10)
|
||||
|
||||
if callViewModel.myParticipantModel!.isMuted {
|
||||
HStack(alignment: .center) {
|
||||
Image("microphone-slash")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c800)
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(2)
|
||||
.background(.white)
|
||||
.cornerRadius(40)
|
||||
}
|
||||
|
||||
if callViewModel.myParticipantModel!.onPause {
|
||||
Image("pause")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 25, height: 25)
|
||||
}
|
||||
}
|
||||
.frame(height: 80)
|
||||
.padding(.all, 10)
|
||||
.background(Color.gray600)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(callViewModel.myParticipantModel!.isSpeaking ? .white : Color.gray600, lineWidth: 4)
|
||||
)
|
||||
.cornerRadius(20)
|
||||
}
|
||||
|
||||
ForEach(0..<callViewModel.participantList.count, id: \.self) { index in
|
||||
HStack {
|
||||
Avatar(contactAvatarModel: callViewModel.participantList[index].avatarModel, avatarSize: 50, hidePresence: true)
|
||||
|
||||
Text(callViewModel.participantList[index].name)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundStyle(Color.white)
|
||||
.default_text_style_500(styleSize: 14)
|
||||
.lineLimit(1)
|
||||
.padding(.horizontal, 10)
|
||||
|
||||
if callViewModel.participantList[index].isMuted {
|
||||
HStack(alignment: .center) {
|
||||
Image("microphone-slash")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c800)
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(2)
|
||||
.background(.white)
|
||||
.cornerRadius(40)
|
||||
}
|
||||
|
||||
if callViewModel.participantList[index].onPause {
|
||||
Image("pause")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 25, height: 25)
|
||||
}
|
||||
}
|
||||
.frame(height: 80)
|
||||
.padding(.all, 10)
|
||||
.background(Color.gray600)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(callViewModel.participantList[index].isSpeaking ? .white : Color.gray600, lineWidth: 4)
|
||||
)
|
||||
.cornerRadius(20)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: geometry.size.width, height: height)
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable function_body_length
|
||||
func bottomSheetContent(geo: GeometryProxy) -> some View {
|
||||
GeometryReader { _ in
|
||||
|
|
@ -1686,7 +1796,12 @@ struct CallView: View {
|
|||
Spacer()
|
||||
|
||||
Button {
|
||||
callViewModel.displayMyVideo()
|
||||
if optionsChangeLayout == 3 {
|
||||
optionsChangeLayout = 2
|
||||
callViewModel.toggleVideoMode(isAudioOnlyMode: false)
|
||||
} else {
|
||||
callViewModel.displayMyVideo()
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Image(callViewModel.videoDisplayed ? "video-camera" : "video-camera-slash")
|
||||
|
|
|
|||
|
|
@ -647,6 +647,22 @@ class CallViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func toggleVideoMode(isAudioOnlyMode: Bool) {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
if self.currentCall != nil {
|
||||
do {
|
||||
let params = try core.createCallParams(call: self.currentCall)
|
||||
|
||||
params.videoEnabled = !isAudioOnlyMode
|
||||
|
||||
try self.currentCall!.update(params: params)
|
||||
} catch {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func switchCamera() {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
let currentDevice = core.videoDevice
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue