Skip to content
Snippets Groups Projects
RecordBox.qml 8.09 KiB
Newer Older
/*
 * Copyright (C) 2020 by Savoir-faire Linux
 * Author: Albert Babí <albert.babi@savoirfairelinux.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

import QtQuick 2.15
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.3
import QtGraphicalEffects 1.0
import net.jami.Models 1.0
import "../../commoncomponents"


Rectangle {

    enum States {
        INIT,
        RECORDING,
        REC_SUCCESS
    }

    id:recBox
    color: "#FFFFFF"
    width: 320
    height: 240
    radius: 5
    border.color: JamiTheme.tabbarBorderColor

    property string pathRecorder: ""
    property string timeText: "00:00"
    property int duration: 0
    property int state: RecordBox.States.INIT
    property bool isVideo: false
    property bool previewAvailable: false

    property int h_offset: -65
    property int v_offset: -65

    function openRecorder(set_x, set_y, vid) {
        focus = true
        visible = true
        x = set_x+(width/2)+h_offset
        y = set_y-(height/2)+v_offset

        updateState(RecordBox.States.INIT)

        isVideo = vid
        if (isVideo){
            ClientWrapper.accountAdaptor.startPreviewing(false)
            previewAvailable = true
        }
    }

    onActiveFocusChanged:  {
        if (visible) {
            closeRecorder()
        }
    }

    onVisibleChanged: {
        if(!visible) {
            closeRecorder()
        }
    }

    function closeRecorder() {
        if (isVideo && ClientWrapper.accountAdaptor.isPreviewing()) {
            ClientWrapper.accountAdaptor.stopPreviewing()
        }
        stopRecording()
        visible = false
    }

    function updateState(new_state) {
        state = new_state
        recordButton.visible = (state == RecordBox.States.INIT)
        btnStop.visible = (state == RecordBox.States.RECORDING)
        btnRestart.visible = (state == RecordBox.States.REC_SUCCESS)
        btnSend.visible = (state == RecordBox.States.REC_SUCCESS)

        if (state == RecordBox.States.INIT) {
            duration = 0
            time.text = "00:00"
            timer.stop()
        } else if (state == RecordBox.States.REC_SUCCESS) {
            timer.stop()
        }
    }

    function startRecording() {
        timer.start()
        pathRecorder = ClientWrapper.avmodel.startLocalRecorder(!isVideo)
        if (pathRecorder == "") {
            timer.stop()
        }
    }

    function stopRecording() {
        if (pathRecorder !=  "") {
            ClientWrapper.avmodel.stopLocalRecorder(pathRecorder)
        }
    }

    function sendRecord() {
        if (pathRecorder != "") {
            MessagesAdapter.sendFile(pathRecorder)
        }
    }

    function updateTimer() {

        duration += 1

        var m = Math.trunc(duration / 60)
        var s = (duration % 60)

        var min = (m < 10) ? "0" + String(m) : String(m)
        var sec = (s < 10) ? "0" + String(s) : String(s)

        time.text = min + ":" + sec;
    }


    Connections{
        target: ClientWrapper.renderManager
    }

    Rectangle {
        id: rectBox
        visible: (isVideo && previewAvailable)
        Layout.alignment: Qt.AlignHCenter
        anchors.fill: parent
        color: "black"
        radius: 5

        PreviewRenderer{
            id: previewWidget
            anchors.fill: rectBox
            anchors.centerIn: rectBox
            layer.enabled: true
            layer.effect: OpacityMask {
                maskSource: rectBox
            }
        }
    }

    Label {
        visible: (isVideo && !previewAvailable)

        Layout.fillWidth: true
        Layout.alignment: Qt.AlignCenter

        text: qsTr("Preview unavailable")
        font.pointSize: 10
        font.kerning: true
    }

    Timer {
        id: timer
        interval: 1000;
        running: false;
        repeat: true
        onTriggered: updateTimer()
    }

    Text {
        id: time
        visible: true
        text: "00:00"
        color: (isVideo ? "white" : "black")
        font.pointSize: (isVideo ? 12 : 20)
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: (isVideo ? 100 : 0)
        anchors.verticalCenter: parent.verticalCenter
        anchors.verticalCenterOffset: (isVideo ? 100 : 0)
    }


    HoverableRadiusButton {
        id: recordButton
        Layout.maximumWidth: 30
        Layout.preferredWidth: 30
        Layout.minimumWidth: 30

        Layout.maximumHeight: 30
        Layout.preferredHeight: 30
        Layout.minimumHeight: 30

        buttonImageHeight: height
        buttonImageWidth: height
        backgroundColor: isVideo? "#000000cc" : "white"

        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5

        radius: height / 2

        icon.source: "qrc:/images/icons/av_icons/fiber_manual_record-24px.svg"
        icon.height: 24
        icon.width: 24
        icon.color: "#dc2719"
        onClicked: {
            updateState(RecordBox.States.RECORDING)
            startRecording()
        }
    }

    HoverableRadiusButton {
        id: btnStop
        Layout.maximumWidth: 30
        Layout.preferredWidth: 30
        Layout.minimumWidth: 30

        Layout.maximumHeight: 30
        Layout.preferredHeight: 30
        Layout.minimumHeight: 30

        buttonImageHeight: height
        buttonImageWidth: height
        backgroundColor: isVideo? "#000000cc" : "white"

        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5

        radius: height / 2

        icon.source: "qrc:/images/icons/av_icons/stop-24px-red.svg"
        icon.height: 24
        icon.width: 24
        icon.color: isVideo? "white" : "black"
        onClicked: {
            stopRecording()
            updateState(RecordBox.States.REC_SUCCESS)
        }
    }

    HoverableRadiusButton {
        id: btnRestart
        Layout.maximumWidth: 30
        Layout.preferredWidth: 30
        Layout.minimumWidth: 30

        Layout.maximumHeight: 30
        Layout.preferredHeight: 30
        Layout.minimumHeight: 30

        buttonImageHeight: height
        buttonImageWidth: height
        backgroundColor: isVideo? "#000000cc" : "white"

        anchors.horizontalCenter: parent.horizontalCenter
        anchors.right: btnRestart.left
        anchors.rightMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5

        radius: height / 2

        icon.source: "qrc:/images/icons/av_icons/re-record-24px.svg"
        icon.height: 24
        icon.width: 24
        icon.color: isVideo? "white" : "black"
        onClicked: {
            stopRecording()
            updateState(RecordBox.States.INIT)
        }
    }

    HoverableRadiusButton {
        id: btnSend
        Layout.maximumWidth: 30
        Layout.preferredWidth: 30
        Layout.minimumWidth: 30

        Layout.maximumHeight: 30
        Layout.preferredHeight: 30
        Layout.minimumHeight: 30

        buttonImageHeight: height
        buttonImageWidth: height
        backgroundColor: isVideo? "#000000cc" : "white"

        anchors.left: btnRestart.right
        anchors.leftMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5

        radius: height / 2

        icon.source: "qrc:/images/icons/av_icons/send-24px.svg"
        icon.height: 24
        icon.width: 24
        icon.color: isVideo? "white" : "black"
        onClicked: {
            stopRecording()
            sendRecord()
            closeRecorder()
            updateState(RecordBox.States.INIT)
        }
    }
}