1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-04-21 21:52:03 +02:00

callview: implement an observable object to detail the current call

Change-Id: Ic7025f66e472457e32149911053c8ff32e06bf21
This commit is contained in:
Aline Gondim Santos 2022-12-16 11:35:12 -03:00
parent fc91cdc23c
commit ce6c7dc02b
22 changed files with 572 additions and 333 deletions

View file

@ -221,7 +221,7 @@ set(COMMON_SOURCES
${APP_SRC_DIR}/callparticipantsmodel.cpp
${APP_SRC_DIR}/tipsmodel.cpp
${APP_SRC_DIR}/positioning.cpp
)
${APP_SRC_DIR}/currentcall.cpp)
set(COMMON_HEADERS
${APP_SRC_DIR}/avatarimageprovider.h
@ -280,7 +280,8 @@ set(COMMON_HEADERS
${APP_SRC_DIR}/videoprovider.h
${APP_SRC_DIR}/callparticipantsmodel.h
${APP_SRC_DIR}/tipsmodel.h
${APP_SRC_DIR}/positioning.h)
${APP_SRC_DIR}/positioning.h
${APP_SRC_DIR}/currentcall.h)
if(WITH_WEBENGINE)
list(APPEND COMMON_SOURCES

@ -1 +0,0 @@
Subproject commit 2195ee0883efc92828a0cf33b830f43f9bd7e01b

View file

@ -238,7 +238,6 @@ CallAdapter::onCallStatusChanged(const QString& callId, int code)
const auto& convInfo = lrcInstance_->getConversationFromCallId(callId);
if (!convInfo.uid.isEmpty()) {
Q_EMIT callStatusChanged(static_cast<int>(call.status), accountId_, convInfo.uid);
updateCallOverlay(convInfo);
}
switch (call.status) {
@ -330,25 +329,11 @@ CallAdapter::onCallInfosChanged(const QString& accountId, const QString& callId)
}
Q_EMIT callInfosChanged(call.isAudioOnly, accountId, convInfo.uid);
participantsModel_->setConferenceLayout(static_cast<int>(call.layout), callId);
updateCallOverlay(convInfo);
}
} catch (...) {
}
}
void
CallAdapter::onRemoteRecordingChanged(const QString& callId,
const QSet<QString>& peerRec,
bool state)
{
Q_UNUSED(peerRec)
Q_UNUSED(state)
const auto currentCallId
= lrcInstance_->getCallIdForConversationUid(lrcInstance_->get_selectedConvUid(), accountId_);
if (callId == currentCallId)
updateRecordingPeers();
}
void
CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
{
@ -511,8 +496,6 @@ CallAdapter::updateCall(const QString& convUid, const QString& accountId, bool f
}
}
updateCallOverlay(convInfo);
updateRecordingPeers(true);
participantsModel_->setParticipants(call->id, getConferencesInfos());
participantsModel_->setConferenceLayout(static_cast<int>(call->layout), call->id);
}
@ -569,7 +552,6 @@ CallAdapter::getConferencesInfos() const
.getAccountInfo(accountId_)
.callModel.get()
->getParticipantsInfos(callId);
int index = 0;
for (int index = 0; index < participantsModel.getParticipants().size(); index++) {
auto participant = participantsModel.toQJsonObject(index);
fillParticipantData(participant);
@ -642,12 +624,6 @@ CallAdapter::connectCallModel(const QString& accountId)
QOverload<const QString&, int>::of(&CallAdapter::onCallStatusChanged),
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::remoteRecordingChanged,
this,
&CallAdapter::onRemoteRecordingChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::callAddedToConference,
this,
@ -660,32 +636,6 @@ CallAdapter::connectCallModel(const QString& accountId)
QOverload<const QString&, const QString&>::of(&CallAdapter::onCallInfosChanged));
}
void
CallAdapter::updateRecordingPeers(bool eraseLabelOnEmpty)
{
const auto& convInfo = lrcInstance_->getConversationFromConvUid(
lrcInstance_->get_selectedConvUid());
auto* call = lrcInstance_->getCallInfoForConversation(convInfo);
if (!call) {
return;
}
const auto& accInfo = lrcInstance_->getCurrentAccountInfo();
QStringList peers {};
for (const auto& uri : call->peerRec) {
auto bestName = accInfo.contactModel->bestNameForContact(uri);
if (!bestName.isEmpty()) {
peers.append(bestName);
}
}
if (!peers.isEmpty())
Q_EMIT remoteRecordingChanged(peers, true);
else if (eraseLabelOnEmpty)
Q_EMIT eraseRemoteRecording();
else
Q_EMIT remoteRecordingChanged(peers, false);
}
void
CallAdapter::sipInputPanelPlayDTMF(const QString& key)
{
@ -698,49 +648,6 @@ CallAdapter::sipInputPanelPlayDTMF(const QString& key)
lrcInstance_->getCurrentCallModel()->playDTMF(callId, key);
}
/*
* For Call Overlay
*/
void
CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo)
{
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
auto* callModel = accInfo.callModel.get();
const auto* callInfo = lrcInstance_->getCallInfoForConversation(convInfo);
const auto currentCallId = lrcInstance_->getCurrentCallId();
if (!callInfo || callInfo->id != currentCallId)
return;
bool isPaused = callInfo->status == lrc::api::call::Status::PAUSED;
bool isAudioOnly = callInfo->isAudioOnly && !isPaused;
bool isAudioMuted = callInfo->status == lrc::api::call::Status::PAUSED;
bool isGrid = callInfo->layout == lrc::api::call::Layout::GRID;
QString previewId {};
if (callInfo->status != lrc::api::call::Status::ENDED) {
for (const auto& media : callInfo->mediaList) {
if (media[libjami::Media::MediaAttributeKey::MEDIA_TYPE]
== libjami::Media::Details::MEDIA_TYPE_VIDEO) {
if (media[libjami::Media::MediaAttributeKey::ENABLED] == TRUE_STR
&& media[libjami::Media::MediaAttributeKey::MUTED] == FALSE_STR) {
if (previewId.isEmpty()) {
previewId = media[libjami::Media::MediaAttributeKey::SOURCE];
}
}
} else if (media[libjami::Media::MediaAttributeKey::LABEL] == "audio_0") {
isAudioMuted |= media[libjami::Media::MediaAttributeKey::MUTED] == TRUE_STR;
}
}
}
Q_EMIT updateOverlay(isPaused,
isAudioOnly,
isAudioMuted,
accInfo.profileInfo.type == lrc::api::profile::Type::SIP,
isGrid,
previewId);
}
void
CallAdapter::saveConferenceSubcalls()
{
@ -1075,7 +982,6 @@ CallAdapter::holdThisCallToggle()
if (callModel->hasCall(callId)) {
callModel->togglePause(callId);
}
Q_EMIT showOnHoldLabel(true);
}
void

View file

@ -100,15 +100,6 @@ Q_SIGNALS:
// For Call Overlay
void updateTimeText(const QString& time);
void showOnHoldLabel(bool isPaused);
void updateOverlay(bool isPaused,
bool isAudioOnly,
bool isAudioMuted,
bool isSIP,
bool isGrid,
const QString& previewId);
void remoteRecordingChanged(const QStringList& peers, bool state);
void eraseRemoteRecording();
public Q_SLOTS:
void onShowIncomingCallView(const QString& accountId, const QString& convUid);
@ -117,18 +108,15 @@ public Q_SLOTS:
void onCallStatusChanged(const QString& accountId, const QString& callId);
void onCallInfosChanged(const QString& accountId, const QString& callId);
void onCallStatusChanged(const QString& callId, int code);
void onRemoteRecordingChanged(const QString& callId, const QSet<QString>& peerRec, bool state);
void onCallAddedToConference(const QString& callId, const QString& confId);
void onParticipantAdded(const QString& callId, int index);
void onParticipantRemoved(const QString& callId, int index);
void onParticipantUpdated(const QString& callId, int index);
private:
void updateRecordingPeers(bool eraseLabelOnEmpty = false);
void showNotification(const QString& accountId, const QString& convUid);
void fillParticipantData(QJsonObject& participant) const;
void preventScreenSaver(bool state);
void updateCallOverlay(const lrc::api::conversation::Info& convInfo);
void saveConferenceSubcalls();
QString accountId_;

308
src/app/currentcall.cpp Normal file
View file

@ -0,0 +1,308 @@
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* 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/>.
*/
#include "currentcall.h"
#include <api/callparticipantsmodel.h>
CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent)
: QObject(parent)
, lrcInstance_(lrcInstance)
{
connect(lrcInstance_,
&LRCInstance::currentAccountIdChanged,
this,
&CurrentCall::onCurrentAccountIdChanged);
connect(lrcInstance_,
&LRCInstance::selectedConvUidChanged,
this,
&CurrentCall::onCurrentConvIdChanged);
connectModel();
}
void
CurrentCall::updateId(QString callId)
{
auto convId = lrcInstance_->get_selectedConvUid();
auto optConv = lrcInstance_->getCurrentConversationModel()->getConversationForUid(convId);
if (!optConv.has_value()) {
return;
}
// If the optional parameter callId is empty, then we've just
// changed conversation selection and need to check the current
// conv's callId for an existing call.
// Otherwise, return if callId doesn't belong to this conversation.
if (callId.isEmpty()) {
callId = optConv->get().getCallId();
} else if (optConv->get().getCallId() != callId) {
return;
}
// Set the current id_ if there is a call.
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
if (accInfo.callModel->hasCall(callId)) {
set_id(callId);
}
}
void
CurrentCall::updateCallStatus()
{
call::Status status {};
auto callModel = lrcInstance_->getCurrentCallModel();
if (callModel->hasCall(id_)) {
auto callInfo = callModel->getCall(id_);
status = callInfo.status;
}
set_status(status);
set_isActive(status_ == call::Status::CONNECTED || status_ == call::Status::IN_PROGRESS
|| status_ == call::Status::PAUSED);
set_isPaused(status_ == call::Status::PAUSED);
}
void
CurrentCall::updateParticipants()
{
auto callModel = lrcInstance_->getCurrentCallModel();
QStringList uris;
auto& participantsModel = callModel->getParticipantsInfos(id_);
for (int index = 0; index < participantsModel.getParticipants().size(); index++) {
auto participantInfo = participantsModel.toQJsonObject(index);
uris.append(participantInfo[ParticipantsInfosStrings::URI].toString());
}
set_uris(uris);
set_isConference(uris.size());
}
void
CurrentCall::updateCallInfo()
{
auto callModel = lrcInstance_->getCurrentCallModel();
if (!callModel->hasCall(id_)) {
return;
}
auto callInfo = callModel->getCall(id_);
set_isGrid(callInfo.layout == call::Layout::GRID);
set_isAudioOnly(callInfo.isAudioOnly);
bool isAudioMuted {};
bool isVideoMuted {};
bool isSharing {};
bool isCapturing {};
QString previewId {};
using namespace libjami::Media;
if (callInfo.status != lrc::api::call::Status::ENDED) {
for (const auto& media : callInfo.mediaList) {
if (media[MediaAttributeKey::MEDIA_TYPE] == Details::MEDIA_TYPE_VIDEO) {
if (media[MediaAttributeKey::SOURCE].startsWith(VideoProtocolPrefix::DISPLAY)
|| media[MediaAttributeKey::SOURCE].startsWith(VideoProtocolPrefix::FILE)) {
isSharing = true;
}
if (media[MediaAttributeKey::ENABLED] == TRUE_STR
&& media[MediaAttributeKey::MUTED] == FALSE_STR && previewId.isEmpty()) {
previewId = media[libjami::Media::MediaAttributeKey::SOURCE];
}
if (media[libjami::Media::MediaAttributeKey::SOURCE].startsWith(
libjami::Media::VideoProtocolPrefix::CAMERA)) {
isVideoMuted |= media[MediaAttributeKey::MUTED] == TRUE_STR;
isCapturing = media[MediaAttributeKey::MUTED] == FALSE_STR;
}
} else if (media[MediaAttributeKey::MEDIA_TYPE] == Details::MEDIA_TYPE_AUDIO) {
if (media[MediaAttributeKey::LABEL] == "audio_0") {
isAudioMuted |= media[libjami::Media::MediaAttributeKey::MUTED] == TRUE_STR;
}
}
}
}
set_previewId(previewId);
set_isAudioMuted(isAudioMuted);
set_isVideoMuted(isVideoMuted);
set_isSharing(isSharing);
set_isCapturing(isCapturing);
set_isHandRaised(callModel->isHandRaised(id_));
set_isModerator(callModel->isModerator(id_));
}
void
CurrentCall::updateRemoteRecorders(const QStringList& recorders)
{
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
remoteRecorderNameList_.clear();
Q_FOREACH (const auto& uri, recorders) {
auto bestName = accInfo.contactModel->bestNameForContact(uri);
if (!bestName.isEmpty()) {
remoteRecorderNameList_.append(bestName);
}
}
// Convenience flag.
set_isRecordingRemotely(!remoteRecorderNameList_.isEmpty());
Q_EMIT remoteRecorderNameListChanged();
}
void
CurrentCall::updateRecordingState(bool state)
{
set_isRecordingLocally(state);
}
void
CurrentCall::connectModel()
{
try {
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
connect(accInfo.callModel.get(),
&CallModel::callStatusChanged,
this,
&CurrentCall::onCallStatusChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::callInfosChanged,
this,
&CurrentCall::onCallInfosChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::currentCallChanged,
this,
&CurrentCall::onCurrentCallChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::participantsChanged,
this,
&CurrentCall::onParticipantsChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::remoteRecordersChanged,
this,
&CurrentCall::onRemoteRecordersChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::recordingStateChanged,
this,
&CurrentCall::onRecordingStateChanged,
Qt::UniqueConnection);
} catch (const std::exception& e) {
qWarning() << "Exception getting account info." << e.what();
}
}
void
CurrentCall::onCurrentConvIdChanged()
{
updateId();
updateCallStatus();
updateParticipants();
updateCallInfo();
auto callModel = lrcInstance_->getCurrentCallModel();
QStringList recorders {};
if (callModel->hasCall(id_)) {
auto callInfo = callModel->getCall(id_);
recorders = callInfo.recordingPeers;
}
updateRecordingState(callModel->isRecording(id_));
updateRemoteRecorders(recorders);
}
void
CurrentCall::onCurrentAccountIdChanged()
{
try {
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
set_isSIP(accInfo.profileInfo.type == profile::Type::SIP);
} catch (const std::exception& e) {
qWarning() << "Can't update current call type" << e.what();
}
connectModel();
}
void
CurrentCall::onCallStatusChanged(const QString& callId, int code)
{
Q_UNUSED(code)
if (id_ != callId) {
return;
}
updateCallStatus();
}
void
CurrentCall::onCallInfosChanged(const QString& accountId, const QString& callId)
{
if (id_ != callId) {
return;
}
updateCallInfo();
}
void
CurrentCall::onCurrentCallChanged(const QString& callId)
{
// If this status change's callId is not the current, it's possible that
// the current value of id_ is stale, and needs to be updated after checking
// the current conversation's getCallId(). Other slots need not do this, as the
// id_ is updated here.
if (id_ == callId) {
return;
}
updateId(callId);
updateCallStatus();
updateParticipants();
updateCallInfo();
}
void
CurrentCall::onParticipantsChanged(const QString& callId)
{
if (id_ != callId) {
return;
}
updateParticipants();
}
void
CurrentCall::onRemoteRecordersChanged(const QString& callId, const QStringList& recorders)
{
if (id_ != callId) {
return;
}
updateRemoteRecorders(recorders);
}
void
CurrentCall::onRecordingStateChanged(const QString& callId, bool state)
{
if (id_ != callId) {
return;
}
updateRecordingState(state);
}

75
src/app/currentcall.h Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* 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/>.
*/
#pragma once
#include "lrcinstance.h"
#include "qtutils.h"
#include <QObject>
#include <QString>
class CurrentCall final : public QObject
{
Q_OBJECT
QML_RO_PROPERTY(QString, id)
QML_RO_PROPERTY(QStringList, uris)
QML_RO_PROPERTY(bool, isAudioOnly)
QML_RO_PROPERTY(bool, isSIP)
QML_RO_PROPERTY(bool, isGrid)
QML_RO_PROPERTY(call::Status, status)
QML_RO_PROPERTY(bool, isActive)
QML_RO_PROPERTY(bool, isPaused)
QML_RO_PROPERTY(bool, isAudioMuted)
QML_RO_PROPERTY(bool, isCapturing)
QML_RO_PROPERTY(bool, isVideoMuted)
QML_RO_PROPERTY(QString, previewId)
QML_RO_PROPERTY(bool, isRecordingLocally)
QML_RO_PROPERTY(bool, isRecordingRemotely)
QML_RO_PROPERTY(QStringList, remoteRecorderNameList)
QML_RO_PROPERTY(bool, isSharing)
QML_RO_PROPERTY(bool, isHandRaised)
QML_RO_PROPERTY(bool, isConference)
QML_RO_PROPERTY(bool, isModerator)
public:
explicit CurrentCall(LRCInstance* lrcInstance, QObject* parent = nullptr);
~CurrentCall() = default;
private:
void updateId(QString callId = {});
void updateCallStatus();
void updateParticipants();
void updateCallInfo();
void updateRemoteRecorders(const QStringList& recorders);
void updateRecordingState(bool state);
void connectModel();
private Q_SLOTS:
void onCurrentConvIdChanged();
void onCurrentAccountIdChanged();
void onCallStatusChanged(const QString& callId, int code);
void onCallInfosChanged(const QString& accountId, const QString& callId);
void onCurrentCallChanged(const QString& callId);
void onParticipantsChanged(const QString& callId);
void onRemoteRecordersChanged(const QString& callId, const QStringList& recorders);
void onRecordingStateChanged(const QString& callId, bool state);
private:
LRCInstance* lrcInstance_;
};

View file

