diff --git a/linphone-desktop/assets/languages/en.ts b/linphone-desktop/assets/languages/en.ts
index e246e3f03..79e1678ff 100644
--- a/linphone-desktop/assets/languages/en.ts
+++ b/linphone-desktop/assets/languages/en.ts
@@ -363,6 +363,14 @@ Server url not configured.
saveScreenshotTitle
+
+ acceptVideoDescription
+
+
+
+ acceptVideoTitle
+
+
MainWindow
diff --git a/linphone-desktop/assets/languages/fr.ts b/linphone-desktop/assets/languages/fr.ts
index 4e26fbdf4..13d702994 100644
--- a/linphone-desktop/assets/languages/fr.ts
+++ b/linphone-desktop/assets/languages/fr.ts
@@ -351,6 +351,14 @@ Url du serveur non configurée.
saveScreenshotTitle
+
+ acceptVideoDescription
+
+
+
+ acceptVideoTitle
+
+
IncomingCall
diff --git a/linphone-desktop/src/components/call/CallModel.cpp b/linphone-desktop/src/components/call/CallModel.cpp
index a4729a313..b670ce4c9 100644
--- a/linphone-desktop/src/components/call/CallModel.cpp
+++ b/linphone-desktop/src/components/call/CallModel.cpp
@@ -36,6 +36,20 @@ CallModel::CallModel (shared_ptr linphone_call) {
m_paused_by_user = false;
break;
+ case linphone::CallStateUpdatedByRemote: {
+ shared_ptr core = CoreManager::getInstance()->getCore();
+
+ if (
+ !m_linphone_call->getCurrentParams()->videoEnabled() &&
+ m_linphone_call->getRemoteParams()->videoEnabled()
+ ) {
+ CoreManager::getInstance()->getCore()->deferCallUpdate(m_linphone_call);
+ emit videoRequested();
+ }
+ }
+
+ break;
+
default:
break;
}
@@ -63,6 +77,16 @@ void CallModel::transfer () {
// TODO
}
+void CallModel::acceptVideoRequest () {
+ shared_ptr params = m_linphone_call->getCurrentParams()->copy();
+ params->enableVideo(true);
+ CoreManager::getInstance()->getCore()->acceptCallUpdate(m_linphone_call, params);
+}
+
+void CallModel::rejectVideoRequest () {
+ CoreManager::getInstance()->getCore()->acceptCallUpdate(m_linphone_call, m_linphone_call->getCurrentParams());
+}
+
// -----------------------------------------------------------------------------
QString CallModel::getSipAddress () const {
@@ -135,6 +159,15 @@ bool CallModel::getPausedByUser () const {
}
void CallModel::setPausedByUser (bool status) {
+ switch (m_linphone_call->getState()) {
+ case linphone::CallStateConnected:
+ case linphone::CallStateStreamsRunning:
+ case linphone::CallStatePaused:
+ case linphone::CallStatePausedByRemote:
+ break;
+ default: return;
+ }
+
if (status) {
if (!m_paused_by_user)
CoreManager::getInstance()->getCore()->pauseCall(m_linphone_call);
@@ -146,20 +179,24 @@ void CallModel::setPausedByUser (bool status) {
CoreManager::getInstance()->getCore()->resumeCall(m_linphone_call);
}
-bool CallModel::getVideoInputEnabled () const {
- shared_ptr params = m_linphone_call->getRemoteParams();
- return params && params->videoEnabled() && getStatus() == CallStatusConnected;
-}
-
-void CallModel::setVideoInputEnabled (bool status) {
- // TODO
-}
-
-bool CallModel::getVideoOutputEnabled () const {
+bool CallModel::getVideoEnabled () const {
shared_ptr params = m_linphone_call->getCurrentParams();
return params && params->videoEnabled() && getStatus() == CallStatusConnected;
}
-void CallModel::setVideoOutputEnabled (bool status) {
- // TODO
+void CallModel::setVideoEnabled (bool status) {
+ switch (m_linphone_call->getState()) {
+ case linphone::CallStateConnected:
+ case linphone::CallStateStreamsRunning:
+ break;
+ default: return;
+ }
+
+ if (status == getVideoEnabled())
+ return;
+
+ shared_ptr params = CoreManager::getInstance()->getCore()->createCallParams(m_linphone_call);
+ params->enableVideo(status);
+
+ CoreManager::getInstance()->getCore()->updateCall(m_linphone_call, params);
}
diff --git a/linphone-desktop/src/components/call/CallModel.hpp b/linphone-desktop/src/components/call/CallModel.hpp
index 8ed51a543..6af866b95 100644
--- a/linphone-desktop/src/components/call/CallModel.hpp
+++ b/linphone-desktop/src/components/call/CallModel.hpp
@@ -16,8 +16,7 @@ class CallModel : public QObject {
Q_PROPERTY(float quality READ getQuality CONSTANT); // Same idea.
Q_PROPERTY(bool microMuted READ getMicroMuted WRITE setMicroMuted NOTIFY microMutedChanged);
Q_PROPERTY(bool pausedByUser READ getPausedByUser WRITE setPausedByUser NOTIFY statusChanged);
- Q_PROPERTY(bool videoInputEnabled READ getVideoInputEnabled WRITE setVideoInputEnabled NOTIFY statusChanged);
- Q_PROPERTY(bool videoOutputEnabled READ getVideoOutputEnabled WRITE setVideoOutputEnabled NOTIFY statusChanged);
+ Q_PROPERTY(bool videoEnabled READ getVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged);
public:
enum CallStatus {
@@ -43,9 +42,13 @@ public:
Q_INVOKABLE void terminate ();
Q_INVOKABLE void transfer ();
+ Q_INVOKABLE void acceptVideoRequest ();
+ Q_INVOKABLE void rejectVideoRequest ();
+
signals:
void statusChanged (CallStatus status);
void microMutedChanged (bool status);
+ void videoRequested ();
private:
QString getSipAddress () const;
@@ -64,11 +67,8 @@ private:
bool getPausedByUser () const;
void setPausedByUser (bool status);
- bool getVideoInputEnabled () const;
- void setVideoInputEnabled (bool status);
-
- bool getVideoOutputEnabled () const;
- void setVideoOutputEnabled (bool status);
+ bool getVideoEnabled () const;
+ void setVideoEnabled (bool status);
bool m_micro_muted = false;
bool m_paused_by_remote = false;
diff --git a/linphone-desktop/ui/views/App/Calls/AbstractStartingCall.qml b/linphone-desktop/ui/views/App/Calls/AbstractStartingCall.qml
index c317e19ff..6656e61e1 100644
--- a/linphone-desktop/ui/views/App/Calls/AbstractStartingCall.qml
+++ b/linphone-desktop/ui/views/App/Calls/AbstractStartingCall.qml
@@ -10,6 +10,8 @@ import App.Styles 1.0
// =============================================================================
Rectangle {
+ property var call
+
default property alias _actionArea: actionArea.data
property var _contactObserver: SipAddressesModel.getContactObserver(sipAddress)
diff --git a/linphone-desktop/ui/views/App/Calls/CallsWindow.qml b/linphone-desktop/ui/views/App/Calls/CallsWindow.qml
index bba66a3da..2d5dc970f 100644
--- a/linphone-desktop/ui/views/App/Calls/CallsWindow.qml
+++ b/linphone-desktop/ui/views/App/Calls/CallsWindow.qml
@@ -15,11 +15,10 @@ Window {
// ---------------------------------------------------------------------------
+ property var call: calls.selectedCall
readonly property bool chatIsOpened: !rightPaned.isClosed()
- // `{}` is a workaround to avoid `TypeError: Cannot read property...` in `Incall` component.
- property var call: calls.selectedCall || {}
- property string sipAddress: call.sipAddress || ''
+ property string sipAddress: call ? call.sipAddress : ''
// ---------------------------------------------------------------------------
@@ -122,19 +121,28 @@ Window {
Component {
id: incomingCall
- IncomingCall {}
+ IncomingCall {
+ call: window.call
+ }
}
Component {
id: outgoingCall
- OutgoingCall {}
+ OutgoingCall {
+ call: window.call
+ }
}
Component {
id: incall
- Incall {}
+ Incall {
+ // `{}` is a workaround to avoid `TypeError: Cannot read property...` in `Incall` component.
+ call: window.call || ({
+ videoEnabled: false
+ })
+ }
}
Component {
@@ -151,7 +159,12 @@ Window {
childA: Loader {
anchors.fill: parent
+
sourceComponent: {
+ if (!window.call) {
+ return null
+ }
+
var status = window.call.status
if (status == null) {
return null
diff --git a/linphone-desktop/ui/views/App/Calls/Incall.qml b/linphone-desktop/ui/views/App/Calls/Incall.qml
index 5f043a695..37079d30f 100644
--- a/linphone-desktop/ui/views/App/Calls/Incall.qml
+++ b/linphone-desktop/ui/views/App/Calls/Incall.qml
@@ -17,13 +17,36 @@ Rectangle {
// ---------------------------------------------------------------------------
+ property var call
+
property var _contactObserver: SipAddressesModel.getContactObserver(sipAddress)
- property var _call: call
// ---------------------------------------------------------------------------
color: CallStyle.backgroundColor
+ // ---------------------------------------------------------------------------
+ // Handle video requests.
+ // ---------------------------------------------------------------------------
+
+ SmartConnect {
+ Component.onCompleted: this.connect(call, 'videoRequested', function () {
+ Utils.openConfirmDialog(window, {
+ descriptionText: qsTr('acceptVideoDescription'),
+ exitHandler: function (status) {
+ if (status) {
+ call.acceptVideoRequest()
+ } else {
+ call.rejectVideoRequest()
+ }
+ },
+ title: qsTr('acceptVideoTitle')
+ })
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
ColumnLayout {
anchors {
fill: parent
@@ -85,7 +108,7 @@ Rectangle {
id: cameraActions
anchors.right: parent.right
- active: Boolean(call.videoInputEnabled) && call.status !== CallModel.CallStatusEnded
+ active: call.videoEnabled && call.status !== CallModel.CallStatusEnded
sourceComponent: ActionBar {
iconSize: CallStyle.header.iconSize
@@ -200,7 +223,7 @@ Rectangle {
Camera {
height: container.height
width: container.width
- call: incall._call
+ call: incall.call
}
}
@@ -208,7 +231,7 @@ Rectangle {
id: cameraLoader
anchors.centerIn: parent
- sourceComponent: call.videoInputEnabled ? camera : avatar
+ sourceComponent: call.videoEnabled ? camera : avatar
}
}
@@ -241,15 +264,11 @@ Rectangle {
}
ActionSwitch {
- icon: 'speaker'
- iconSize: CallStyle.actionArea.iconSize
- onClicked: enabled = !enabled
- }
-
- ActionSwitch {
+ enabled: call.videoEnabled
icon: 'camera'
iconSize: CallStyle.actionArea.iconSize
- onClicked: enabled = !enabled
+
+ onClicked: call.videoEnabled = !enabled
}
ActionButton {
@@ -266,9 +285,9 @@ Rectangle {
width: CallStyle.actionArea.userVideo.width
isPreview: true
+ visible: incall.width >= CallStyle.actionArea.lowWidth && call.videoEnabled
- call: incall._call
- visible: Boolean(incall.width >= CallStyle.actionArea.lowWidth && call.videoOutputEnabled)
+ Component.onCompleted: call = incall.call
}
ActionBar {
diff --git a/linphone-desktop/ui/views/App/Calls/OutgoingCall.qml b/linphone-desktop/ui/views/App/Calls/OutgoingCall.qml
index 119f5d884..ca8bc46f6 100644
--- a/linphone-desktop/ui/views/App/Calls/OutgoingCall.qml
+++ b/linphone-desktop/ui/views/App/Calls/OutgoingCall.qml
@@ -10,7 +10,7 @@ import App.Styles 1.0
AbstractStartingCall {
GridLayout {
- columns: parent.width < CallStyle.actionArea.lowWidth && call.videoOutputEnabled ? 1 : 2
+ columns: parent.width < CallStyle.actionArea.lowWidth && call.videoEnabled ? 1 : 2
rowSpacing: ActionBarStyle.spacing
anchors {
@@ -26,13 +26,6 @@ AbstractStartingCall {
onClicked: call.microMuted = enabled
}
-
- ActionSwitch {
- icon: 'speaker'
- iconSize: CallStyle.actionArea.iconSize
-
- onClicked: enabled = !enabled
- }
}
Item {
@@ -40,7 +33,7 @@ AbstractStartingCall {
height: CallStyle.actionArea.userVideo.height
width: CallStyle.actionArea.userVideo.width
- visible: call.videoOutputEnabled
+ visible: call.videoEnabled
}
ActionBar {