From 50e398c6676239c7273da4ecd593a59502cfc5fa Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 23 Aug 2022 17:56:32 +0200 Subject: [PATCH] Fix camera/video activations when changing conference layout. Fix missing camera button in one-one when video has been deactivated. Test video enabled state on params instead of currentParams in order to know if we are in audio only mode. Add a loading page when conference is not ready or if we are alone in the conference in audio only mode. Remove outgoing call when calling a conference. Fix crash on shutdown. Fix closing window request after calling a conference from smart search bar. --- .../app/proxyModel/ProxyAbstractListModel.hpp | 8 +- .../app/proxyModel/ProxyAbstractMapModel.hpp | 6 +- .../app/proxyModel/ProxyAbstractObject.hpp | 1 + .../src/components/call/CallModel.cpp | 17 +++- .../src/components/call/CallModel.hpp | 3 + linphone-app/src/components/camera/Camera.cpp | 10 +++ linphone-app/src/components/camera/Camera.hpp | 2 + .../components/conference/ConferenceModel.cpp | 9 +++ .../components/conference/ConferenceModel.hpp | 6 ++ .../conference/ConferenceProxyModel.cpp | 2 +- .../ParticipantDeviceListModel.cpp | 44 +++++++---- .../ParticipantDeviceListModel.hpp | 5 +- .../ui/modules/Linphone/Camera/CameraItem.qml | 5 +- .../ui/modules/Linphone/Menus/IncallMenu.qml | 15 ++-- .../ui/views/App/Calls/CallsWindow.js | 26 ++++--- .../ui/views/App/Calls/CallsWindow.qml | 20 +++-- linphone-app/ui/views/App/Calls/Incall.qml | 77 +++++++++++-------- .../views/App/Calls/IncallActiveSpeaker.qml | 8 +- .../ui/views/App/Calls/WaitingRoom.qml | 8 +- 19 files changed, 183 insertions(+), 89 deletions(-) diff --git a/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp b/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp index 55e72b270..ee4162041 100644 --- a/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp @@ -33,7 +33,7 @@ public: ProxyAbstractListModel (QObject *parent = Q_NULLPTR) : ProxyAbstractObject(parent) {} virtual ~ProxyAbstractListModel(){ - resetData(); + clearData(); } virtual int rowCount (const QModelIndex &index = QModelIndex()) const override{ @@ -100,9 +100,13 @@ public: return true; } + virtual void clearData(){ + mList.clear(); + } + virtual void resetData(){ beginResetModel(); - mList.clear(); + clearData(); endResetModel(); } diff --git a/linphone-app/src/app/proxyModel/ProxyAbstractMapModel.hpp b/linphone-app/src/app/proxyModel/ProxyAbstractMapModel.hpp index 93ebb90ba..a22310b80 100644 --- a/linphone-app/src/app/proxyModel/ProxyAbstractMapModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyAbstractMapModel.hpp @@ -32,7 +32,7 @@ public: ProxyAbstractMapModel (QObject *parent = Q_NULLPTR) : ProxyAbstractObject(parent) {} virtual ~ProxyAbstractMapModel(){ - resetData(); + clearData(); } virtual int rowCount (const QModelIndex &index = QModelIndex()) const override{ @@ -58,10 +58,8 @@ public: return QVariant(); } - virtual void resetData() override{ - beginResetModel(); + virtual void clearData() override{ mMappedList.clear(); - endResetModel(); } protected: diff --git a/linphone-app/src/app/proxyModel/ProxyAbstractObject.hpp b/linphone-app/src/app/proxyModel/ProxyAbstractObject.hpp index fc7f0dd46..b2affa0c3 100644 --- a/linphone-app/src/app/proxyModel/ProxyAbstractObject.hpp +++ b/linphone-app/src/app/proxyModel/ProxyAbstractObject.hpp @@ -38,6 +38,7 @@ public: return rowCount(); } Q_INVOKABLE virtual bool remove(QObject *itemToRemove){return false;} + Q_INVOKABLE virtual void clearData(){} Q_INVOKABLE virtual void resetData(){} signals: diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index b19900a5f..c036f0971 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -237,7 +237,7 @@ QSharedPointer CallModel::getConferenceSharedModel(){ bool CallModel::isConference () const{ // Check status to avoid crash when requesting a conference on an ended call. - return Utils::coreStringToAppString(mCall->getRemoteAddress()->asString()).toLower().contains("conf-id") || (getStatus() != CallStatusEnded && mCall->getConference() != nullptr); + return mCall && (Utils::coreStringToAppString(mCall->getRemoteAddress()->asString()).toLower().contains("conf-id") || (getStatus() != CallStatusEnded && mCall->getConference() != nullptr)); } // ----------------------------------------------------------------------------- @@ -471,6 +471,7 @@ void CallModel::handleCallStateChanged (const shared_ptr &call, break; case linphone::Call::State::StreamsRunning: { + if (!mWasConnected && CoreManager::getInstance()->getSettingsModel()->getAutomaticallyRecordCalls()) { startRecording(); mWasConnected = true; @@ -480,7 +481,7 @@ void CallModel::handleCallStateChanged (const shared_ptr &call, setCallId(QString::fromStdString(mCall->getCallLog()->getCallId())); break; } - case linphone::Call::State::Connected: + case linphone::Call::State::Connected: getConferenceSharedModel(); case linphone::Call::State::Referred: case linphone::Call::State::Released: mPausedByRemote = false; @@ -749,8 +750,8 @@ void CallModel::setCameraEnabled (bool status){ return; shared_ptr params = core->createCallParams(mCall); - params->setVideoDirection(status ? linphone::MediaDirection::SendRecv : linphone::MediaDirection::RecvOnly); params->enableVideo(true); + params->setVideoDirection(status ? linphone::MediaDirection::SendRecv : linphone::MediaDirection::RecvOnly); mCall->update(params); } } @@ -788,6 +789,14 @@ bool CallModel::getRemoteVideoEnabled () const { return params && params->videoEnabled(); } +bool CallModel::getLocalVideoEnabled () const { + if(mCall){ + shared_ptr params = mCall->getParams(); + return params && params->videoEnabled(); + }else + return true; +} + bool CallModel::getVideoEnabled () const { if(mCall){ shared_ptr params = mCall->getCurrentParams(); @@ -979,7 +988,7 @@ std::shared_ptr CallModel::getRemoteAddress()const{ } LinphoneEnums::ConferenceLayout CallModel::getConferenceVideoLayout() const{ - return LinphoneEnums::fromLinphone(mCall->getParams()->getConferenceVideoLayout()); + return mCall ? LinphoneEnums::fromLinphone(mCall->getParams()->getConferenceVideoLayout()) : LinphoneEnums::ConferenceLayoutGrid; } void CallModel::changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout){ diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp index 3662a02f2..991a10b1e 100644 --- a/linphone-app/src/components/call/CallModel.hpp +++ b/linphone-app/src/components/call/CallModel.hpp @@ -70,6 +70,7 @@ class CallModel : public QObject { Q_PROPERTY(bool pausedByUser READ getPausedByUser WRITE setPausedByUser NOTIFY statusChanged) Q_PROPERTY(bool videoEnabled READ getVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged) + Q_PROPERTY(bool localVideoEnabled READ getLocalVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged) Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE setCameraEnabled NOTIFY statusChanged) Q_PROPERTY(bool updating READ getUpdating NOTIFY statusChanged) @@ -264,6 +265,8 @@ public: bool getPausedByUser () const; void setPausedByUser (bool status); + bool getLocalVideoEnabled () const; + bool getVideoEnabled () const; void setVideoEnabled (bool status); diff --git a/linphone-app/src/components/camera/Camera.cpp b/linphone-app/src/components/camera/Camera.cpp index f4369b510..b5935ebef 100644 --- a/linphone-app/src/components/camera/Camera.cpp +++ b/linphone-app/src/components/camera/Camera.cpp @@ -222,7 +222,10 @@ ParticipantDeviceModel * Camera::getParticipantDeviceModel() const{ void Camera::setCallModel (CallModel *callModel) { if (mCallModel != callModel) { + if( mCallModel) + disconnect(mCallModel, &CallModel::statusChanged, this, &Camera::onCallStateChanged); mCallModel = callModel; + connect(mCallModel, &CallModel::statusChanged, this, &Camera::onCallStateChanged); updateWindowIdLocation(); update(); @@ -286,3 +289,10 @@ void Camera::deactivatePreview(){ mPreviewCounterMutex.unlock(); } } + +void Camera::onCallStateChanged(){ + if( mCallModel->getStatus() == CallModel::CallStatusEnded){ + resetWindowId(); + mCallModel = nullptr; + } +} \ No newline at end of file diff --git a/linphone-app/src/components/camera/Camera.hpp b/linphone-app/src/components/camera/Camera.hpp index 58d20c9cf..9e757a867 100644 --- a/linphone-app/src/components/camera/Camera.hpp +++ b/linphone-app/src/components/camera/Camera.hpp @@ -68,6 +68,8 @@ public: void isReady(); void isNotReady(); +public slots: + void onCallStateChanged(); signals: void callChanged (CallModel *callModel); diff --git a/linphone-app/src/components/conference/ConferenceModel.cpp b/linphone-app/src/components/conference/ConferenceModel.cpp index c649d6dfb..2b054ef12 100644 --- a/linphone-app/src/components/conference/ConferenceModel.cpp +++ b/linphone-app/src/components/conference/ConferenceModel.cpp @@ -122,6 +122,13 @@ std::list> ConferenceModel::getParticipan participantList.push_front(me); return participantList; } + +void ConferenceModel::setIsReady(bool state){ + if( mIsReady != state){ + mIsReady = state; + emit isReadyChanged(); + } +} //----------------------------------------------------------------------------------------------------------------------- // LINPHONE LISTENERS //----------------------------------------------------------------------------------------------------------------------- @@ -169,6 +176,8 @@ void ConferenceModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr emit participantDeviceIsSpeakingChanged(participantDevice, isSpeaking); } void ConferenceModel::onConferenceStateChanged(linphone::Conference::State newState){ + if(newState == linphone::Conference::State::Created) + setIsReady(true); updateLocalParticipant(); emit conferenceStateChanged(newState); } diff --git a/linphone-app/src/components/conference/ConferenceModel.hpp b/linphone-app/src/components/conference/ConferenceModel.hpp index dc86f8983..083920376 100644 --- a/linphone-app/src/components/conference/ConferenceModel.hpp +++ b/linphone-app/src/components/conference/ConferenceModel.hpp @@ -41,6 +41,7 @@ public: Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT) Q_PROPERTY(ParticipantListModel* participants READ getParticipantListModel CONSTANT) Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged) + Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged) static QSharedPointer create(std::shared_ptr chatRoom, QObject *parent = Q_NULLPTR); @@ -56,6 +57,9 @@ public: Q_INVOKABLE ParticipantModel* getLocalParticipant() const; ParticipantListModel* getParticipantListModel() const; std::list> getParticipantList() const; // SDK exclude me. We want to get ALL participants. + + void setIsReady(bool state); + virtual void onParticipantAdded(const std::shared_ptr & participant); virtual void onParticipantRemoved(const std::shared_ptr & participant); @@ -83,6 +87,7 @@ signals: void participantDeviceStateChanged(const std::shared_ptr & device, linphone::ParticipantDeviceState state); void conferenceStateChanged(linphone::Conference::State newState); void subjectChanged(); + void isReadyChanged(); private: void connectTo(ConferenceListener * listener); @@ -92,6 +97,7 @@ private: QSharedPointer mLocalParticipant; QSharedPointer mParticipantListModel; + bool mIsReady = false; }; Q_DECLARE_METATYPE(QSharedPointer) diff --git a/linphone-app/src/components/conference/ConferenceProxyModel.cpp b/linphone-app/src/components/conference/ConferenceProxyModel.cpp index f487e424f..a2a922a13 100644 --- a/linphone-app/src/components/conference/ConferenceProxyModel.cpp +++ b/linphone-app/src/components/conference/ConferenceProxyModel.cpp @@ -49,7 +49,7 @@ ConferenceProxyModel::ConferenceProxyModel (QObject *parent) : SortFilterProxyMo bool ConferenceProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const { const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); const CallModel *callModel = index.data().value(); - return callModel->getCall()->getParams()->getLocalConferenceMode() || callModel->getCall()->getCurrentParams()->getLocalConferenceMode(); + return callModel->getCall() && (callModel->getCall()->getParams()->getLocalConferenceMode() || callModel->getCall()->getCurrentParams()->getLocalConferenceMode()); } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index ab77ed47c..cc0ea4367 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -39,25 +39,35 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptrisConference()) { mCallModel = callModel; - auto conferenceModel = callModel->getConferenceSharedModel(); - - updateDevices(conferenceModel->getConference()->getMe()->getDevices(), true); - updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false); - - qDebug() << "Conference have " << mList.size() << " devices"; - connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded); - connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this, &ParticipantDeviceListModel::onParticipantDeviceRemoved); - connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged); + connect(mCallModel, &CallModel::conferenceModelChanged, this, &ParticipantDeviceListModel::onConferenceModelChanged); + initConferenceModel(); + } +} + +void ParticipantDeviceListModel::initConferenceModel(){ + if(!mInitialized && mCallModel){ + auto conferenceModel = mCallModel->getConferenceSharedModel(); + if(conferenceModel){ + updateDevices(conferenceModel->getConference()->getMe()->getDevices(), true); + updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false); + + qDebug() << "Conference have " << mList.size() << " devices"; + connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded); + connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this, &ParticipantDeviceListModel::onParticipantDeviceRemoved); + connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged); + mInitialized = true; + } } } @@ -171,6 +181,12 @@ bool ParticipantDeviceListModel::isMeAlone() const{ return true; } +void ParticipantDeviceListModel::onConferenceModelChanged (){ + if(!mInitialized){ + initConferenceModel(); + } +} + void ParticipantDeviceListModel::onSecurityLevelChanged(std::shared_ptr device){ emit securityLevelChanged(device); } diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp index 55a510d19..ac61f7089 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp @@ -28,8 +28,8 @@ #include #include #include "app/proxyModel/ProxyListModel.hpp" +#include "components/call/CallModel.hpp" -class CallModel; class ParticipantDeviceModel; class ParticipantDeviceListModel : public ProxyListModel { @@ -39,6 +39,7 @@ public: ParticipantDeviceListModel (std::shared_ptr participant, QObject *parent = nullptr); ParticipantDeviceListModel (CallModel * callModel, QObject *parent = nullptr); + void initConferenceModel(); void updateDevices(std::shared_ptr participant); void updateDevices(const std::list>& devices, const bool& isMe); @@ -52,6 +53,7 @@ public: bool isMeAlone() const; public slots: + void onConferenceModelChanged (); void onSecurityLevelChanged(std::shared_ptr device); void onParticipantAdded(const std::shared_ptr & participant); void onParticipantRemoved(const std::shared_ptr & participant); @@ -71,6 +73,7 @@ signals: private: CallModel * mCallModel = nullptr; QList mActiveSpeakers;// First item is last speaker + bool mInitialized = false; }; diff --git a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml index 5a901d9ff..dcb1ea77d 100644 --- a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml +++ b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml @@ -33,10 +33,13 @@ Item { property bool d : callModel && callModel.cameraEnabled property bool isReady: cameraLoader.item && cameraLoader.item.isReady + property bool hadCall : false + onCallModelChanged: if(callModel) hadCall = true + signal videoDefinitionChanged() onCurrentDeviceChanged: {if(container.isCameraFromDevice) resetActive()} - Component.onDestruction: isVideoEnabled=false + Component.onDestruction: if(!hadCall || (hadCall && callModel) ){isVideoEnabled=false} function resetActive(){ resetTimer.resetActive() } diff --git a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml index 26fec8e81..8d2462655 100644 --- a/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml +++ b/linphone-app/ui/modules/Linphone/Menus/IncallMenu.qml @@ -113,7 +113,7 @@ Rectangle{ , visible: true}, {titleIndex: 1 - , icon: (mainItem.callModel && mainItem.callModel.videoEnabled ? + , icon: (mainItem.callModel && mainItem.callModel.localVideoEnabled ? (mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid ? IncallMenuStyle.settingsIcons.gridIcon : IncallMenuStyle.settingsIcons.activeSpeakerIcon) : IncallMenuStyle.settingsIcons.audioOnlyIcon) , nextPage:layoutMenu @@ -236,21 +236,24 @@ Rectangle{ text: modelData.text // break bind. Radiobutton checked itself without taking care of custom binding. This workaound works as long as we don't really need the binding. - Component.onCompleted: checked = mainItem.callModel ? (mainItem.callModel.videoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) - || (!mainItem.callModel.videoEnabled && modelData.value == 2) + Component.onCompleted: checked = mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) + || (!mainItem.callModel.localVideoEnabled && modelData.value == 2) : false Timer{ id: changingLayoutDelay interval: 100 onTriggered: {if(modelData.value == 2) mainItem.callModel.videoEnabled = false - else mainItem.callModel.conferenceVideoLayout = modelData.value + 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.videoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) - || (!mainItem.callModel.videoEnabled && modelData.value == 2) + if(! ( mainItem.callModel ? (mainItem.callModel.localVideoEnabled && modelData.value == mainItem.callModel.conferenceVideoLayout) + || (!mainItem.callModel.localVideoEnabled && modelData.value == 2) : false)){ mainItem.enabled = false mainItem.layoutChanging(modelData.value)// Let time to clear cameras diff --git a/linphone-app/ui/views/App/Calls/CallsWindow.js b/linphone-app/ui/views/App/Calls/CallsWindow.js index 9df8466c4..da5280712 100644 --- a/linphone-app/ui/views/App/Calls/CallsWindow.js +++ b/linphone-app/ui/views/App/Calls/CallsWindow.js @@ -89,19 +89,23 @@ function getContent (call, conferenceInfoModel) { console.log("incomingCall") return incomingCall } - window.conferenceInfoModel = call.conferenceInfoModel; - if (status === CallModel.CallStatusOutgoing || status === CallModel.CallStatusEnded) { - console.log("Is conference ? "+call.isConference) - return waitingRoom - } - - if(call.isConference){ - console.log("incall") + if( window.conferenceInfoModel != call.conferenceInfoModel) { + Qt.callLater(function(){window.conferenceInfoModel = call.conferenceInfoModel}) + return middlePane.sourceComponent // unchange. Wait for later decision on conference model (avoid binding loop on sourceComponent) + }else{ + if(call.isConference){ + console.log("incall") + return incall + } + if (status === CallModel.CallStatusOutgoing || status === CallModel.CallStatusEnded) { + console.log("Is conference ? "+call.isConference) + return waitingRoom + } + + + console.log("incall") return incall } - - console.log("incall") - return incall } // ----------------------------------------------------------------------------- diff --git a/linphone-app/ui/views/App/Calls/CallsWindow.qml b/linphone-app/ui/views/App/Calls/CallsWindow.qml index a7c3f0e3b..f17dbad02 100644 --- a/linphone-app/ui/views/App/Calls/CallsWindow.qml +++ b/linphone-app/ui/views/App/Calls/CallsWindow.qml @@ -18,6 +18,7 @@ Window { // `{}` is a workaround to avoid `TypeError: Cannot read property...` when calls list is empty property CallModel call: calls.selectedCall + onCallChanged: if(!call && conferenceInfoModel) {conferenceInfoModel = null} /* ?calls.selectedCall:{ callError: '', @@ -53,7 +54,6 @@ Window { function endOfProcess(exitValue){ window.detachVirtualWindow(); if(exitValue == 0 && calls.count == 0 && middlePane.sourceComponent != waitingRoom) { - console.log("Closing") close(); } } @@ -84,6 +84,7 @@ Window { id: mainPaned anchors.fill: parent defaultChildAWidth: CallsWindowStyle.callsList.defaultWidth + defaultClosed: true maximumLeftLimit: CallsWindowStyle.callsList.maximumWidth minimumLeftLimit: CallsWindowStyle.callsList.minimumWidth @@ -264,13 +265,18 @@ Window { id: middlePane anchors.fill: parent sourceComponent: Logic.getContent(window.call, window.conferenceInfoModel) + property var lastComponent: null onSourceComponentChanged: { - if( sourceComponent == waitingRoom) - mainPaned.close() - rightPaned.childAItem.update() - if(!sourceComponent && calls.count == 0) - window.close() - }// Force update when loading a new Content. It's just to be sure + if(lastComponent != sourceComponent){ + if( sourceComponent == waitingRoom) + mainPaned.close() + rightPaned.childAItem.update() + if(!sourceComponent && calls.count == 0) + window.close() + lastComponent = sourceComponent + } + + }// Force update when loading a new Content. It's just to be sure active: window.call || window.conferenceInfoModel } diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml index f0f85c8f7..e5dace53f 100644 --- a/linphone-app/ui/views/App/Calls/Incall.qml +++ b/linphone-app/ui/views/App/Calls/Incall.qml @@ -183,7 +183,7 @@ Rectangle { id: address Layout.fillWidth: true horizontalAlignment: Qt.AlignHCenter - visible: !conferenceModel && callModel + visible: !conferenceModel && callModel && !callModel.isConference text: !conferenceModel && callModel ? callModel.peerAddress : '' @@ -275,34 +275,48 @@ Rectangle { } RowLayout{ anchors.fill: parent - Loader{ - id: conferenceLayout + Item{ Layout.fillHeight: true Layout.fillWidth: true - sourceComponent: conference.conferenceModel - ? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid || !conference.callModel.videoEnabled? gridComponent : activeSpeakerComponent - : activeSpeakerComponent - onSourceComponentChanged: console.log("conferenceLayout: "+conference.callModel.conferenceVideoLayout) - active: conference.callModel - ColumnLayout { + Loader{ + id: conferenceLayout + anchors.fill: parent + sourceComponent: conference.conferenceModel + ? conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid || !conference.callModel.videoEnabled + ? gridComponent + : activeSpeakerComponent + : activeSpeakerComponent + onSourceComponentChanged: console.log("conferenceLayout: "+conference.callModel.conferenceVideoLayout) + active: conference.callModel + } + Rectangle{ anchors.fill: parent - visible: !conference.callModel || !conferenceLayout.item || conferenceLayout.item.participantCount == 0 - BusyIndicator{ - Layout.preferredHeight: 50 - Layout.preferredWidth: 50 - Layout.alignment: Qt.AlignCenter - running: parent.visible - color: IncallStyle.buzyColor - } - Text{ - Layout.alignment: Qt.AlignCenter - - text: conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid && !conference.callModel.videoEnabled - //: 'Waiting for another participant...' : Waiting message for more participant. - ? qsTr('incallWaitParticipantMessage') - //: 'Video conference is not ready. Please Wait...' : Waiting message for starting conference. - : qsTr('incallWaitMessage') - color: IncallStyle.buzyColor + color: conference.color + visible: !conference.callModel || (conference.callModel.isConference + && (!conference.conferenceModel + || (conference.conferenceModel && !conference.conferenceModel.isReady)) + ) + || !conferenceLayout.item || conferenceLayout.item.participantCount == 0 + || (conferenceLayout.sourceComponent == gridComponent && !conference.callModel.videoEnabled && conferenceLayout.item.participantCount <= 1) + ColumnLayout { + anchors.fill: parent + BusyIndicator{ + Layout.preferredHeight: 40 + Layout.preferredWidth: 40 + Layout.alignment: Qt.AlignCenter + running: parent.visible + color: IncallStyle.buzyColor + } + Text{ + Layout.alignment: Qt.AlignCenter + + text: conferenceLayout.sourceComponent == gridComponent && !conference.callModel.videoEnabled + //: 'Waiting for another participant...' : Waiting message for more participant. + ? qsTr('incallWaitParticipantMessage') + //: 'Video conference is not ready. Please Wait...' : Waiting message for starting conference. + : qsTr('incallWaitMessage') + color: IncallStyle.buzyColor + } } } } @@ -438,12 +452,13 @@ Rectangle { backgroundRadius: 90 colorSet: callModel && callModel.cameraEnabled ? IncallStyle.buttons.cameraOn : IncallStyle.buttons.cameraOff updating: callModel.videoEnabled && callModel.updating - visible: callModel && ( !callModel.isConference || callModel.videoEnabled) + visible: callModel && (!callModel.isConference || callModel.localVideoEnabled) onClicked: if(callModel){ - if( callModel.isConference)// Only deactivate camera in conference. - callModel.cameraEnabled = !callModel.cameraEnabled - else// In one-one, we deactivate all videos. - callModel.videoEnabled = !callModel.videoEnabled + if( callModel.isConference){// Only deactivate camera in conference. + callModel.cameraEnabled = !callModel.cameraEnabled + }else{// In one-one, we deactivate all videos. + callModel.videoEnabled = !callModel.videoEnabled + } } } diff --git a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml index a01bbfdb8..61dc128a3 100644 --- a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml +++ b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml @@ -89,11 +89,13 @@ Item { width: 16 * cellHeight / 9 model: mainItem.callModel.isConference - ? mainItem.participantDevices - : mainItem.callModel.videoEnabled && !callModel.pausedByUser + ? mainItem.participantDevices.showMe && mainItem.participantDevices.count <= 1 + ? [] + : mainItem.participantDevices + : mainItem.callModel.localVideoEnabled && !callModel.pausedByUser ? [{videoEnabled:true, isPreview:true}] : [] - onModelChanged: console.log( mainItem.callModel.isConference+"/"+mainItem.callModel.videoEnabled + "/" +mainItem.callModel.cameraEnabled + " / " +count) + onModelChanged: console.log( mainItem.callModel.isConference+"/"+mainItem.callModel.localVideoEnabled + "/" +mainItem.callModel.cameraEnabled + " / " +count) spacing: 15 verticalLayoutDirection: ItemView.BottomToTop delegate:Item{ diff --git a/linphone-app/ui/views/App/Calls/WaitingRoom.qml b/linphone-app/ui/views/App/Calls/WaitingRoom.qml index 722150f6d..a91958156 100644 --- a/linphone-app/ui/views/App/Calls/WaitingRoom.qml +++ b/linphone-app/ui/views/App/Calls/WaitingRoom.qml @@ -80,7 +80,7 @@ Rectangle { font.pointSize: WaitingRoomStyle.elapsedTime.pointSize horizontalAlignment: Text.AlignHCenter width: parent.width - visible: mainItem.callModel + visible: mainItem.callModel && mainItem.isEnding Timer { interval: 1000 repeat: true @@ -139,10 +139,10 @@ Rectangle { anchors.centerIn: parent height: cameraHeight width : cameraWidth - - deactivateCamera: !mainItem.previewLoaderEnabled - callModel: mainItem.callModel + callModel: mainItem.callModel conferenceInfoModel: mainItem.conferenceInfoModel + deactivateCamera: !mainItem.previewLoaderEnabled || mainItem.isEnding + /* image: mainItem._sipAddressObserver && mainItem._sipAddressObserver.contact && mainItem._sipAddressObserver.contact.vcard.avatar