From 13e4822e2c1cea7fdded2217cbd93a3ad0156e9b Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Wed, 24 May 2017 14:19:45 +0200 Subject: [PATCH] feat(ui/views/App/Calls/ConferenceManager): in progress --- linphone-desktop/assets/languages/en.ts | 11 + linphone-desktop/assets/languages/fr.ts | 11 + linphone-desktop/resources.qrc | 1 + .../src/components/call/CallModel.cpp | 20 +- .../components/conference/ConferenceModel.cpp | 61 +++++ .../components/conference/ConferenceModel.hpp | 20 ++ .../ui/views/App/Calls/Conference.qml | 216 ++++++++++++++++++ 7 files changed, 331 insertions(+), 9 deletions(-) create mode 100644 linphone-desktop/ui/views/App/Calls/Conference.qml diff --git a/linphone-desktop/assets/languages/en.ts b/linphone-desktop/assets/languages/en.ts index d28e5bb8a..d95f0da50 100644 --- a/linphone-desktop/assets/languages/en.ts +++ b/linphone-desktop/assets/languages/en.ts @@ -357,6 +357,17 @@ Server url not configured. Status + + Conference + + conferenceTitle + CONFERENCE + + + pendingRequestLabel + Please to wait, a request is pending. + + ConferenceManager diff --git a/linphone-desktop/assets/languages/fr.ts b/linphone-desktop/assets/languages/fr.ts index 4e9643974..3e93740b9 100644 --- a/linphone-desktop/assets/languages/fr.ts +++ b/linphone-desktop/assets/languages/fr.ts @@ -357,6 +357,17 @@ Url du serveur non configurée. Status + + Conference + + conferenceTitle + CONFÉRENCE + + + pendingRequestLabel + Merci de patienter, une requête est en attente. + + ConferenceManager diff --git a/linphone-desktop/resources.qrc b/linphone-desktop/resources.qrc index 5be4da53f..8cb03098b 100644 --- a/linphone-desktop/resources.qrc +++ b/linphone-desktop/resources.qrc @@ -355,6 +355,7 @@ ui/views/App/Calls/CallsWindow.js ui/views/App/Calls/CallsWindow.qml ui/views/App/Calls/ConferenceManager.qml + ui/views/App/Calls/Conference.qml ui/views/App/Calls/EndedCall.qml ui/views/App/Calls/IncallFullscreenWindow.qml ui/views/App/Calls/Incall.js diff --git a/linphone-desktop/src/components/call/CallModel.cpp b/linphone-desktop/src/components/call/CallModel.cpp index e170a02aa..d5f6fcdd7 100644 --- a/linphone-desktop/src/components/call/CallModel.cpp +++ b/linphone-desktop/src/components/call/CallModel.cpp @@ -79,9 +79,10 @@ QString CallModel::getSipAddress () const { void CallModel::setRecordFile (shared_ptr &callParams) { callParams->setRecordFile( ::Utils::qStringToLinphoneString( - CoreManager::getInstance()->getSettingsModel()->getSavedVideosFolder() + - QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss") - ) + ".mkv" + QStringLiteral("%1%2.mkv") + .arg(CoreManager::getInstance()->getSettingsModel()->getSavedVideosFolder()) + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss")) + ) ); } @@ -183,14 +184,15 @@ void CallModel::startRecording () { } void CallModel::stopRecording () { - if (mRecording) { - qInfo() << QStringLiteral("Stop recording call:") << this; + if (!mRecording) + return; - mRecording = false; - mCall->stopRecording(); + qInfo() << QStringLiteral("Stop recording call:") << this; - emit recordingChanged(false); - } + mRecording = false; + mCall->stopRecording(); + + emit recordingChanged(false); } // ----------------------------------------------------------------------------- diff --git a/linphone-desktop/src/components/conference/ConferenceModel.cpp b/linphone-desktop/src/components/conference/ConferenceModel.cpp index 5bdbefb38..8ecd9cb1a 100644 --- a/linphone-desktop/src/components/conference/ConferenceModel.cpp +++ b/linphone-desktop/src/components/conference/ConferenceModel.cpp @@ -20,8 +20,15 @@ * Author: Ronan Abhamon */ +#include + +#include "../../Utils.hpp" +#include "../core/CoreManager.hpp" + #include "ConferenceModel.hpp" +using namespace std; + // ============================================================================= ConferenceModel::ConferenceModel (QObject *parent) : QAbstractListModel(parent) {} @@ -47,3 +54,57 @@ QVariant ConferenceModel::data (const QModelIndex &index, int role) const { return QVariant(); } + +// ----------------------------------------------------------------------------- + +void ConferenceModel::startRecording () { + if (mRecording) + return; + + qInfo() << QStringLiteral("Start recording conference:") << this; + + CoreManager *coreManager = CoreManager::getInstance(); + coreManager->getCore()->startConferenceRecording( + ::Utils::qStringToLinphoneString( + QStringLiteral("%1%2.mkv") + .arg(coreManager->getSettingsModel()->getSavedVideosFolder()) + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss")) + ) + ); + mRecording = true; + + emit recordingChanged(true); +} + +void ConferenceModel::stopRecording () { + if (!mRecording) + return; + + qInfo() << QStringLiteral("Stop recording conference:") << this; + + mRecording = false; + CoreManager::getInstance()->getCore()->stopConferenceRecording(); + + emit recordingChanged(false); +} + +// ----------------------------------------------------------------------------- + +bool ConferenceModel::getMicroMuted () const { + return !CoreManager::getInstance()->getCore()->micEnabled(); +} + +void ConferenceModel::setMicroMuted (bool status) { + shared_ptr core = CoreManager::getInstance()->getCore(); + + if (status == core->micEnabled()) { + core->enableMic(!status); + emit microMutedChanged(status); + } +} + +// ----------------------------------------------------------------------------- + +bool ConferenceModel::getRecording () const { + return mRecording; +} diff --git a/linphone-desktop/src/components/conference/ConferenceModel.hpp b/linphone-desktop/src/components/conference/ConferenceModel.hpp index 72e930d35..ab06e3bd1 100644 --- a/linphone-desktop/src/components/conference/ConferenceModel.hpp +++ b/linphone-desktop/src/components/conference/ConferenceModel.hpp @@ -28,6 +28,12 @@ // ============================================================================= class ConferenceModel : public QAbstractListModel { + Q_OBJECT; + + Q_PROPERTY(bool microMuted READ getMicroMuted WRITE setMicroMuted NOTIFY microMutedChanged); + + Q_PROPERTY(bool recording READ getRecording NOTIFY recordingChanged); + public: ConferenceModel (QObject *parent = Q_NULLPTR); ~ConferenceModel () = default; @@ -37,7 +43,21 @@ public: QHash roleNames () const override; QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; + Q_INVOKABLE void startRecording (); + Q_INVOKABLE void stopRecording (); + +signals: + void microMutedChanged (bool status); + void recordingChanged (bool status); + private: + bool getMicroMuted () const; + void setMicroMuted (bool status); + + bool getRecording () const; + + bool mRecording = false; + QStringList mSipAddresses; }; diff --git a/linphone-desktop/ui/views/App/Calls/Conference.qml b/linphone-desktop/ui/views/App/Calls/Conference.qml new file mode 100644 index 000000000..22e5b55fc --- /dev/null +++ b/linphone-desktop/ui/views/App/Calls/Conference.qml @@ -0,0 +1,216 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.3 + +import Common 1.0 +import Linphone 1.0 +import LinphoneUtils 1.0 +import Utils 1.0 + +import App.Styles 1.0 + +//import 'Conference.js' as Logic + +// ============================================================================= + +Rectangle { + property var call: null // TODO: Remove me + + color: CallStyle.backgroundColor + + // --------------------------------------------------------------------------- + + ConferenceModel { + id: conference + } + + ColumnLayout { + anchors { + fill: parent + topMargin: CallStyle.header.topMargin + } + + spacing: 0 + + // ------------------------------------------------------------------------- + // Call info. + // ------------------------------------------------------------------------- + + Item { + id: info + + Layout.fillWidth: true + Layout.leftMargin: CallStyle.header.leftMargin + Layout.rightMargin: CallStyle.header.rightMargin + Layout.preferredHeight: CallStyle.header.conferenceDescription.height + + ActionBar { + id: leftActions + + anchors.left: parent.left + iconSize: CallStyle.header.iconSize + } + + Text { + id: conferenceDescription + + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + text: qsTr('conferenceTitle') + + height: parent.height + width: parent.width - rightActions.width - leftActions.width - CallStyle.header.conferenceDescription.width + } + + // ----------------------------------------------------------------------- + // Video actions. + // ----------------------------------------------------------------------- + + ActionBar { + id: rightActions + + anchors.right: parent.right + iconSize: CallStyle.header.iconSize + + ActionSwitch { + enabled: conference.recording + icon: 'record' + useStates: false + + onClicked: !enabled + ? conference.startRecording() + : conference.stopRecording() + } + } + } + + Text { + id: elapsedTime + + Layout.fillWidth: true + color: CallStyle.header.elapsedTime.color + font.pointSize: CallStyle.header.elapsedTime.fontSize + horizontalAlignment: Text.AlignHCenter + + Timer { + interval: 1000 + repeat: true + running: true + triggeredOnStart: true + + onTriggered: elapsedTime.text = Utils.formatElapsedTime(conference.duration) + } + } + + // ------------------------------------------------------------------------- + // Contacts visual. + // ------------------------------------------------------------------------- + + Item { + id: container + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.margins: CallStyle.container.margins + } + + // ------------------------------------------------------------------------- + // Action Buttons. + // ------------------------------------------------------------------------- + + Item { + Layout.fillWidth: true + Layout.preferredHeight: CallStyle.actionArea.height + + RowLayout { + anchors { + left: parent.left + leftMargin: CallStyle.actionArea.leftButtonsGroupMargin + verticalCenter: parent.verticalCenter + } + + spacing: ActionBarStyle.spacing + + Row { + spacing: CallStyle.actionArea.vu.spacing + + VuMeter { + Timer { + interval: 50 + repeat: true + running: micro.enabled + + onTriggered: parent.value = conference.microVu + } + + enabled: micro.enabled + } + + ActionSwitch { + id: micro + + enabled: !conference.microMuted + icon: 'micro' + iconSize: CallStyle.actionArea.iconSize + + onClicked: conference.microMuted = enabled + } + } + + Row { + spacing: CallStyle.actionArea.vu.spacing + + VuMeter { + Timer { + interval: 50 + repeat: true + running: speaker.enabled + + onTriggered: parent.value = conference.speakerVu + } + + enabled: speaker.enabled + } + + ActionSwitch { + id: speaker + + enabled: true + icon: 'speaker' + iconSize: CallStyle.actionArea.iconSize + + onClicked: console.log('TODO') + } + } + } + + ActionBar { + anchors { + right: parent.right + rightMargin: CallStyle.actionArea.rightButtonsGroupMargin + verticalCenter: parent.verticalCenter + } + iconSize: CallStyle.actionArea.iconSize + + ActionSwitch { + enabled: !conference.pausedByUser + icon: 'pause' + updating: conference.updating + + onClicked: conference.pausedByUser = enabled + + TooltipArea { + text: qsTr('pendingRequestLabel') + visible: parent.updating + } + } + + ActionButton { + icon: 'hangup' + + onClicked: conference.terminate() + } + } + } + } +}