mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-28 09:19:19 +00:00
feat(ui/views/App/Calls/Incall): supports screenshots, video recording
This commit is contained in:
parent
222f88109c
commit
677712e854
12 changed files with 110 additions and 53 deletions
|
Before Width: | Height: | Size: 1,014 B After Width: | Height: | Size: 1,014 B |
|
Before Width: | Height: | Size: 1,008 B After Width: | Height: | Size: 1,008 B |
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>record_over</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="record_over">
|
||||
<path d="M20,40 C31.045695,40 40,31.045695 40,20 C40,8.954305 31.045695,0 20,0 C8.954305,0 0,8.954305 0,20 C0,31.045695 8.954305,40 20,40 Z" fill="#E8E8E8" opacity="0.85"></path>
|
||||
<circle stroke="#FF5E00" cx="19.5" cy="15.5" r="5"></circle>
|
||||
<circle fill="#FF5E00" cx="19.5" cy="15.5" r="3"></circle>
|
||||
<text font-family="Arial-BoldMT, Arial" font-size="8" font-weight="bold" fill="#FF5E00">
|
||||
<tspan x="11.5546875" y="29.5">REC</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1,008 B |
|
|
@ -359,10 +359,6 @@ Server url not configured.</translation>
|
|||
</context>
|
||||
<context>
|
||||
<name>Incall</name>
|
||||
<message>
|
||||
<source>saveScreenshotTitle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>acceptVideoDescription</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
|
|||
|
|
@ -347,10 +347,6 @@ Url du serveur non configurée.</translation>
|
|||
</context>
|
||||
<context>
|
||||
<name>Incall</name>
|
||||
<message>
|
||||
<source>saveScreenshotTitle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>acceptVideoDescription</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
|
|||
|
|
@ -127,9 +127,8 @@
|
|||
<file>assets/images/pause_on_normal.svg</file>
|
||||
<file>assets/images/pause_on_pressed.svg</file>
|
||||
<file>assets/images/pause_on_updating.svg</file>
|
||||
<file>assets/images/record_hovered.svg</file>
|
||||
<file>assets/images/record_normal.svg</file>
|
||||
<file>assets/images/record_pressed.svg</file>
|
||||
<file>assets/images/record_off.svg</file>
|
||||
<file>assets/images/record_on.svg</file>
|
||||
<file>assets/images/screenshot_hovered.svg</file>
|
||||
<file>assets/images/screenshot_normal.svg</file>
|
||||
<file>assets/images/screenshot_pressed.svg</file>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#endif // ifdef _WIN32
|
||||
|
||||
#define PATH_AVATARS (LINPHONE_FOLDER "avatars/")
|
||||
#define PATH_CAPTURES (LINPHONE_FOLDER "captures/")
|
||||
#define PATH_LOGS (LINPHONE_FOLDER "logs/")
|
||||
#define PATH_THUMBNAILS (LINPHONE_FOLDER "thumbnails/")
|
||||
|
||||
|
|
@ -92,3 +93,7 @@ string Paths::getMessageHistoryFilepath () {
|
|||
string Paths::getThumbnailsDirPath () {
|
||||
return getDirectoryPath(MAIN_PATH + PATH_THUMBNAILS);
|
||||
}
|
||||
|
||||
string Paths::getCapturesDirPath () {
|
||||
return getDirectoryPath(MAIN_PATH + PATH_CAPTURES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace Paths {
|
|||
std::string getCallHistoryFilepath ();
|
||||
std::string getConfigFilepath ();
|
||||
std::string getFriendsListFilepath ();
|
||||
std::string getCapturesDirPath ();
|
||||
std::string getLogsDirpath ();
|
||||
std::string getMessageHistoryFilepath ();
|
||||
std::string getThumbnailsDirPath ();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "../../app/Paths.hpp"
|
||||
#include "../../utils.hpp"
|
||||
#include "../core/CoreManager.hpp"
|
||||
|
||||
|
|
@ -61,6 +65,17 @@ CallModel::CallModel (shared_ptr<linphone::Call> linphone_call) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CallModel::setRecordFile (shared_ptr<linphone::CallParams> &call_params) {
|
||||
call_params->setRecordFile(
|
||||
Paths::getCapturesDirPath() +
|
||||
::Utils::qStringToLinphoneString(
|
||||
QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss")
|
||||
) + ".mkv"
|
||||
);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CallModel::accept () {
|
||||
CoreManager::getInstance()->getCore()->acceptCall(m_linphone_call);
|
||||
}
|
||||
|
|
@ -78,8 +93,9 @@ void CallModel::transfer () {
|
|||
}
|
||||
|
||||
void CallModel::acceptVideoRequest () {
|
||||
shared_ptr<linphone::CallParams> params = m_linphone_call->getCurrentParams()->copy();
|
||||
shared_ptr<linphone::CallParams> params = CoreManager::getInstance()->getCore()->createCallParams(m_linphone_call);
|
||||
params->enableVideo(true);
|
||||
|
||||
CoreManager::getInstance()->getCore()->acceptCallUpdate(m_linphone_call, params);
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +103,47 @@ void CallModel::rejectVideoRequest () {
|
|||
CoreManager::getInstance()->getCore()->acceptCallUpdate(m_linphone_call, m_linphone_call->getCurrentParams());
|
||||
}
|
||||
|
||||
void CallModel::takeSnapshot () {
|
||||
static QString old_name;
|
||||
QString new_name = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss") + ".jpg";
|
||||
|
||||
if (new_name == old_name) {
|
||||
qWarning() << "Unable to take snapshot. Wait one second.";
|
||||
return;
|
||||
}
|
||||
|
||||
old_name = new_name;
|
||||
|
||||
qInfo() << "Take snapshot of call:" << &m_linphone_call;
|
||||
|
||||
m_linphone_call->takeVideoSnapshot(
|
||||
Paths::getCapturesDirPath() + ::Utils::qStringToLinphoneString(new_name)
|
||||
);
|
||||
}
|
||||
|
||||
void CallModel::startRecording () {
|
||||
if (m_recording)
|
||||
return;
|
||||
|
||||
qInfo() << "Start recording call:" << &m_linphone_call;
|
||||
|
||||
m_linphone_call->startRecording();
|
||||
m_recording = true;
|
||||
|
||||
emit recordingChanged(true);
|
||||
}
|
||||
|
||||
void CallModel::stopRecording () {
|
||||
if (m_recording) {
|
||||
qInfo() << "Stop recording call:" << &m_linphone_call;
|
||||
|
||||
m_recording = false;
|
||||
m_linphone_call->stopRecording();
|
||||
|
||||
emit recordingChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
QString CallModel::getSipAddress () const {
|
||||
|
|
@ -215,3 +272,7 @@ bool CallModel::getUpdating () const {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CallModel::getRecording () const {
|
||||
return m_recording;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ class CallModel : public QObject {
|
|||
Q_PROPERTY(bool videoEnabled READ getVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged);
|
||||
Q_PROPERTY(bool updating READ getUpdating NOTIFY statusChanged)
|
||||
|
||||
Q_PROPERTY(bool recording READ getRecording NOTIFY recordingChanged);
|
||||
|
||||
public:
|
||||
enum CallStatus {
|
||||
CallStatusConnected,
|
||||
|
|
@ -40,6 +42,8 @@ public:
|
|||
return m_linphone_call;
|
||||
}
|
||||
|
||||
static void setRecordFile (shared_ptr<linphone::CallParams> &call_params);
|
||||
|
||||
Q_INVOKABLE void accept ();
|
||||
Q_INVOKABLE void acceptWithVideo ();
|
||||
Q_INVOKABLE void terminate ();
|
||||
|
|
@ -48,10 +52,16 @@ public:
|
|||
Q_INVOKABLE void acceptVideoRequest ();
|
||||
Q_INVOKABLE void rejectVideoRequest ();
|
||||
|
||||
Q_INVOKABLE void takeSnapshot ();
|
||||
|
||||
Q_INVOKABLE void startRecording ();
|
||||
Q_INVOKABLE void stopRecording ();
|
||||
|
||||
signals:
|
||||
void statusChanged (CallStatus status);
|
||||
void microMutedChanged (bool status);
|
||||
void videoRequested ();
|
||||
void recordingChanged (bool status);
|
||||
|
||||
private:
|
||||
QString getSipAddress () const;
|
||||
|
|
@ -75,9 +85,12 @@ private:
|
|||
|
||||
bool getUpdating () const;
|
||||
|
||||
bool getRecording () const;
|
||||
|
||||
bool m_micro_muted = false;
|
||||
bool m_paused_by_remote = false;
|
||||
bool m_paused_by_user = false;
|
||||
bool m_recording = false;
|
||||
|
||||
std::shared_ptr<linphone::Call> m_linphone_call;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ void CallsListModel::launchAudioCall (const QString &sip_uri) const {
|
|||
|
||||
shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
|
||||
params->enableVideo(false);
|
||||
CallModel::setRecordFile(params);
|
||||
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
|
|
@ -84,6 +85,7 @@ void CallsListModel::launchVideoCall (const QString &sip_uri) const {
|
|||
shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
|
||||
params->enableEarlyMediaSending(true);
|
||||
params->enableVideo(true);
|
||||
CallModel::setRecordFile(params);
|
||||
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,19 @@ Rectangle {
|
|||
Component.onCompleted: this.connect(call, 'videoRequested', function () {
|
||||
var dialog
|
||||
|
||||
// Close window if call is ended.
|
||||
// Close dialog after 10s.
|
||||
var timeout = Utils.setTimeout(incall, 10000, function () {
|
||||
call.statusChanged.disconnect(endedHandler)
|
||||
dialog.close()
|
||||
call.rejectVideoRequest()
|
||||
})
|
||||
|
||||
// Close dialog if call is ended.
|
||||
var endedHandler = function (status) {
|
||||
if (status === CallModel.CallStatusEnded) {
|
||||
dialog.close()
|
||||
Utils.clearTimeout(timeout)
|
||||
call.statusChanged.disconnect(endedHandler)
|
||||
dialog.close()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +54,7 @@ Rectangle {
|
|||
dialog = Utils.openConfirmDialog(window, {
|
||||
descriptionText: qsTr('acceptVideoDescription'),
|
||||
exitHandler: function (status) {
|
||||
Utils.clearTimeout(timeout)
|
||||
call.statusChanged.disconnect(endedHandler)
|
||||
|
||||
if (status) {
|
||||
|
|
@ -118,43 +127,37 @@ Rectangle {
|
|||
width: parent.width - cameraActions.width - callQuality.width - CallStyle.header.contactDescription.width
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Video actions.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Loader {
|
||||
id: cameraActions
|
||||
|
||||
anchors.right: parent.right
|
||||
active: call.videoEnabled && call.status !== CallModel.CallStatusEnded
|
||||
active: call.status !== CallModel.CallStatusEnded
|
||||
|
||||
sourceComponent: ActionBar {
|
||||
iconSize: CallStyle.header.iconSize
|
||||
|
||||
ActionButton {
|
||||
icon: 'screenshot'
|
||||
visible: call.videoEnabled
|
||||
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
|
||||
folder: shortcuts.home
|
||||
selectExisting: false
|
||||
title: qsTr('saveScreenshotTitle')
|
||||
|
||||
onAccepted: cameraLoader.item.saveScreenshot(fileUrl)
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
// TODO: At this moment, FileDialog does not support default filename, use this name in the future:
|
||||
//'linphone ' + ((new Date()).toLocaleString(Qt.locale(), 'yyyy-MM-dd hh:mm:ss')) + '.jpg'
|
||||
|
||||
cameraLoader.item.takeScreenshot()
|
||||
fileDialog.open()
|
||||
}
|
||||
onClicked: call.takeSnapshot()
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
ActionSwitch {
|
||||
enabled: call.recording
|
||||
icon: 'record'
|
||||
useStates: false
|
||||
|
||||
onClicked: !enabled ? call.startRecording() : call.stopRecording()
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
icon: 'fullscreen'
|
||||
visible: call.videoEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -242,15 +245,13 @@ Rectangle {
|
|||
}
|
||||
|
||||
Loader {
|
||||
id: cameraLoader
|
||||
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: call.videoEnabled ? camera : avatar
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Buttons.
|
||||
// Action Buttons.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Item {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue