Commit 370c4481 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/views/App/Calls/Incall): add fullscreen support

parent 59ed757f
......@@ -259,6 +259,7 @@
<file>ui/views/App/Calls/Incall.qml</file>
<file>ui/views/App/Calls/IncomingCall.qml</file>
<file>ui/views/App/Calls/OutgoingCall.qml</file>
<file>ui/views/App/IncallFullscreen.qml</file>
<file>ui/views/App/MainWindow/ContactEdit.qml</file>
<file>ui/views/App/MainWindow/Contacts.qml</file>
<file>ui/views/App/MainWindow/Conversation.qml</file>
......
......@@ -62,6 +62,20 @@ struct ContextInfo {
// -----------------------------------------------------------------------------
inline void setWindowId (const Camera &camera) {
ContextInfo *context_info = camera.m_context_info;
qInfo() << QStringLiteral("Set context info (width: %1, height: %2, is_preview: %3).")
.arg(context_info->width).arg(context_info->height).arg(camera.m_is_preview);
if (camera.m_is_preview)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(context_info);
else
camera.m_call->getLinphoneCall()->setNativeVideoWindowId(context_info);
}
// -----------------------------------------------------------------------------
CameraRenderer::CameraRenderer (const Camera *camera) : m_camera(camera) {}
QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize &size) {
......@@ -74,10 +88,7 @@ QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize &
context_info->width = size.width();
context_info->height = size.height();
if (m_camera->m_is_preview)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(context_info);
else
m_camera->m_call->getLinphoneCall()->setNativeVideoWindowId(context_info);
setWindowId(*m_camera);
return new QOpenGLFramebufferObject(size, format);
}
......@@ -148,20 +159,9 @@ CallModel *Camera::getCall () const {
void Camera::setCall (CallModel *call) {
if (m_call != call) {
if (call) {
shared_ptr<linphone::Call> linphone_call = call->getLinphoneCall();
linphone::CallState state = linphone_call->getState();
if (state == linphone::CallStateConnected || state == linphone::CallStateStreamsRunning) {
if (m_is_preview)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(m_context_info);
else
linphone_call->setNativeVideoWindowId(m_context_info);
}
}
m_call = call;
if ((m_call = call))
setWindowId(*this);
emit callChanged(call);
emit callChanged(m_call);
}
}
......@@ -53,6 +53,7 @@ private:
class Camera : public QQuickFramebufferObject {
friend class CameraRenderer;
friend void setWindowId (const Camera &camera);
Q_OBJECT;
......
......@@ -4,6 +4,8 @@
.pragma library
.import QtQuick 2.0 as QtQuick
.import 'uri-tools.js' as UriTools
// =============================================================================
......@@ -136,15 +138,15 @@ function openWindow (window, parent, options) {
'qrc:/ui/views/App/' + window + '.qml'
)
if (component.status !== Component.Ready) {
if (component.status !== QtQuick.Component.Ready) {
console.debug('Window not ready.')
if (component.status === Component.Error) {
if (component.status === QtQuick.Component.Error) {
console.debug('Error:' + component.errorString())
}
return // Error.
}
object = component.createObject(parent)
object = component.createObject(parent, options ? options.properties : {})
}
object.closing.connect(object.destroy.bind(object))
......
import QtQuick 2.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import Common 1.0
......@@ -20,6 +19,21 @@ Rectangle {
property var call
property var _contactObserver: SipAddressesModel.getContactObserver(sipAddress)
property var _fullscreen: null
// ---------------------------------------------------------------------------
function _showFullscreen () {
if (_fullscreen) {
return
}
_fullscreen = Utils.openWindow('IncallFullscreen', incall, {
properties: {
call: incall.call
}
})
}
// ---------------------------------------------------------------------------
......@@ -96,6 +110,7 @@ Rectangle {
anchors.left: parent.left
icon: 'call_quality_0'
iconSize: CallStyle.header.iconSize
visible: call.status !== CallModel.CallStatusEnded
// See: http://www.linphone.org/docs/liblinphone/group__call__misc.html#ga62c7d3d08531b0cc634b797e273a0a73
Timer {
......@@ -158,6 +173,8 @@ Rectangle {
ActionButton {
icon: 'fullscreen'
visible: call.videoEnabled
onClicked: _showFullscreen()
}
}
}
......@@ -246,7 +263,7 @@ Rectangle {
Loader {
anchors.centerIn: parent
sourceComponent: call.videoEnabled ? camera : avatar
sourceComponent: call.videoEnabled && !_fullscreen ? camera : avatar
}
}
......@@ -295,16 +312,20 @@ Rectangle {
}
}
Camera {
Loader {
anchors.centerIn: parent
height: CallStyle.actionArea.userVideo.height
width: CallStyle.actionArea.userVideo.width
visible: incall.width >= CallStyle.actionArea.lowWidth && call.videoEnabled && !_fullscreen
Camera {
anchors.fill: parent
isPreview: true
visible: incall.width >= CallStyle.actionArea.lowWidth && call.videoEnabled
Component.onCompleted: call = incall.call
}
}
ActionBar {
anchors {
......
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Window 2.2
import Common 1.0
import Common.Styles 1.0
import Linphone 1.0
import Utils 1.0
import App.Styles 1.0
// =============================================================================
Window {
id: incall
// ---------------------------------------------------------------------------
property var call
// ---------------------------------------------------------------------------
function _exit (cb) {
incall.close()
if (cb) {
cb()
}
}
// ---------------------------------------------------------------------------
visible: true
visibility: Window.FullScreen
onActiveChanged: incall.showFullScreen()
// ---------------------------------------------------------------------------
Rectangle {
anchors.fill: parent
color: '#000000' // Not a style.
}
Camera {
id: camera
anchors.fill: parent
call: incall.call
}
ColumnLayout {
anchors {
fill: parent
topMargin: CallStyle.header.topMargin
}
spacing: 0
// -------------------------------------------------------------------------
// Call info.
// -------------------------------------------------------------------------
Item {
id: info
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
Layout.leftMargin: CallStyle.header.leftMargin
Layout.rightMargin: CallStyle.header.rightMargin
Layout.preferredHeight: CallStyle.header.contactDescription.height
Icon {
id: callQuality
anchors.left: parent.left
icon: 'call_quality_0'
iconSize: CallStyle.header.iconSize
// See: http://www.linphone.org/docs/liblinphone/group__call__misc.html#ga62c7d3d08531b0cc634b797e273a0a73
Timer {
interval: 5000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
var quality = call.quality
callQuality.icon = 'call_quality_' + (
// Note: `quality` is in the [0, 5] interval.
// It's necessary to map in the `call_quality_` interval. ([0, 3])
quality >= 0 ? Math.round(quality / (5 / 3)) : 0
)
}
}
}
// -----------------------------------------------------------------------
// Video actions.
// -----------------------------------------------------------------------
ActionBar {
anchors.right: parent.right
iconSize: CallStyle.header.iconSize
ActionButton {
icon: 'screenshot'
onClicked: call.takeSnapshot()
}
ActionSwitch {
enabled: call.recording
icon: 'record'
useStates: false
onClicked: !enabled ? call.startRecording() : call.stopRecording()
}
ActionButton {
icon: 'fullscreen'
onClicked: _exit()
}
}
}
Text {
id: elapsedTime
Layout.fillWidth: true
color: CallStyle.header.elapsedTime.color
font.pointSize: CallStyle.header.elapsedTime.fontSize
horizontalAlignment: Text.AlignHCenter
Component.onCompleted: {
var updateDuration = function () {
text = Utils.formatElapsedTime(call.duration)
Utils.setTimeout(elapsedTime, 1000, updateDuration)
}
updateDuration()
}
}
// -------------------------------------------------------------------------
// Action Buttons.
// -------------------------------------------------------------------------
Item {
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Layout.preferredHeight: CallStyle.actionArea.height
GridLayout {
anchors {
left: parent.left
leftMargin: CallStyle.actionArea.leftButtonsGroupMargin
verticalCenter: parent.verticalCenter
}
rowSpacing: ActionBarStyle.spacing
ActionSwitch {
enabled: !call.microMuted
icon: 'micro'
iconSize: CallStyle.actionArea.iconSize
onClicked: call.microMuted = enabled
}
ActionSwitch {
enabled: true
icon: 'camera'
iconSize: CallStyle.actionArea.iconSize
updating: call.updating
onClicked: _exit(function () { call.videoEnabled = false })
}
ActionButton {
Layout.preferredHeight: CallStyle.actionArea.iconSize
Layout.preferredWidth: CallStyle.actionArea.iconSize
icon: 'options' // TODO: display options.
iconSize: CallStyle.actionArea.iconSize
}
}
Camera {
anchors.centerIn: parent
height: CallStyle.actionArea.userVideo.height
width: CallStyle.actionArea.userVideo.width
isPreview: true
call: incall.call
}
ActionBar {
anchors {
right: parent.right
rightMargin: CallStyle.actionArea.rightButtonsGroupMargin
verticalCenter: parent.verticalCenter
}
iconSize: CallStyle.actionArea.iconSize
ActionSwitch {
enabled: !call.pausedByUser
icon: 'pause'
updating: call.updating
onClicked: _exit(function () { call.pausedByUser = enabled })
}
ActionButton {
icon: 'hangup'
onClicked: _exit(call.terminate)
}
}
}
}
}
......@@ -12,7 +12,7 @@ QtObject {
property int height: 100
property int iconSize: 40
property int leftButtonsGroupMargin: 50
property int lowWidth: 415
property int lowWidth: 515
property int rightButtonsGroupMargin: 50
property QtObject userVideo: QtObject {
......
......@@ -6,4 +6,5 @@ module App
# Views ------------------------------------------------------------------------
IncallFullscreen 1.0 IncallFullscreen.qml
ManageAccounts 1.0 ManageAccounts.qml
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment