mirror of
https://github.com/savoirfairelinux/jami-client-qt.git
synced 2026-01-12 04:06:31 +08:00
Introduces the ViewCoordinator component to promote dynamic view loading and reduce coupling between components. The following objects are now created and destroyed as needed: - SettingsView - WizardView - dialogs Further refactoring will be required in order to do the same with the ConversationView, which now parents the ChatView and the CallStackView. Gitlab: #897 Change-Id: Ice6a0c133e62e1e0c8d7fb99ec2c41234c049b59
339 lines
9.8 KiB
C++
339 lines
9.8 KiB
C++
/*
|
|
* Copyright (C) 2022-2023 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);
|
|
|
|
connect(&lrcInstance_->behaviorController(),
|
|
&BehaviorController::showIncomingCallView,
|
|
this,
|
|
&CurrentCall::onShowIncomingCallView);
|
|
|
|
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();
|
|
set_id((accInfo.callModel->hasCall(callId) ? callId : QString()));
|
|
}
|
|
|
|
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_isOutgoing(callInfo.isOutgoing);
|
|
set_isGrid(callInfo.layout == call::Layout::GRID);
|
|
set_isAudioOnly(callInfo.isAudioOnly);
|
|
|
|
bool isAudioMuted {};
|
|
bool isVideoMuted {};
|
|
bool isSharing {};
|
|
QString sharingSource {};
|
|
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;
|
|
sharingSource = media[MediaAttributeKey::SOURCE];
|
|
}
|
|
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_sharingSource(sharingSource);
|
|
set_isCapturing(isCapturing);
|
|
set_isHandRaised(callModel->isHandRaised(id_));
|
|
set_isModerator(callModel->isModerator(id_));
|
|
|
|
QStringList recorders {};
|
|
if (callModel->hasCall(id_)) {
|
|
auto callInfo = callModel->getCall(id_);
|
|
recorders = callInfo.recordingPeers;
|
|
}
|
|
updateRecordingState(callModel->isRecording(id_));
|
|
updateRemoteRecorders(recorders);
|
|
}
|
|
|
|
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()
|
|
{
|
|
auto callModel = lrcInstance_->getCurrentCallModel();
|
|
if (callModel == nullptr) {
|
|
return;
|
|
}
|
|
|
|
connect(callModel,
|
|
&CallModel::callStatusChanged,
|
|
this,
|
|
&CurrentCall::onCallStatusChanged,
|
|
Qt::UniqueConnection);
|
|
connect(callModel,
|
|
&CallModel::callInfosChanged,
|
|
this,
|
|
&CurrentCall::onCallInfosChanged,
|
|
Qt::UniqueConnection);
|
|
connect(callModel,
|
|
&CallModel::currentCallChanged,
|
|
this,
|
|
&CurrentCall::onCurrentCallChanged,
|
|
Qt::UniqueConnection);
|
|
connect(callModel,
|
|
&CallModel::participantsChanged,
|
|
this,
|
|
&CurrentCall::onParticipantsChanged,
|
|
Qt::UniqueConnection);
|
|
connect(callModel,
|
|
&CallModel::remoteRecordersChanged,
|
|
this,
|
|
&CurrentCall::onRemoteRecordersChanged,
|
|
Qt::UniqueConnection);
|
|
connect(callModel,
|
|
&CallModel::recordingStateChanged,
|
|
this,
|
|
&CurrentCall::onRecordingStateChanged,
|
|
Qt::UniqueConnection);
|
|
}
|
|
|
|
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 in CurrentCall::updateId.
|
|
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);
|
|
}
|
|
|
|
void
|
|
CurrentCall::onShowIncomingCallView(const QString& accountId, const QString& convUid)
|
|
{
|
|
if (accountId != lrcInstance_->get_currentAccountId()
|
|
|| convUid != lrcInstance_->get_selectedConvUid()) {
|
|
return;
|
|
}
|
|
|
|
// Update the id in case the current conversation now has a call
|
|
// that matches the current id.
|
|
updateId();
|
|
updateCallStatus();
|
|
updateCallInfo();
|
|
}
|