@ -186,7 +186,6 @@ Rectangle {
callStackView.setLinkedWebview(chatView)
callStackView.responsibleAccountId = LRCInstance.currentAccountId
callStackView.responsibleConvUid = convId
callStackView.isAudioOnly = item.isAudioOnly
currentConvUID = convId
if (item.callState === Call.Status.IN_PROGRESS ||

View file

@ -162,7 +162,7 @@ Control {
layoutModel.get(index).ActiveSetting = layoutManager.isCallFullscreen
break
case JamiStrings.mosaic:
if (!isGrid)
if (!CurrentCall.isGrid)
CallAdapter.showGridConferenceLayout()
break
case JamiStrings.participantsSide:
@ -189,10 +189,10 @@ Control {
}
onTriggered: {
layoutModel.clear()
if (isConference) {
if (CurrentCall.isConference) {
layoutModel.append({"Name": JamiStrings.mosaic,
"IconSource": JamiResources.mosaic_black_24dp_svg,
"ActiveSetting": isGrid,
"ActiveSetting": CurrentCall.isGrid,
"TopMargin": true,
"BottomMargin": true,
"SectionEnd": true})
@ -223,8 +223,8 @@ Control {
"ActiveSetting": layoutManager.isCallFullscreen,
"TopMargin": true,
"BottomMargin": true,
"SectionEnd": isConference})
if (isConference) {
"SectionEnd": CurrentCall.isConference})
if (CurrentCall.isConference) {
layoutModel.append({"Name": JamiStrings.hideSpectators,
"IconSource": JamiResources.videocam_off_24dp_svg,
"ActiveSetting": UtilsAdapter.getAppValue(Settings.HideSpectators),
@ -263,6 +263,7 @@ Control {
JamiResources.micro_black_24dp_svg
icon.color: checked ? "red" : "white"
text: !checked ? JamiStrings.mute : JamiStrings.unmute
checked: CurrentCall.isAudioMuted
property var menuAction: audioInputMenuAction
},
Action {
@ -282,6 +283,7 @@ Control {
JamiResources.videocam_24dp_svg
icon.color: checked ? "red" : "white"
text: !checked ? JamiStrings.muteCamera : JamiStrings.unmuteCamera
checked: !CurrentCall.isCapturing
property var menuAction: videoInputMenuAction
}
]
@ -314,11 +316,13 @@ Control {
Action {
id: resumePauseCallAction
onTriggered: root.resumePauseCallClicked()
icon.source: isPaused ?
icon.source: CurrentCall.isPaused ?
JamiResources.play_circle_outline_24dp_svg :
JamiResources.pause_circle_outline_24dp_svg
icon.color: "white"
text: isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall
text: CurrentCall.isPaused ?
JamiStrings.resumeCall :
JamiStrings.pauseCall
},
Action {
id: inputPanelSIPAction
@ -337,17 +341,17 @@ Control {
Action {
id: shareAction
onTriggered: {
if (sharingActive)
if (CurrentCall.isSharing)
root.stopSharingClicked()
else
root.shareScreenClicked()
}
icon.source: sharingActive ?
icon.source: CurrentCall.isSharing ?
JamiResources.share_stop_black_24dp_svg :
JamiResources.share_screen_black_24dp_svg
icon.color: sharingActive ?
icon.color: CurrentCall.isSharing ?
"red" : "white"
text: sharingActive ?
text: CurrentCall.isSharing ?
JamiStrings.stopSharing :
JamiStrings.shareScreen
property real size: 34
@ -362,12 +366,13 @@ Control {
text: checked ?
JamiStrings.lowerHand :
JamiStrings.raiseHand
checked: CurrentCall.isHandRaised
property real size: 34
},
Action {
id: layoutAction
onTriggered: {
if (!isGrid)
if (!CurrentCall.isGrid)
CallAdapter.showGridConferenceLayout()
}
checkable: true
@ -386,6 +391,7 @@ Control {
text: !checked ? JamiStrings.startRec : JamiStrings.stopRec
property bool blinksWhenChecked: true
property real size: 28
checked: CurrentCall.isRecordingLocally
onCheckedChanged: function(checked) {
CallOverlayModel.setUrgentCount(recordAction,
checked ? -1 : 0)
@ -397,27 +403,29 @@ Control {
icon.source: JamiResources.plugins_24dp_svg
icon.color: "white"
text: JamiStrings.viewPlugin
enabled: PluginAdapter.isEnabled && PluginAdapter.callMediaHandlersListCount
enabled: PluginAdapter.isEnabled
&& PluginAdapter.callMediaHandlersListCount
}
]
property var overflowItemCount
Connections {
target: callOverlay
target: CurrentCall
function onIsAudioOnlyChanged() { Qt.callLater(reset) }
function onIsSIPChanged() { Qt.callLater(reset) }
function onIsActiveChanged() { if (CurrentCall.isActive) reset() }
function onIsRecordingLocallyChanged() { Qt.callLater(reset) }
function onIsHandRaisedChanged() { Qt.callLater(reset) }
function onIsConferenceChanged() { Qt.callLater(reset) }
function onIsModeratorChanged() { Qt.callLater(reset) }
function onIsSIPChanged() { Qt.callLater(reset) }
function onIsAudioOnlyChanged() { Qt.callLater(reset) }
function onIsAudioMutedChanged() { Qt.callLater(reset) }
function onIsVideoMutedChanged() { Qt.callLater(reset) }
function onIsRecordingChanged() { Qt.callLater(reset) }
function onLocalHandRaisedChanged() { Qt.callLater(reset) }
function onIsConferenceChanged() { Qt.callLater(reset) }
}
Connections {
target: CurrentAccount
function onVideoEnabledVideoChanged() { reset() }
}
@ -433,29 +441,24 @@ Control {
// overflow controls
CallOverlayModel.addSecondaryControl(audioOutputAction)
if (isConference) {
if (CurrentCall.isConference) {
CallOverlayModel.addSecondaryControl(raiseHandAction)
raiseHandAction.checked = CallAdapter.isHandRaised()
}
if (isModerator && !isSIP)
if (CurrentCall.isModerator && !CurrentCall.isSIP)
CallOverlayModel.addSecondaryControl(addPersonAction)
if (isSIP) {
if (CurrentCall.isSIP) {
CallOverlayModel.addSecondaryControl(resumePauseCallAction)
CallOverlayModel.addSecondaryControl(inputPanelSIPAction)
CallOverlayModel.addSecondaryControl(callTransferAction)
}
CallOverlayModel.addSecondaryControl(chatAction)
if (CurrentAccount.videoEnabled_Video)
if (CurrentAccount.videoEnabled_Video && !CurrentCall.isSIP)
CallOverlayModel.addSecondaryControl(shareAction)
CallOverlayModel.addSecondaryControl(layoutAction)
CallOverlayModel.addSecondaryControl(recordAction)
if (pluginsAction.enabled)
CallOverlayModel.addSecondaryControl(pluginsAction)
overflowItemCount = CallOverlayModel.secondaryModel().rowCount()
muteAudioAction.checked = isAudioMuted
recordAction.checked = CallAdapter.isRecordingThisCall()
muteVideoAction.checked = isAudioOnly ? true : isVideoMuted
}
Item {

View file

@ -39,6 +39,7 @@ ItemDelegate {
action: ItemAction
checkable: ItemAction.checkable
hoverEnabled: ItemAction.enabled
// hide the action's visual elements like the blurry looking icon
icon.source: ""
@ -122,7 +123,11 @@ ItemDelegate {
anchors.centerIn: parent
source: ItemAction ? ItemAction.icon.source : ""
color: ItemAction ? ItemAction.icon.color : null
color: ItemAction ?
(ItemAction.enabled ?
ItemAction.icon.color :
Qt.lighter(ItemAction.icon.color)) :
null
SequentialAnimation on opacity {
loops: Animation.Infinite
@ -172,7 +177,8 @@ ItemDelegate {
indicator: null
visible: menuAction !== undefined && !UrgentCount && menuAction.enabled
visible: ItemAction.enabled
&& menuAction !== undefined && !UrgentCount && menuAction.enabled
y: isVertical ? 0 : -4
x: isVertical ? -4 : 0

View file

@ -35,48 +35,11 @@ import "../../commoncomponents"
Item {
id: root
property bool isPaused
property bool isAudioOnly
property bool isAudioMuted
property bool isVideoMuted
property bool isRecording
property bool remoteRecording
property bool isSIP
property bool isModerator
property bool isConference
property bool isGrid
property bool participantsSide: UtilsAdapter.getAppValue(Settings.ParticipantsSide)
property bool localHandRaised
property bool sharingActive: AvAdapter.isSharing()
property string callId: ""
signal chatButtonClicked
signal fullScreenClicked
function setRecording(localIsRecording) {
callViewContextMenu.localIsRecording = localIsRecording
mainOverlay.recordingVisible = localIsRecording
|| callViewContextMenu.peerIsRecording
}
function updateUI(isPaused, isAudioOnly, isAudioMuted, isSIP, isGrid) {
if (isPaused !== undefined) {
root.isPaused = isPaused
root.isAudioOnly = isAudioOnly
root.isAudioMuted = isAudioMuted
callViewContextMenu.isVideoMuted = root.isVideoMuted
root.isSIP = isSIP
root.isGrid = isGrid
root.localHandRaised = CallAdapter.isHandRaised()
}
root.isRecording = CallAdapter.isRecordingThisCall()
root.isModerator = CallAdapter.isModerator()
}
function showOnHoldImage(visible) {
onHoldImage.visible = visible
}
function closeContextMenuAndRelatedWindows() {
ContactPickerCreation.closeContactPicker()
sipInputPanel.close()
@ -94,29 +57,6 @@ Item {
callViewContextMenu.openMenu()
}
function showRemoteRecording(peers, state) {
var label = ""
var i = 0
if (state) {
for (var p in peers) {
label += peers[p]
if (i !== (peers.length - 1))
label += ", "
i += 1
}
label += " " + ((peers.length > 1) ? JamiStrings.areRecording : JamiStrings.isRecording)
}
mainOverlay.remoteRecordingLabel = state ? label : JamiStrings.peerStoppedRecording
root.remoteRecording = state
callOverlayRectMouseArea.entered()
}
function resetRemoteRecording() {
mainOverlay.remoteRecordingLabel = ""
root.remoteRecording = false
}
DropArea {
anchors.fill: parent
onDropped: function(drop) {
@ -158,7 +98,7 @@ Item {
width: 200
height: 200
visible: false
visible: CurrentCall.isPaused
source: JamiResources.ic_pause_white_100px_svg
}
@ -199,17 +139,10 @@ Item {
PluginHandlerPickerCreation.openPluginHandlerPicker()
}
function recordClicked() {
CallAdapter.recordThisCallToggle()
updateUI()
}
MainOverlay {
id: mainOverlay
anchors.fill: parent
isRecording: root.isRecording
remoteRecording: root.remoteRecording
Connections {
target: mainOverlay.callActionBar
@ -222,7 +155,7 @@ Item {
function onShareWindowClicked() { openShareWindow() }
function onStopSharingClicked() { AvAdapter.stopSharing() }
function onShareScreenAreaClicked() { openShareScreenArea() }
function onRecordCallClicked() { recordClicked() }
function onRecordCallClicked() { CallAdapter.recordThisCallToggle() }
function onShareFileClicked() { jamiFileDialog.open() }
function onPluginsClicked() { openPluginsMenu() }
function onFullScreenClicked() { root.fullScreenClicked() }
@ -232,13 +165,9 @@ Item {
CallViewContextMenu {
id: callViewContextMenu
isSIP: root.isSIP
isPaused: root.isPaused
isRecording: root.isRecording
onTransferCallButtonClicked: openContactPicker(ContactList.TRANSFER)
onPluginItemClicked: openPluginsMenu()
onRecordCallClicked: root.recordClicked()
onRecordCallClicked: CallAdapter.recordThisCallToggle()
onOpenSelectionWindow: {
SelectScreenWindowCreation.createSelectScreenWindowObject(appWindow)
SelectScreenWindowCreation.showSelectScreenWindow(callPreviewId, windowSelection)

View file

@ -28,7 +28,6 @@ import "../../commoncomponents"
Rectangle {
id: root
property bool isAudioOnly: false
property var sipKeys: [
"1", "2", "3", "A",
"4", "5", "6", "B",
@ -123,13 +122,6 @@ Rectangle {
Connections {
target: CallAdapter
function onCallInfosChanged(audioOnly, accountId, convUid) {
if (callStackMainView.currentItem.stackNumber === CallStackView.OngoingPageStack
&& responsibleConvUid === convUid && responsibleAccountId === accountId) {
ongoingCallPage.isAudioOnly = audioOnly
}
}
function onCallStatusChanged(status, accountId, convUid) {
if (callStackMainView.currentItem.stackNumber === CallStackView.InitialPageStack
&& responsibleConvUid === convUid && responsibleAccountId === accountId) {
@ -143,8 +135,6 @@ Rectangle {
property int stackNumber: CallStackView.OngoingPageStack
isAudioOnly: root.isAudioOnly
visible: callStackMainView.currentItem.stackNumber === stackNumber
}
@ -153,8 +143,6 @@ Rectangle {
property int stackNumber: CallStackView.InitialPageStack
isAudioOnly: root.isAudioOnly
onCallAccepted: {
CallAdapter.acceptACall(responsibleAccountId, responsibleConvUid)
mainViewSidePanel.selectTab(SidePanelTabBar.Conversations)

View file

@ -31,11 +31,6 @@ import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
ContextMenuAutoLoader {
id: root
property bool isSIP: false
property bool isPaused: false
property bool isVideoMuted: false
property bool isRecording: false
property bool windowSelection: false
signal pluginItemClicked
@ -47,9 +42,11 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: resumePauseCall
canTrigger: isSIP
itemName: isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall
iconSource: isPaused ?
canTrigger: CurrentCall.isSIP
itemName: CurrentCall.isPaused ?
JamiStrings.resumeCall :
JamiStrings.pauseCall
iconSource: CurrentCall.isPaused ?
JamiResources.play_circle_outline_24dp_svg :
JamiResources.pause_circle_outline_24dp_svg
onClicked: {
@ -59,7 +56,7 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: inputPanelSIP
canTrigger: isSIP
canTrigger: CurrentCall.isSIP
itemName: JamiStrings.sipInputPanel
iconSource: JamiResources.ic_keypad_svg
onClicked: {
@ -69,10 +66,10 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: callTransfer
canTrigger: isSIP
canTrigger: CurrentCall.isSIP
itemName: JamiStrings.transferCall
iconSource: JamiResources.phone_forwarded_24dp_svg
addMenuSeparatorAfter: isSIP
addMenuSeparatorAfter: CurrentCall.isSIP
onClicked: {
root.transferCallButtonClicked()
}
@ -80,7 +77,9 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: localRecord
itemName: root.isRecording ? JamiStrings.stopRec : JamiStrings.startRec
itemName: CurrentCall.isRecordingLocally ?
JamiStrings.stopRec :
JamiStrings.startRec
iconSource: JamiResources.fiber_manual_record_24dp_svg
iconColor: JamiTheme.recordIconColor
onClicked: {
@ -103,8 +102,9 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: stopSharing
canTrigger: AvAdapter.isSharing()
&& !isSIP && !isVideoMuted
canTrigger: CurrentCall.isSharing
&& !CurrentCall.isSIP
&& !CurrentCall.isVideoMuted
itemName: JamiStrings.stopSharing
iconSource: JamiResources.share_stop_black_24dp_svg
iconColor: JamiTheme.redColor
@ -113,8 +113,9 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: shareScreen
canTrigger: CurrentAccount.videoEnabled_Video && AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !isSIP
canTrigger: CurrentAccount.videoEnabled_Video
&& AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !CurrentCall.isSIP
itemName: JamiStrings.shareScreen
iconSource: JamiResources.laptop_black_24dp_svg
onClicked: {
@ -129,8 +130,10 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: shareWindow
canTrigger: Qt.platform.os === "linux" && CurrentAccount.videoEnabled_Video && AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !isSIP
canTrigger: Qt.platform.os === "linux"
&& CurrentAccount.videoEnabled_Video
&& AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !CurrentCall.isSIP
itemName: JamiStrings.shareWindow
iconSource: JamiResources.window_black_24dp_svg
onClicked: {
@ -144,8 +147,9 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: shareScreenArea
canTrigger: CurrentAccount.videoEnabled_Video && AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !isSIP
canTrigger: CurrentAccount.videoEnabled_Video
&& AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
&& !CurrentCall.isSIP
itemName: JamiStrings.shareScreenArea
iconSource: JamiResources.share_area_black_24dp_svg
onClicked: {
@ -160,7 +164,8 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: shareFile
canTrigger: CurrentAccount.videoEnabled_Video && !isSIP
canTrigger: CurrentAccount.videoEnabled_Video
&& !CurrentCall.isSIP
itemName: JamiStrings.shareFile
iconSource: JamiResources.file_black_24dp_svg
onClicked: {
@ -170,7 +175,8 @@ ContextMenuAutoLoader {
GeneralMenuItem {
id: viewPlugin
canTrigger: PluginAdapter.isEnabled && PluginAdapter.callMediaHandlersListCount
canTrigger: PluginAdapter.isEnabled &&
PluginAdapter.callMediaHandlersListCount
itemName: JamiStrings.viewPlugin
iconSource: JamiResources.extension_24dp_svg
onClicked: {

View file

@ -31,7 +31,7 @@ Rectangle {
id: root
property bool isIncoming: false
property bool isAudioOnly: false
property bool isAudioOnly: CurrentCall.isAudioOnly
property int callStatus: 0
signal callCanceled

View file

@ -32,7 +32,21 @@ Item {
id: root
property string timeText: "00:00"
property string remoteRecordingLabel: ""
property string remoteRecordingLabel
Connections {
target: CurrentCall
function onIsRecordingRemotelyChanged() {
var label = ""
if (CurrentCall.isRecordingRemotely) {
label = CurrentCall.remoteRecorderNameList.join(", ") + " "
label += (CurrentCall.remoteRecorderNameList.length > 1) ?
JamiStrings.areRecording : JamiStrings.isRecording
}
root.remoteRecordingLabel = label
}
}
property alias callActionBar: __callActionBar
@ -43,8 +57,6 @@ Item {
property string muteAlertMessage: ""
property bool muteAlertActive: false
property bool remoteRecording: false
property bool isRecording: false
onMuteAlertActiveChanged: {
if (muteAlertActive) {
@ -117,7 +129,7 @@ Item {
root.timeText = CallAdapter.getCallDurationTime(
LRCInstance.currentAccountId,
LRCInstance.selectedConvUid)
if (root.opacity === 0 && !root.remoteRecording)
if (root.opacity === 0 && !CurrentCall.isRecordingRemotely)
root.remoteRecordingLabel = ""
}
}
@ -149,11 +161,11 @@ Item {
font.pointSize: JamiTheme.textFontSize
text: {
if (!root.isAudioOnly) {
if (remoteRecordingLabel === "") {
if (!CurrentCall.isAudioOnly) {
if (root.remoteRecordingLabel === "") {
return CurrentConversation.title
} else {
return remoteRecordingLabel
return root.remoteRecordingLabel
}
}
return ""
@ -180,7 +192,7 @@ Item {
Rectangle {
id: recordingRect
visible: root.isRecording || root.remoteRecording
visible: CurrentCall.isRecordingLocally || CurrentCall.isRecordingRemotely
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.rightMargin: JamiTheme.preferredMarginSize

View file

@ -42,9 +42,8 @@ Rectangle {
property int previewMarginYBottom: previewMargin + 84
property int previewToX: 0
property int previewToY: 0
property bool isAudioOnly: false
property var linkedWebview: null
property string callPreviewId: ""
property string callPreviewId
onCallPreviewIdChanged: {
controlPreview.start()
@ -56,8 +55,6 @@ Rectangle {
if (accountPeerPair[0] === "" || accountPeerPair[1] === "")
return
contactImage.imageId = accountPeerPair[1]
distantRenderer.rendererId = UtilsAdapter.getCallId(accountPeerPair[0],
accountPeerPair[1])
}
function setLinkedWebview(webViewId) {
@ -68,7 +65,6 @@ Rectangle {
closeInCallConversation)
}
Connections {
target: UtilsAdapter
@ -178,11 +174,12 @@ Rectangle {
VideoView {
id: distantRenderer
rendererId: CurrentCall.id
anchors.centerIn: parent
anchors.fill: parent
z: -1
visible: participantsLayer.count === 0 && !root.isAudioOnly
visible: !CurrentCall.isConference && !CurrentCall.isAudioOnly
}
ParticipantsLayer {
@ -190,17 +187,16 @@ Rectangle {
anchors.fill: parent
anchors.centerIn: parent
anchors.margins: 1
visible: participantsLayer.count !== 0
visible: CurrentCall.isConference
participantsSide: callOverlay.participantsSide
onCountChanged: {
callOverlay.isConference = participantsLayer.count > 0
}
}
LocalVideo {
id: previewRenderer
visible: (CurrentCall.isSharing || !CurrentCall.isVideoMuted)
&& !CurrentCall.isConference
height: width * invAspectRatio
width: Math.max(callPageMainRect.width / 5, JamiTheme.minimumPreviewWidth)
x: callPageMainRect.width - previewRenderer.width - previewMargin
@ -217,6 +213,7 @@ Rectangle {
previewRenderer.startWithId(rendId)
}
}
onVisibleChanged: {
controlPreview.stop()
if (visible) {
@ -297,7 +294,6 @@ Rectangle {
id: callOverlay
anchors.fill: parent
isConference: participantsLayer.count > 0
function toggleConversation() {
if (inCallMessageWebViewStack.visible)
@ -307,35 +303,19 @@ Rectangle {
}
Connections {
target: CallAdapter
target: CurrentCall
function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted,
isSIP, isGrid, previewId) {
root.callPreviewId = previewId
callOverlay.showOnHoldImage(isPaused)
root.isAudioOnly = isAudioOnly
callOverlay.showOnHoldImage(isPaused)
audioCallPageRectCentralRect.visible = !isPaused && root.isAudioOnly && participantsLayer.count === 0
callOverlay.updateUI(isPaused, isAudioOnly,
isAudioMuted,
isSIP,
isGrid)
callOverlay.isVideoMuted = !AvAdapter.isCapturing()
callOverlay.sharingActive = AvAdapter.isSharing()
previewRenderer.visible = (AvAdapter.isSharing() || AvAdapter.isCapturing()) && participantsLayer.count == 0
}
function onShowOnHoldLabel(isPaused) {
callOverlay.showOnHoldImage(isPaused)
audioCallPageRectCentralRect.visible = !isPaused && root.isAudioOnly && participantsLayer.count === 0
}
function onRemoteRecordingChanged(label, state) {
callOverlay.showRemoteRecording(label, state)
}
function onEraseRemoteRecording() {
callOverlay.resetRemoteRecording()
function onPreviewIdChanged() {
if (CurrentCall.previewId !== "") {
if (root.callPreviewId !== "" &&
root.callPreviewId !== CurrentCall.previewId) {
VideoDevices.stopDevice(root.callPreviewId)
}
VideoDevices.startDevice(CurrentCall.previewId)
} else {
VideoDevices.stopDevice(root.callPreviewId)
}
root.callPreviewId = CurrentCall.previewId
}
}
@ -367,7 +347,9 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
visible: root.isAudioOnly
visible: !CurrentCall.isPaused &&
CurrentCall.isAudioOnly &&
!CurrentCall.isConference
ConversationAvatar {
id: contactImage

View file

@ -58,7 +58,7 @@ Popup {
function onAboutToShow(visible) {
// Reset the model on each show.
if (isCall) {
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentConversation.callId)
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id)
} else {
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.uris[0]
pluginhandlerPickerListView.model = PluginAdapter.getChatHandlerSelectableModel(LRCInstance.currentAccountId, peerId)
@ -68,8 +68,8 @@ Popup {
function toggleHandlerSlot(handlerId, isLoaded) {
if (isCall) {
PluginModel.toggleCallMediaHandler(handlerId, CurrentConversation.callId, !isLoaded)
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentConversation.callId)
PluginModel.toggleCallMediaHandler(handlerId, CurrentCall.id, !isLoaded)
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id)
} else {
var accountId = LRCInstance.currentAccountId
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.uris[0]
@ -125,7 +125,7 @@ Popup {
model: {
if (isCall) {
return PluginAdapter.getMediaHandlerSelectableModel(CurrentConversation.callId)
return PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id)
} else {
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.uris[0]
return PluginAdapter.getChatHandlerSelectableModel(LRCInstance.currentAccountId, peerId)

View file

@ -29,6 +29,7 @@
#include "previewengine.h"
#include "utilsadapter.h"
#include "conversationsadapter.h"
#include "currentcall.h"
#include "currentconversation.h"
#include "currentaccount.h"
#include "videodevices.h"
@ -118,6 +119,7 @@ registerTypes(QQmlEngine* engine,
auto accountAdapter = new AccountAdapter(settingsManager, systemTray, lrcInstance, parent);
auto utilsAdapter = new UtilsAdapter(settingsManager, systemTray, lrcInstance, parent);
auto pluginAdapter = new PluginAdapter(lrcInstance, parent);
auto currentCall = new CurrentCall(lrcInstance, parent);
auto currentConversation = new CurrentConversation(lrcInstance, parent);
auto currentAccount = new CurrentAccount(lrcInstance, settingsManager, parent);
auto tipsModel = new TipsModel(settingsManager, parent);
@ -135,6 +137,7 @@ registerTypes(QQmlEngine* engine,
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, accountAdapter, "AccountAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, utilsAdapter, "UtilsAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, pluginAdapter, "PluginAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentCall, "CurrentCall");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentConversation, "CurrentConversation");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccount, "CurrentAccount");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, videoDevices, "VideoDevices");

View file

@ -139,7 +139,7 @@ struct Info
bool isAudioOnly = false;
Layout layout = Layout::GRID;
VectorMapStringString mediaList = {};
QSet<QString> peerRec {};
QStringList recordingPeers {};
bool hasMediaWithType(const QString& type, const QString& mediaType) const
{

View file

@ -429,7 +429,7 @@ Q_SIGNALS:
* Emitted when the rendered image changed
* @param confId
*/
void onParticipantsChanged(const QString& confId) const;
void participantsChanged(const QString& confId) const;
/**
* Emitted when a call starts
* @param callId
@ -469,15 +469,19 @@ Q_SIGNALS:
int urgentCount) const;
/**
* Listen from CallbacksHandler when the peer start recording
* Provides notification of a new set of recording peers once a change has occured,
* in the form of a list, as QSet<QString> is not directly QML compatible.
* @param callId
* @param contactId
* @param peerName
* @param state the new state
* @param recorders
*/
void remoteRecordingChanged(const QString& callId,
const QSet<QString>& peerRec,
bool state) const;
void remoteRecordersChanged(const QString& callId, const QStringList& recorders) const;
/**
* Provides notification of change in the local call recording state.,
* @param callId
* @param state
*/
void recordingStateChanged(const QString& callId, bool state) const;
/*!
* Emitted before new pending conferences are inserted into the underlying list
@ -504,6 +508,11 @@ Q_SIGNALS:
*/
void callInfosChanged(const QString& accountId, const QString& callId) const;
/**
* Emit currentCallChanged
*/
void currentCallChanged(const QString& callId) const;
private:
std::unique_ptr<CallModelPimpl> pimpl_;
};

View file

@ -201,6 +201,12 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent)
&CallbacksHandler::slotConferenceChanged,
Qt::QueuedConnection);
connect(&CallManager::instance(),
&CallManagerInterface::recordingStateChanged,
this,
&CallbacksHandler::recordingStateChanged,
Qt::QueuedConnection);
connect(&CallManager::instance(),
&CallManagerInterface::incomingMessage,
this,
@ -572,6 +578,12 @@ CallbacksHandler::slotConferenceCreated(const QString& accountId, const QString&
Q_EMIT conferenceCreated(accountId, callId);
}
void
CallbacksHandler::slotConferenceRemoved(const QString& accountId, const QString& callId)
{
Q_EMIT conferenceRemoved(accountId, callId);
}
void
CallbacksHandler::slotConferenceChanged(const QString& accountId,
const QString& callId,
@ -581,12 +593,6 @@ CallbacksHandler::slotConferenceChanged(const QString& accountId,
slotCallStateChanged(accountId, callId, state, 0);
}
void
CallbacksHandler::slotConferenceRemoved(const QString& accountId, const QString& callId)
{
Q_EMIT conferenceRemoved(accountId, callId);
}
void
CallbacksHandler::slotAccountMessageStatusChanged(const QString& accountId,
const QString& conversationId,

View file

@ -377,6 +377,7 @@ Q_SIGNALS:
void conversationPreferencesUpdated(const QString& accountId,
const QString& conversationId,
const MapStringString& preferences);
void recordingStateChanged(const QString& callId, bool state);
/**
* Emitted when a conversation receives a new position

View file

@ -259,9 +259,16 @@ public Q_SLOTS:
/**
* Listen from CallbacksHandler when the peer start recording
* @param callId
* @param peerUri
* @param state the new state
*/
void remoteRecordingChanged(const QString& callId, const QString& peerNumber, bool state);
void onRemoteRecordingChanged(const QString& callId, const QString& peerUri, bool state);
/**
* Listen from CallbacksHandler when we start/stop recording
* @param callId
* @param state the new state
*/
void onRecordingStateChanged(const QString& callId, bool state);
};
CallModel::CallModel(const account::Info& owner,
@ -382,7 +389,7 @@ CallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringStrin
}
#ifdef ENABLE_LIBWRAP
auto callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
#else // dbus
#else // dbus
// do not use auto here (QDBusPendingReply<QString>)
QString callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
#endif // ENABLE_LIBWRAP
@ -975,7 +982,11 @@ CallModelPimpl::CallModelPimpl(const CallModel& linked,
connect(&callbacksHandler,
&CallbacksHandler::remoteRecordingChanged,
this,
&CallModelPimpl::remoteRecordingChanged);
&CallModelPimpl::onRemoteRecordingChanged);
connect(&callbacksHandler,
&CallbacksHandler::recordingStateChanged,
this,
&CallModelPimpl::onRecordingStateChanged);
#ifndef ENABLE_LIBWRAP
// Only necessary with dbus since the daemon runs separately
@ -1140,7 +1151,7 @@ CallModel::setCurrentCall(const QString& callId) const
}
if (!lrc::api::Lrc::holdConferences) {
return;
continue;
}
// If the account is the host and it is attached to the conference,
// then we should hold it.
@ -1157,6 +1168,8 @@ CallModel::setCurrentCall(const QString& callId) const
}
}
}
Q_EMIT currentCallChanged(callId);
}
void
@ -1599,7 +1612,7 @@ CallModelPimpl::slotOnConferenceInfosUpdated(const QString& confId,
}
}
Q_EMIT linked.callInfosChanged(linked.owner.id, confId);
Q_EMIT linked.onParticipantsChanged(confId);
Q_EMIT linked.participantsChanged(confId);
}
bool
@ -1686,13 +1699,14 @@ CallModelPimpl::sendProfile(const QString& callId)
}
void
CallModelPimpl::remoteRecordingChanged(const QString& callId, const QString& peerNumber, bool state)
CallModelPimpl::onRemoteRecordingChanged(const QString& callId, const QString& peerUri, bool state)
{
auto it = calls.find(callId);
if (it == calls.end() or not it->second)
if (it == calls.end() or !it->second) {
return;
}
auto uri = peerNumber;
auto uri = peerUri;
if (uri.contains("ring:"))
uri.remove("ring:");
@ -1701,15 +1715,19 @@ CallModelPimpl::remoteRecordingChanged(const QString& callId, const QString& pee
if (uri.contains("@ring.dht"))
uri.remove("@ring.dht");
// Add peer to peerRec set
if (state && not it->second->peerRec.contains(uri))
it->second->peerRec.insert(uri);
// Add/remove peer to recordingPeers, preventing duplicates.
if (state && !it->second->recordingPeers.contains(uri))
it->second->recordingPeers.append(uri);
else if (!state && it->second->recordingPeers.contains(uri))
it->second->recordingPeers.removeAll(uri);
// remove peer from peerRec set
if (!state && it->second->peerRec.contains(uri))
it->second->peerRec.remove(uri);
Q_EMIT linked.remoteRecordersChanged(callId, it->second->recordingPeers);
}
Q_EMIT linked.remoteRecordingChanged(callId, it->second->peerRec, state);
void
CallModelPimpl::onRecordingStateChanged(const QString& callId, bool state)
{
Q_EMIT linked.recordingStateChanged(callId, state);
}
} // namespace lrc