mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Fix video crashes on changing layout.
- Make as readonly the isVideoEnabled from Camera and let it to do its work. - Use deactivateCamera to temporary deactivate it (preveiw aswell). - Check audio only from callModel video layout. - Deactivate Camera Sticker when changing layout. - Temporize layout changes in order to let time to Qt to shutdown its objects, and to let the SDK to not use/reuse deleted Qt objects. - Dynamic load some items on Sticker only if needed. - Forbid to change layout if previous change has not been done. - Remove old clean layout functions.
This commit is contained in:
parent
149fe9ea8e
commit
c870daf530
9 changed files with 172 additions and 87 deletions
|
|
@ -44,6 +44,7 @@ int Camera::mPreviewCounter;
|
|||
|
||||
// =============================================================================
|
||||
Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
|
||||
qDebug() << "[Camera] Camera constructor" << this;
|
||||
updateWindowIdLocation();
|
||||
setTextureFollowsItemSize(true);
|
||||
// The fbo content must be y-mirrored because the ms rendering is y-inverted.
|
||||
|
|
@ -66,9 +67,11 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
|
|||
|
||||
Camera::~Camera(){
|
||||
qDebug() << "[Camera] Camera destructor" << this;
|
||||
mRefreshTimer->stop();
|
||||
|
||||
if(mIsPreview)
|
||||
deactivatePreview();
|
||||
setWindowIdLocation(None);
|
||||
setWindowIdLocation(None);// We need to remove the Qt Buffer from SDK ot avoid to reuse it.
|
||||
}
|
||||
|
||||
void Camera::resetWindowId() const{
|
||||
|
|
@ -157,8 +160,6 @@ void Camera::removeParticipantDeviceModel(){
|
|||
}
|
||||
|
||||
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
|
||||
resetWindowId();
|
||||
|
||||
QQuickFramebufferObject::Renderer * renderer = NULL;
|
||||
if(mWindowIdLocation == CorePreview){
|
||||
qDebug() << "[Camera] Setting Camera to Preview";
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ Item {
|
|||
property bool isFullscreen: false
|
||||
property bool hideCamera: false
|
||||
property bool isPaused: false
|
||||
property bool deactivateCamera: false
|
||||
property bool deactivateCamera: true
|
||||
property bool isVideoEnabled: !deactivateCamera && (!callModel || callModel.videoEnabled)
|
||||
&& (!container.currentDevice || callModel && (container.currentDevice
|
||||
&& (container.currentDevice.videoEnabled || (container.currentDevice.isMe && callModel.cameraEnabled))))
|
||||
&& (!container.currentDevice || ( callModel && container.currentDevice &&
|
||||
( (!container.currentDevice.isMe && container.currentDevice.videoEnabled)
|
||||
|| (container.currentDevice.isMe && callModel.cameraEnabled))))
|
||||
|
||||
property bool a : callModel && callModel.videoEnabled
|
||||
property bool b: container.currentDevice && container.currentDevice.videoEnabled
|
||||
|
|
@ -51,6 +52,10 @@ Item {
|
|||
anchors.fill: parent
|
||||
|
||||
active: !resetActive && container.isVideoEnabled
|
||||
onActiveChanged: {
|
||||
console.log("QML Camera status : " + active)
|
||||
}
|
||||
|
||||
sourceComponent: container.isVideoEnabled && !container.isPaused? camera : null
|
||||
|
||||
Timer{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,14 @@ Rectangle{
|
|||
onVisibleChanged: if(!visible && contentsStack.nViews > 1) {
|
||||
contentsStack.pop()
|
||||
}
|
||||
property bool _activateCamera: false
|
||||
Connections{// Enable camera only when status is ok
|
||||
target: mainItem.callModel
|
||||
onStatusChanged: if( mainItem._activateCamera && (status == LinphoneEnums.CallStatusConnected || status == LinphoneEnums.CallStatusIdle)){
|
||||
camera._activateCamera = false
|
||||
callModel.cameraEnabled = true
|
||||
}
|
||||
}
|
||||
ButtonGroup{id: modeGroup}
|
||||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
|
|
@ -227,6 +235,7 @@ Rectangle{
|
|||
bottomWidth: IncallMenuStyle.list.border.width
|
||||
Layout.preferredHeight: Math.max(layoutIcon.height, radio.contentItem.implicitHeight) + 20
|
||||
Layout.fillWidth: true
|
||||
enabled: mainItem.callModel && !mainItem.callModel.updating
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
|
||||
|
|
@ -238,37 +247,16 @@ Rectangle{
|
|||
Layout.alignment: Qt.AlignVCenter
|
||||
ButtonGroup.group: modeGroup
|
||||
text: modelData.text
|
||||
|
||||
property bool isInternallyChecked: mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout)
|
||||
|| (!mainItem.callModel.localVideoEnabled && modelData.value == LinphoneEnums.ConferenceLayoutAudioOnly)
|
||||
: false
|
||||
// break bind. Radiobutton checked itself without taking care of custom binding. This workaound works as long as we don't really need the binding.
|
||||
onIsInternallyCheckedChanged: checked = isInternallyChecked
|
||||
Component.onCompleted: checked = isInternallyChecked
|
||||
Timer{
|
||||
id: changingLayoutDelay
|
||||
interval: 100
|
||||
onTriggered: {if(modelData.value == 2) mainItem.callModel.videoEnabled = false
|
||||
else {
|
||||
mainItem.callModel.conferenceVideoLayout = modelData.value
|
||||
mainItem.callModel.videoEnabled = true
|
||||
}
|
||||
mainItem.enabled = true
|
||||
}
|
||||
}
|
||||
onClicked:{
|
||||
// Do changes only if we choose a different layout.
|
||||
if(! ( mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout)
|
||||
|| (!mainItem.callModel.localVideoEnabled && modelData.value == LinphoneEnums.ConferenceLayoutAudioOnly)
|
||||
: false)){
|
||||
mainItem.enabled = false
|
||||
mainItem.layoutChanging(modelData.value)// Let time to clear cameras
|
||||
changingLayoutDelay.start()
|
||||
}
|
||||
}
|
||||
onClicked: mainItem.layoutChanging(modelData.value)
|
||||
}
|
||||
Icon{
|
||||
id: layoutIcon
|
||||
id: layoutIcon
|
||||
Layout.minimumWidth: iconWidth
|
||||
Layout.rightMargin: 10
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
|
|
|||
|
|
@ -101,15 +101,20 @@ Item{
|
|||
color: "#80000000"
|
||||
source: usernameItem
|
||||
}
|
||||
ActionButton{
|
||||
visible: mainItem._showCloseButton && mainItem._isPreview && mainItem._callModel && mainItem._callModel.videoEnabled
|
||||
Loader{
|
||||
id: closeLoader
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: 5
|
||||
anchors.topMargin: 5
|
||||
isCustom: true
|
||||
colorSet: DecorationStickerStyle.closePreview
|
||||
onClicked: mainItem.closeRequested()
|
||||
active: mainItem._showCloseButton && mainItem._isPreview && mainItem._callModel && mainItem._callModel.videoEnabled
|
||||
sourceComponent: Component{
|
||||
ActionButton{
|
||||
isCustom: true
|
||||
colorSet: DecorationStickerStyle.closePreview
|
||||
onClicked: mainItem.closeRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout{
|
||||
anchors.top: parent.top
|
||||
|
|
@ -137,17 +142,22 @@ Item{
|
|||
iconSize: DecorationStickerStyle.isMuted.button.iconSize
|
||||
}
|
||||
}
|
||||
BusyIndicator{// Joining spinner
|
||||
Loader{
|
||||
id: busyLoader
|
||||
property bool delayed : false
|
||||
Layout.preferredHeight: 20
|
||||
Layout.preferredWidth: 20
|
||||
property bool delayed : false
|
||||
visible: delayed && mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting)
|
||||
Timer{// Delay starting spinner (Qt bug)
|
||||
id: indicatorDelay
|
||||
interval: 100
|
||||
onTriggered: parent.delayed = true
|
||||
active: delayed && mainItem._currentDevice && (mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateScheduledForJoining || mainItem._currentDevice.state == LinphoneEnums.ParticipantDeviceStateAlerting)
|
||||
sourceComponent: Component{
|
||||
BusyIndicator{// Joining spinner
|
||||
Timer{// Delay starting spinner (Qt bug)
|
||||
id: indicatorDelay
|
||||
interval: 100
|
||||
onTriggered: busyLoader.delayed = true
|
||||
}
|
||||
Component.onCompleted: indicatorDelay.start()
|
||||
}
|
||||
}
|
||||
Component.onCompleted: indicatorDelay.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Item{
|
|||
property alias showActiveSpeakerOverlay: camera.showActiveSpeakerOverlay
|
||||
property alias isCameraFromDevice: camera.isCameraFromDevice
|
||||
property alias deactivateCamera: camera.deactivateCamera
|
||||
property alias isVideoEnabled: camera.isVideoEnabled
|
||||
readonly property alias isVideoEnabled: camera.isVideoEnabled
|
||||
|
||||
property alias image: avatar.image
|
||||
property alias avatarBackgroundColor: avatar.avatarBackgroundColor
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Rectangle {
|
|||
property bool cameraIsReady : false
|
||||
property bool previewIsReady : false
|
||||
property bool isFullScreen: false // Use this variable to test if we are in fullscreen. Do not test _fullscreen : we need to clean memory before having the window (see .js file)
|
||||
property bool layoutChanging: false
|
||||
|
||||
property var _fullscreen: null
|
||||
on_FullscreenChanged: if( !_fullscreen) isFullScreen = false
|
||||
|
|
@ -40,7 +41,7 @@ Rectangle {
|
|||
: conferenceLayout.item ? conferenceLayout.item.participantCount : 2
|
||||
|
||||
// States
|
||||
property bool isAudioOnly: callModel && callModel.isConference && conferenceLayout.sourceComponent == gridComponent && !callModel.videoEnabled
|
||||
property bool isAudioOnly: callModel && callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutAudioOnly
|
||||
property bool isReady : mainItem.callModel
|
||||
&& (!mainItem.callModel.isConference
|
||||
|| (mainItem.conferenceModel && mainItem.conferenceModel.isReady)
|
||||
|
|
@ -308,7 +309,7 @@ Rectangle {
|
|||
Layout.leftMargin: 70
|
||||
Layout.rightMargin: rightMenu.visible ? 15 : 70
|
||||
callModel: mainItem.callModel
|
||||
cameraEnabled: !mainItem.isFullScreen
|
||||
cameraEnabled: !mainItem.isFullScreen && !mainItem.layoutChanging
|
||||
}
|
||||
}
|
||||
Component{
|
||||
|
|
@ -318,7 +319,7 @@ Rectangle {
|
|||
callModel: mainItem.callModel
|
||||
isRightReducedLayout: rightMenu.visible
|
||||
isLeftReducedLayout: mainItem.listCallsOpened
|
||||
cameraEnabled: !mainItem.isFullScreen
|
||||
cameraEnabled: !mainItem.isFullScreen && !mainItem.layoutChanging
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
|
|
@ -328,12 +329,50 @@ Rectangle {
|
|||
Layout.fillWidth: true
|
||||
Loader{
|
||||
id: conferenceLayout
|
||||
anchors.fill: parent
|
||||
sourceComponent: mainItem.conferenceModel
|
||||
? mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker
|
||||
? activeSpeakerComponent
|
||||
: gridComponent
|
||||
: activeSpeakerComponent
|
||||
anchors.fill: parent
|
||||
|
||||
Timer{// Avoid Qt crashes when layout changes while videos are on
|
||||
id: layoutDelay
|
||||
interval: 100
|
||||
property int step : 0
|
||||
property var layoutMode
|
||||
onTriggered: {
|
||||
switch(step){
|
||||
case 2 : step = 0; mainItem.layoutChanging = false; break;
|
||||
case 1: ++step; conferenceLayout.sourceComponent = conferenceLayout.getLayout(); layoutDelay.restart(); break;
|
||||
case 0: if( mainItem.callModel.conferenceVideoLayout != layoutMode)
|
||||
mainItem.callModel.conferenceVideoLayout = layoutMode
|
||||
else {
|
||||
++step;
|
||||
layoutDelay.restart()
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
function begin(layoutMode){
|
||||
step = 0
|
||||
layoutDelay.layoutMode = layoutMode
|
||||
mainItem.layoutChanging = true
|
||||
layoutDelay.restart()
|
||||
}
|
||||
}
|
||||
function getLayout(){
|
||||
return mainItem.conferenceModel
|
||||
? mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker
|
||||
? activeSpeakerComponent
|
||||
: gridComponent
|
||||
: activeSpeakerComponent
|
||||
}
|
||||
|
||||
Connections{
|
||||
target: mainItem.callModel
|
||||
|
||||
onConferenceVideoLayoutChanged: {
|
||||
layoutDelay.layoutMode = mainItem.callModel.conferenceVideoLayout
|
||||
layoutDelay.restart()
|
||||
}
|
||||
}
|
||||
sourceComponent: getLayout()
|
||||
active: mainItem.callModel && !mainItem.isFullScreen
|
||||
}
|
||||
Rectangle{
|
||||
|
|
@ -342,12 +381,16 @@ Rectangle {
|
|||
visible: !mainItem.isReady
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
BusyIndicator{
|
||||
Loader{
|
||||
Layout.preferredHeight: 40
|
||||
Layout.preferredWidth: 40
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
running: parent.visible
|
||||
color: IncallStyle.buzyColor
|
||||
active: parent.visible
|
||||
sourceComponent: Component{
|
||||
BusyIndicator{
|
||||
color: IncallStyle.buzyColor
|
||||
}
|
||||
}
|
||||
}
|
||||
Text{
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
|
|
@ -370,8 +413,11 @@ Rectangle {
|
|||
callModel: mainItem.callModel
|
||||
conferenceModel: mainItem.conferenceModel
|
||||
visible: false
|
||||
enabled: !mainItem.layoutChanging
|
||||
onClose: rightMenu.visible = !rightMenu.visible
|
||||
onLayoutChanging: conferenceLayout.item.clearAll(layoutMode)
|
||||
onLayoutChanging: {
|
||||
layoutDelay.begin(layoutMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -487,14 +533,14 @@ Rectangle {
|
|||
isCustom: true
|
||||
backgroundRadius: 90
|
||||
colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff
|
||||
updating: callModel.videoEnabled && callModel.updating
|
||||
updating: callModel.videoEnabled && callModel.updating && !mainItem.layoutChanging
|
||||
property bool _activateCamera: false
|
||||
onClicked: if(callModel){
|
||||
onClicked: if(callModel && !mainItem.layoutChanging){
|
||||
if( callModel.isConference){// Only deactivate camera in conference.
|
||||
if(mainItem.isAudioOnly && SettingsModel.videoConferenceLayout != 2) {
|
||||
if(mainItem.isAudioOnly) {
|
||||
var layout = SettingsModel.videoConferenceLayout != LinphoneEnums.ConferenceLayoutAudioOnly ? SettingsModel.videoConferenceLayout : LinphoneEnums.ConferenceLayoutGrid
|
||||
layoutDelay.being(layout)
|
||||
camera._activateCamera = true
|
||||
conferenceLayout.item.clearAll(SettingsModel.videoConferenceLayout)
|
||||
callModel.conferenceVideoLayout = SettingsModel.videoConferenceLayout
|
||||
}else
|
||||
callModel.cameraEnabled = !callModel.cameraEnabled
|
||||
}else{// In one-one, we deactivate all videos.
|
||||
|
|
|
|||
|
|
@ -37,12 +37,6 @@ Item {
|
|||
onConferenceCreated: cameraView.resetCamera()
|
||||
}
|
||||
|
||||
function clearAll(layoutMode){
|
||||
if( layoutMode != LinphoneEnums.ConferenceLayoutActiveSpeaker){
|
||||
mainItem.cameraEnabled = false
|
||||
miniViews.model = []
|
||||
}
|
||||
}
|
||||
Sticker{
|
||||
id: cameraView
|
||||
anchors.fill: parent
|
||||
|
|
@ -54,7 +48,7 @@ Item {
|
|||
: callModel.isConference
|
||||
? allDevices.activeSpeaker
|
||||
: null
|
||||
deactivateCamera: isPreview && callModel.pausedByUser
|
||||
deactivateCamera: !mainItem.cameraEnabled || (isPreview && callModel.pausedByUser)
|
||||
? true
|
||||
: callModel.isConference
|
||||
? (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused) )
|
||||
|
|
@ -63,8 +57,6 @@ Item {
|
|||
|| !mainItem.isConferenceReady
|
||||
: (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused || !callModel.videoEnabled) )
|
||||
|| currentDevice && !currentDevice.videoEnabled
|
||||
|
||||
isVideoEnabled: !deactivateCamera
|
||||
isPreview: !preview.visible && mainItem.participantCount == 1
|
||||
onIsPreviewChanged: {cameraView.resetCamera() }
|
||||
isCameraFromDevice: isPreview
|
||||
|
|
@ -101,7 +93,7 @@ Item {
|
|||
sourceComponent:
|
||||
Sticker{
|
||||
id: previewSticker
|
||||
deactivateCamera: !mainItem.callModel || callModel.pausedByUser || !mainItem.callModel.cameraEnabled
|
||||
deactivateCamera: !mainItem.cameraEnabled || !mainItem.callModel || callModel.pausedByUser || !mainItem.callModel.cameraEnabled
|
||||
currentDevice: allDevices.me
|
||||
isPreview: true
|
||||
callModel: mainItem.callModel
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ Window {
|
|||
property ConferenceModel conferenceModel: callModel && callModel.conferenceModel
|
||||
property var _fullscreen: null
|
||||
property bool listCallsOpened: false
|
||||
property bool layoutChanging: false
|
||||
|
||||
property bool isAudioOnly: callModel && callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutAudioOnly
|
||||
|
||||
signal openListCallsRequest()
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -238,7 +241,7 @@ Window {
|
|||
isCustom: true
|
||||
backgroundRadius: width/2
|
||||
colorSet: IncallStyle.buttons.screenshot
|
||||
visible: SettingsModel.incallScreenshotEnabled && conference.callModel && (!conference.callModel.isConference || mainItem.callModel.snapshotEnabled)
|
||||
visible: SettingsModel.incallScreenshotEnabled && conference.callModel && (!conference.callModel.isConference || window.callModel.snapshotEnabled)
|
||||
onClicked: conference.callModel && conference.callModel.takeSnapshot()
|
||||
//: 'Take Snapshot' : Tooltip for takking snapshot.
|
||||
tooltipText: qsTr('incallSnapshotTooltip')
|
||||
|
|
@ -279,6 +282,7 @@ Window {
|
|||
Layout.leftMargin: window.hideButtons ? 15 : 70
|
||||
Layout.rightMargin: rightMenu.visible ? 15 : 70
|
||||
callModel: conference.callModel
|
||||
cameraEnabled: !conference.layoutChanging
|
||||
}
|
||||
}
|
||||
Component{
|
||||
|
|
@ -286,6 +290,7 @@ Window {
|
|||
IncallActiveSpeaker{
|
||||
id: activeSpeaker
|
||||
callModel: conference.callModel
|
||||
cameraEnabled: !conference.layoutChanging
|
||||
isRightReducedLayout: rightMenu.visible
|
||||
isLeftReducedLayout: conference.listCallsOpened
|
||||
}
|
||||
|
|
@ -297,13 +302,48 @@ Window {
|
|||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
sourceComponent: conference.callModel
|
||||
? conference.conferenceModel
|
||||
? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker
|
||||
? activeSpeakerComponent
|
||||
: gridComponent
|
||||
: activeSpeakerComponent
|
||||
: null
|
||||
Timer{// Avoid Qt crashes when layout changes while videos are on
|
||||
id: layoutDelay
|
||||
interval: 100
|
||||
property int step : 0
|
||||
property var layoutMode
|
||||
onTriggered: {
|
||||
switch(step){
|
||||
case 2 : step = 0; conference.layoutChanging = false; break;
|
||||
case 1: ++step; conferenceLayout.sourceComponent = conferenceLayout.getLayout(); layoutDelay.restart(); break;
|
||||
case 0: if( conference.callModel.conferenceVideoLayout != layoutMode)
|
||||
conference.callModel.conferenceVideoLayout = layoutMode
|
||||
else {
|
||||
++step;
|
||||
layoutDelay.restart()
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
function begin(layoutMode){
|
||||
step = 0
|
||||
layoutDelay.layoutMode = layoutMode
|
||||
conference.layoutChanging = true
|
||||
layoutDelay.restart()
|
||||
}
|
||||
}
|
||||
function getLayout(){
|
||||
return conference.conferenceModel
|
||||
? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutActiveSpeaker
|
||||
? activeSpeakerComponent
|
||||
: gridComponent
|
||||
: activeSpeakerComponent
|
||||
}
|
||||
|
||||
Connections{
|
||||
target: conference.callModel
|
||||
|
||||
onConferenceVideoLayoutChanged: {
|
||||
layoutDelay.layoutMode = conference.callModel.conferenceVideoLayout
|
||||
layoutDelay.restart()
|
||||
}
|
||||
}
|
||||
sourceComponent: getLayout()
|
||||
active: conference.callModel
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
|
@ -332,6 +372,9 @@ Window {
|
|||
conferenceModel: conference.conferenceModel
|
||||
visible: false
|
||||
onClose: rightMenu.visible = !rightMenu.visible
|
||||
onLayoutChanging: {
|
||||
layoutDelay.begin(layoutMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -450,8 +493,14 @@ Window {
|
|||
backgroundRadius: 90
|
||||
colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff
|
||||
updating: callModel && callModel.videoEnabled && callModel.updating
|
||||
enabled: callModel && callModel.videoEnabled
|
||||
onClicked: if(callModel) callModel.cameraEnabled = !callModel.cameraEnabled
|
||||
onClicked: if(callModel && !conference.layoutChanging){
|
||||
if( callModel.isConference){// Only deactivate camera in conference.
|
||||
callModel.cameraEnabled = !callModel.cameraEnabled
|
||||
}else{// In one-one, we deactivate all videos.
|
||||
if(callModel.videoEnabled ) Qt.callLater(function(){window.exit()})
|
||||
callModel.videoEnabled = !callModel.videoEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
|
|
|
|||
|
|
@ -27,12 +27,6 @@ Mosaic {
|
|||
|
||||
// On grid view, we limit the quality if there are enough participants// The vga mode has been activated from the factory rc
|
||||
//onParticipantCountChanged: participantCount > ConstantsCpp.maxMosaicParticipants ? SettingsModel.setLimitedMosaicQuality() : SettingsModel.setHighMosaicQuality()
|
||||
function clearAll(layoutMode){
|
||||
if( layoutMode != 2 && layoutMode != LinphoneEnums.ConferenceLayoutGrid){
|
||||
clear()
|
||||
gridModel.model = []
|
||||
}
|
||||
}
|
||||
delegateModel: DelegateModel{
|
||||
id: gridModel
|
||||
property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue