linphone-desktop/ui/views/App/Calls/IncallFullscreenWindow.qml
2018-08-07 18:03:17 +02:00

437 lines
11 KiB
QML

import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Window 2.2
import Common 1.0
import Common.Styles 1.0
import DesktopTools 1.0
import Linphone 1.0
import Utils 1.0
import App.Styles 1.0
import 'Incall.js' as Logic
// =============================================================================
Window {
id: window
// ---------------------------------------------------------------------------
property var call
property var caller
property bool hideButtons: false
// ---------------------------------------------------------------------------
function exit (cb) {
DesktopTools.screenSaverStatus = true
// `exit` is called by `Incall.qml`.
// The `window` id can be null if the window was closed in this view.
if (!window) {
return
}
// It's necessary to call `showNormal` before close on MacOs
// because the dock will be hidden forever!
window.visible = false
window.showNormal()
window.close()
if (cb) {
cb()
}
}
// ---------------------------------------------------------------------------
Component.onCompleted: {
window.call = caller.call
var show = function (visibility) {
if (visibility === Window.Windowed) {
window.visibilityChanged.disconnect(show)
window.showFullScreen()
}
}
window.visibilityChanged.connect(show)
}
visible: false
// ---------------------------------------------------------------------------
Shortcut {
sequence: StandardKey.Close
onActivated: window.exit()
}
// ---------------------------------------------------------------------------
Rectangle {
anchors.fill: parent
color: '#000000' // Not a style.
focus: true
Keys.onEscapePressed: window.exit()
Loader {
anchors.fill: parent
active: {
var caller = window.caller
return caller && !caller.cameraActivated
}
sourceComponent: camera
Component {
id: camera
Camera {
call: window.call
}
}
}
// -------------------------------------------------------------------------
// Handle mouse move / Hide buttons.
// -------------------------------------------------------------------------
MouseArea {
Timer {
id: hideButtonsTimer
interval: 5000
running: true
onTriggered: hideButtons = true
}
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
propagateComposedEvents: true
onEntered: hideButtonsTimer.start()
onExited: hideButtonsTimer.stop()
onPositionChanged: {
hideButtonsTimer.stop()
hideButtons = false
hideButtonsTimer.start()
}
}
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.preferredHeight: CallStyle.header.contactDescription.height
Layout.rightMargin: CallStyle.header.rightMargin
ActionBar {
anchors.left: parent.left
iconSize: CallStyle.header.iconSize
visible: !hideButtons
Icon {
id: callQuality
icon: 'call_quality_0'
iconSize: parent.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
)
}
}
}
ActionButton {
icon: 'tel_keypad'
onClicked: telKeypad.visible = !telKeypad.visible
}
}
// ---------------------------------------------------------------------
// Timer.
// ---------------------------------------------------------------------
Text {
id: elapsedTime
anchors.fill: parent
font.pointSize: CallStyle.header.elapsedTime.fullscreen.pointSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: !window.hideButtons
// Not a customizable style.
color: 'white'
style: Text.Raised
styleColor: 'black'
Component.onCompleted: {
var updateDuration = function () {
var call = window.caller.call
text = Utils.formatElapsedTime(call.duration)
Utils.setTimeout(elapsedTime, 1000, updateDuration)
}
updateDuration()
}
}
// ---------------------------------------------------------------------
// Video actions.
// ---------------------------------------------------------------------
ActionBar {
anchors.right: parent.right
iconSize: CallStyle.header.buttonIconSize
visible: !hideButtons
ActionButton {
icon: 'screenshot'
onClicked: call.takeSnapshot()
TooltipArea {
text: qsTr('takeSnapshotLabel')
}
}
ActionSwitch {
id: recordingSwitch
enabled: call.recording
icon: 'record'
useStates: false
visible: SettingsModel.callRecorderEnabled
onClicked: !enabled
? call.startRecording()
: call.stopRecording()
TooltipArea {
text: !recordingSwitch.enabled
? qsTr('startRecordingLabel')
: qsTr('stopRecordingLabel')
}
}
ActionButton {
icon: 'fullscreen'
onClicked: window.exit()
}
}
}
// -----------------------------------------------------------------------
// Action Buttons.
// -----------------------------------------------------------------------
Item {
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Layout.preferredHeight: CallStyle.actionArea.height
visible: !hideButtons
GridLayout {
anchors {
left: parent.left
leftMargin: CallStyle.actionArea.leftButtonsGroupMargin
verticalCenter: parent.verticalCenter
}
rowSpacing: ActionBarStyle.spacing
Row {
spacing: CallStyle.actionArea.vu.spacing
visible: SettingsModel.muteMicrophoneEnabled
VuMeter {
Timer {
interval: 50
repeat: true
running: micro.enabled
onTriggered: parent.value = call.microVu
}
enabled: micro.enabled
}
ActionSwitch {
id: micro
enabled: !call.microMuted
icon: 'micro'
iconSize: CallStyle.actionArea.iconSize
onClicked: call.microMuted = enabled
}
}
Row {
spacing: CallStyle.actionArea.vu.spacing
VuMeter {
Timer {
interval: 50
repeat: true
running: speaker.enabled
onTriggered: parent.value = call.speakerVu
}
enabled: speaker.enabled
}
ActionSwitch {
id: speaker
enabled: true
icon: 'speaker'
iconSize: CallStyle.actionArea.iconSize
onClicked: console.log('TODO')
}
}
ActionSwitch {
enabled: true
icon: 'camera'
iconSize: CallStyle.actionArea.iconSize
updating: call.updating
onClicked: window.exit(function () { call.videoEnabled = false })
}
ActionButton {
Layout.preferredHeight: CallStyle.actionArea.iconSize
Layout.preferredWidth: CallStyle.actionArea.iconSize
icon: 'options'
iconSize: CallStyle.actionArea.iconSize
onClicked: Logic.openMediaParameters()
}
}
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
visible: SettingsModel.callPauseEnabled
onClicked: window.exit(function () { call.pausedByUser = enabled })
}
ActionButton {
icon: 'hangup'
onClicked: window.exit(call.terminate)
}
}
}
}
}
// ---------------------------------------------------------------------------
// Preview.
// ---------------------------------------------------------------------------
Loader {
active: {
var caller = window.caller
return caller && !caller.cameraActivated
}
sourceComponent: cameraPreview
Component {
id: cameraPreview
Camera {
property bool scale: false
function xPosition () {
return window.width / 2 - width / 2
}
function yPosition () {
return window.height - height
}
call: window.call
isPreview: true
height: CallStyle.actionArea.userVideo.height * (scale ? 2 : 1)
width: CallStyle.actionArea.userVideo.width * (scale ? 2 : 1)
DragBox {
container: window
draggable: parent
xPosition: parent.xPosition
yPosition: parent.yPosition
onWheel: parent.scale = wheel.angleDelta.y > 0
}
}
}
}
// ---------------------------------------------------------------------------
// TelKeypad.
// ---------------------------------------------------------------------------
TelKeypad {
id: telKeypad
call: window.call
visible: false
}
}