mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-01 22:25:26 +02:00
participantsmodel: move to current call
Not useful in calladapter as we need to check if it's for the current call. Also, fix some race-confitions where the callparticipantsmodel was empty (in swarm-call with only the host in general) https://git.jami.net/savoirfairelinux/jami-client-qt/-/issues/639 Change-Id: I69df1aa9f7d2d5b198c0fdc01e88e36f9c2c0bd7
This commit is contained in:
parent
28476a01d5
commit
1ed5bb1e1f
5 changed files with 155 additions and 240 deletions
|
@ -32,8 +32,8 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
#include <api/callmodel.h>
|
||||||
#include <api/callparticipantsmodel.h>
|
#include <api/callparticipantsmodel.h>
|
||||||
#include <api/devicemodel.h>
|
|
||||||
|
|
||||||
#include <media_const.h>
|
#include <media_const.h>
|
||||||
|
|
||||||
|
@ -47,9 +47,6 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject*
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation);
|
connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation);
|
||||||
|
|
||||||
participantsModel_.reset(new CallParticipantsModel(lrcInstance_, this));
|
|
||||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, participantsModel_.get(), "CallParticipantsModel");
|
|
||||||
|
|
||||||
overlayModel_.reset(new CallOverlayModel(lrcInstance_, this));
|
overlayModel_.reset(new CallOverlayModel(lrcInstance_, this));
|
||||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, overlayModel_.get(), "CallOverlayModel");
|
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, overlayModel_.get(), "CallOverlayModel");
|
||||||
|
|
||||||
|
@ -164,69 +161,6 @@ CallAdapter::onCallStatusChanged(const QString& accountId, const QString& callId
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CallAdapter::onParticipantAdded(const QString& callId, int index)
|
|
||||||
{
|
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
|
|
||||||
auto& callModel = accInfo.callModel;
|
|
||||||
try {
|
|
||||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& currentConvInfo = accInfo.conversationModel.get()->getConversationForUid(
|
|
||||||
lrcInstance_->get_selectedConvUid());
|
|
||||||
if (callId != currentConvInfo->get().callId && callId != currentConvInfo->get().confId) {
|
|
||||||
qDebug() << "trying to update not current conf";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto infos = getConferencesInfos();
|
|
||||||
if (index < infos.size())
|
|
||||||
participantsModel_->addParticipant(index, infos[index]);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallAdapter::onParticipantRemoved(const QString& callId, int index)
|
|
||||||
{
|
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
|
|
||||||
auto& callModel = accInfo.callModel;
|
|
||||||
try {
|
|
||||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& currentConvInfo = accInfo.conversationModel.get()->getConversationForUid(
|
|
||||||
lrcInstance_->get_selectedConvUid());
|
|
||||||
if (callId != currentConvInfo->get().callId && callId != currentConvInfo->get().confId) {
|
|
||||||
qDebug() << "trying to update not current conf";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
participantsModel_->removeParticipant(index);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallAdapter::onParticipantUpdated(const QString& callId, int index)
|
|
||||||
{
|
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
|
|
||||||
auto& callModel = accInfo.callModel;
|
|
||||||
try {
|
|
||||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
|
||||||
return;
|
|
||||||
const auto& currentConvInfo = accInfo.conversationModel.get()->getConversationForUid(
|
|
||||||
lrcInstance_->get_selectedConvUid());
|
|
||||||
if (callId != currentConvInfo->get().callId && callId != currentConvInfo->get().confId) {
|
|
||||||
qDebug() << "trying to update not current conf";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto infos = getConferencesInfos();
|
|
||||||
if (index < infos.size())
|
|
||||||
participantsModel_->updateParticipant(index, infos[index]);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CallAdapter::onCallStarted(const QString& callId)
|
CallAdapter::onCallStarted(const QString& callId)
|
||||||
{
|
{
|
||||||
|
@ -336,30 +270,6 @@ CallAdapter::onCallStatusChanged(const QString& callId, int code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CallAdapter::onCallInfosChanged(const QString& accountId, const QString& callId)
|
|
||||||
{
|
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
|
|
||||||
auto& callModel = accInfo.callModel;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const auto call = callModel->getCall(callId);
|
|
||||||
/*
|
|
||||||
* Change status label text.
|
|
||||||
*/
|
|
||||||
const auto& convInfo = lrcInstance_->getConversationFromCallId(callId);
|
|
||||||
if (!convInfo.uid.isEmpty()) {
|
|
||||||
if (!convInfo.confId.isEmpty() && callId != convInfo.confId) {
|
|
||||||
// In this case the conv has a confId, ignore subcalls changes.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Q_EMIT callInfosChanged(call.isAudioOnly, accountId, convInfo.uid);
|
|
||||||
participantsModel_->setConferenceLayout(static_cast<int>(call.layout), callId);
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
|
CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
|
||||||
{
|
{
|
||||||
|
@ -525,73 +435,6 @@ CallAdapter::updateCall(const QString& convUid, const QString& accountId, bool f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
participantsModel_->setParticipants(call->id, getConferencesInfos());
|
|
||||||
participantsModel_->setConferenceLayout(static_cast<int>(call->layout), call->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallAdapter::fillParticipantData(QJsonObject& participant) const
|
|
||||||
{
|
|
||||||
// TODO: getCurrentDeviceId should be part of CurrentAccount, and Current<thing>
|
|
||||||
// should be read accessible through LRCInstance ??
|
|
||||||
auto getCurrentDeviceId = [](const account::Info& accInfo) -> QString {
|
|
||||||
const auto& deviceList = accInfo.deviceModel->getAllDevices();
|
|
||||||
auto devIt = std::find_if(std::cbegin(deviceList),
|
|
||||||
std::cend(deviceList),
|
|
||||||
[](const Device& dev) { return dev.isCurrent; });
|
|
||||||
return devIt != deviceList.cend() ? devIt->id : QString();
|
|
||||||
};
|
|
||||||
|
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
|
|
||||||
using namespace lrc::api::ParticipantsInfosStrings;
|
|
||||||
|
|
||||||
// If both the URI and the device Id match, we set the "is local" flag
|
|
||||||
// used to filter out the participant.
|
|
||||||
// TODO:
|
|
||||||
// - This filter should always be applied, and any local streams should render
|
|
||||||
// using local sinks. Local non-preview participants should have proxy participant
|
|
||||||
// items replaced into this model using their local sink Ids.
|
|
||||||
// - The app setting should remain and be used to control whether or not the preview
|
|
||||||
// sink partipcant is rendered.
|
|
||||||
auto uri = participant[URI].toString();
|
|
||||||
participant[ISLOCAL] = false;
|
|
||||||
if (uri == accInfo.profileInfo.uri && participant[DEVICE] == getCurrentDeviceId(accInfo)) {
|
|
||||||
participant[BESTNAME] = tr("Me");
|
|
||||||
participant[ISLOCAL] = true;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
participant[BESTNAME] = accInfo.contactModel->bestNameForContact(uri);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList
|
|
||||||
CallAdapter::getConferencesInfos() const
|
|
||||||
{
|
|
||||||
QVariantList map;
|
|
||||||
const auto& convInfo = lrcInstance_->getConversationFromConvUid(
|
|
||||||
lrcInstance_->get_selectedConvUid());
|
|
||||||
if (convInfo.uid.isEmpty())
|
|
||||||
return map;
|
|
||||||
auto callId = convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId;
|
|
||||||
if (!callId.isEmpty()) {
|
|
||||||
try {
|
|
||||||
auto& participantsModel = lrcInstance_->accountModel()
|
|
||||||
.getAccountInfo(accountId_)
|
|
||||||
.callModel.get()
|
|
||||||
->getParticipantsInfos(callId);
|
|
||||||
for (int index = 0; index < participantsModel.getParticipants().size(); index++) {
|
|
||||||
auto participant = participantsModel.toQJsonObject(index);
|
|
||||||
fillParticipantData(participant);
|
|
||||||
map.push_back(QVariant(participant));
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -629,25 +472,6 @@ void
|
||||||
CallAdapter::connectCallModel(const QString& accountId)
|
CallAdapter::connectCallModel(const QString& accountId)
|
||||||
{
|
{
|
||||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
|
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
|
||||||
|
|
||||||
connect(accInfo.callModel.get(),
|
|
||||||
&CallModel::participantAdded,
|
|
||||||
this,
|
|
||||||
&CallAdapter::onParticipantAdded,
|
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
connect(accInfo.callModel.get(),
|
|
||||||
&CallModel::participantRemoved,
|
|
||||||
this,
|
|
||||||
&CallAdapter::onParticipantRemoved,
|
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
connect(accInfo.callModel.get(),
|
|
||||||
&CallModel::participantUpdated,
|
|
||||||
this,
|
|
||||||
&CallAdapter::onParticipantUpdated,
|
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
connect(accInfo.callModel.get(),
|
connect(accInfo.callModel.get(),
|
||||||
&CallModel::callStarted,
|
&CallModel::callStarted,
|
||||||
this,
|
this,
|
||||||
|
@ -671,11 +495,6 @@ CallAdapter::connectCallModel(const QString& accountId)
|
||||||
this,
|
this,
|
||||||
&CallAdapter::onCallAddedToConference,
|
&CallAdapter::onCallAddedToConference,
|
||||||
Qt::UniqueConnection);
|
Qt::UniqueConnection);
|
||||||
|
|
||||||
connect(accInfo.callModel.get(),
|
|
||||||
&CallModel::callInfosChanged,
|
|
||||||
this,
|
|
||||||
QOverload<const QString&, const QString&>::of(&CallAdapter::onCallInfosChanged));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -719,24 +538,19 @@ CallAdapter::setActiveStream(const QString& uri, const QString& deviceId, const
|
||||||
confId = convInfo.callId;
|
confId = convInfo.callId;
|
||||||
try {
|
try {
|
||||||
const auto call = callModel->getCall(confId);
|
const auto call = callModel->getCall(confId);
|
||||||
auto participants = getConferencesInfos();
|
auto& participantsModel = callModel->getParticipantsInfos(call.id);
|
||||||
std::vector<QJsonObject> activeParticipants = {};
|
auto participants = participantsModel.getParticipants();
|
||||||
|
decltype(participants) activeParticipants = {};
|
||||||
bool removeActive = false;
|
bool removeActive = false;
|
||||||
for (auto part : participants) {
|
for (auto part : participants) {
|
||||||
auto participant = part.toJsonObject();
|
auto isParticipant = part.uri == uri && part.device == deviceId
|
||||||
|
&& part.sinkId == streamId;
|
||||||
auto puri = participant[lrc::api::ParticipantsInfosStrings::URI].toString();
|
if (part.active && !isParticipant)
|
||||||
auto pdeviceId = participant[lrc::api::ParticipantsInfosStrings::DEVICE].toString();
|
activeParticipants.push_back(part);
|
||||||
auto pstreamId = participant[lrc::api::ParticipantsInfosStrings::STREAMID].toString();
|
|
||||||
|
|
||||||
auto isParticipant = puri == uri && pdeviceId == deviceId && pstreamId == streamId;
|
|
||||||
auto active = participant[lrc::api::ParticipantsInfosStrings::ACTIVE].toBool();
|
|
||||||
if (active && !isParticipant)
|
|
||||||
activeParticipants.push_back(participant);
|
|
||||||
|
|
||||||
if (isParticipant) {
|
if (isParticipant) {
|
||||||
// Else, continue.
|
// Else, continue.
|
||||||
if (!active) {
|
if (!part.active) {
|
||||||
callModel->setActiveStream(confId, uri, deviceId, streamId, true);
|
callModel->setActiveStream(confId, uri, deviceId, streamId, true);
|
||||||
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
||||||
} else if (call.layout == lrc::api::call::Layout::ONE_WITH_SMALL) {
|
} else if (call.layout == lrc::api::call::Layout::ONE_WITH_SMALL) {
|
||||||
|
@ -747,12 +561,8 @@ CallAdapter::setActiveStream(const QString& uri, const QString& deviceId, const
|
||||||
}
|
}
|
||||||
if (removeActive) {
|
if (removeActive) {
|
||||||
// If in Big, we can remove other actives
|
// If in Big, we can remove other actives
|
||||||
for (const auto& p : activeParticipants) {
|
for (const auto& part : activeParticipants)
|
||||||
auto puri = p[lrc::api::ParticipantsInfosStrings::URI].toString();
|
callModel->setActiveStream(confId, part.uri, part.device, part.sinkId, false);
|
||||||
auto deviceId = p[lrc::api::ParticipantsInfosStrings::DEVICE].toString();
|
|
||||||
auto streamId = p[lrc::api::ParticipantsInfosStrings::STREAMID].toString();
|
|
||||||
callModel->setActiveStream(confId, puri, deviceId, streamId, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
|
@ -770,31 +580,24 @@ CallAdapter::minimizeParticipant(const QString& uri)
|
||||||
confId = convInfo.callId;
|
confId = convInfo.callId;
|
||||||
try {
|
try {
|
||||||
const auto call = callModel->getCall(confId);
|
const auto call = callModel->getCall(confId);
|
||||||
auto participants = getConferencesInfos();
|
auto& participantsModel = callModel->getParticipantsInfos(call.id);
|
||||||
|
auto participants = participantsModel.getParticipants();
|
||||||
auto activeParticipants = 0;
|
auto activeParticipants = 0;
|
||||||
for (auto& part : participants) {
|
for (auto& part : participants) {
|
||||||
auto participant = part.toJsonObject();
|
if (part.active) {
|
||||||
if (participant[lrc::api::ParticipantsInfosStrings::ACTIVE].toBool()) {
|
|
||||||
activeParticipants += 1;
|
activeParticipants += 1;
|
||||||
if (participant[lrc::api::ParticipantsInfosStrings::URI].toString() == uri
|
if (part.uri == uri && call.layout == lrc::api::call::Layout::ONE_WITH_SMALL) {
|
||||||
&& call.layout == lrc::api::call::Layout::ONE_WITH_SMALL) {
|
callModel->setActiveStream(confId, part.uri, part.device, part.sinkId, false);
|
||||||
auto deviceId = participant[lrc::api::ParticipantsInfosStrings::DEVICE]
|
|
||||||
.toString();
|
|
||||||
auto streamId = participant[lrc::api::ParticipantsInfosStrings::STREAMID]
|
|
||||||
.toString();
|
|
||||||
callModel->setActiveStream(confId, uri, deviceId, streamId, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (activeParticipants == 1) {
|
if (activeParticipants == 1) {
|
||||||
// only one active left, we can change the layout.
|
// only one active left, we can change the layout.
|
||||||
if (call.layout == lrc::api::call::Layout::ONE) {
|
if (call.layout == lrc::api::call::Layout::ONE)
|
||||||
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
|
||||||
} else {
|
else
|
||||||
callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
|
callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "qmladapterbase.h"
|
#include "qmladapterbase.h"
|
||||||
#include "screensaver.h"
|
#include "screensaver.h"
|
||||||
#include "calloverlaymodel.h"
|
#include "calloverlaymodel.h"
|
||||||
#include "callparticipantsmodel.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -80,7 +79,6 @@ public:
|
||||||
Q_INVOKABLE void muteAudioToggle();
|
Q_INVOKABLE void muteAudioToggle();
|
||||||
Q_INVOKABLE void muteCameraToggle();
|
Q_INVOKABLE void muteCameraToggle();
|
||||||
Q_INVOKABLE bool isRecordingThisCall();
|
Q_INVOKABLE bool isRecordingThisCall();
|
||||||
Q_INVOKABLE QVariantList getConferencesInfos() const;
|
|
||||||
Q_INVOKABLE void muteParticipant(const QString& accountUri,
|
Q_INVOKABLE void muteParticipant(const QString& accountUri,
|
||||||
const QString& deviceId,
|
const QString& deviceId,
|
||||||
const QString& sinkId,
|
const QString& sinkId,
|
||||||
|
@ -95,11 +93,10 @@ public:
|
||||||
Q_INVOKABLE void setCallInfo();
|
Q_INVOKABLE void setCallInfo();
|
||||||
Q_INVOKABLE void updateAdvancedInformation();
|
Q_INVOKABLE void updateAdvancedInformation();
|
||||||
|
|
||||||
Q_INVOKABLE bool takeScreenshot(const QImage &image, const QString &path);
|
Q_INVOKABLE bool takeScreenshot(const QImage& image, const QString& path);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
|
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
|
||||||
void callInfosChanged(const QVariant& infos, const QString& accountId, const QString& convUid);
|
|
||||||
|
|
||||||
// For Call Overlay
|
// For Call Overlay
|
||||||
void updateTimeText(const QString& time);
|
void updateTimeText(const QString& time);
|
||||||
|
@ -109,18 +106,13 @@ public Q_SLOTS:
|
||||||
void onShowCallView(const QString& accountId, const QString& convUid);
|
void onShowCallView(const QString& accountId, const QString& convUid);
|
||||||
void onAccountChanged();
|
void onAccountChanged();
|
||||||
void onCallStatusChanged(const QString& accountId, const QString& callId);
|
void onCallStatusChanged(const QString& accountId, const QString& callId);
|
||||||
void onCallInfosChanged(const QString& accountId, const QString& callId);
|
|
||||||
void onCallStatusChanged(const QString& callId, int code);
|
void onCallStatusChanged(const QString& callId, int code);
|
||||||
void onCallAddedToConference(const QString& callId, const QString& confId);
|
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);
|
|
||||||
void onCallStarted(const QString& callId);
|
void onCallStarted(const QString& callId);
|
||||||
void onCallEnded(const QString& callId);
|
void onCallEnded(const QString& callId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showNotification(const QString& accountId, const QString& convUid);
|
void showNotification(const QString& accountId, const QString& convUid);
|
||||||
void fillParticipantData(QJsonObject& participant) const;
|
|
||||||
void preventScreenSaver(bool state);
|
void preventScreenSaver(bool state);
|
||||||
void saveConferenceSubcalls();
|
void saveConferenceSubcalls();
|
||||||
|
|
||||||
|
@ -129,7 +121,6 @@ private:
|
||||||
ScreenSaver screenSaver;
|
ScreenSaver screenSaver;
|
||||||
SystemTray* systemTray_;
|
SystemTray* systemTray_;
|
||||||
QScopedPointer<CallOverlayModel> overlayModel_;
|
QScopedPointer<CallOverlayModel> overlayModel_;
|
||||||
QScopedPointer<CallParticipantsModel> participantsModel_;
|
|
||||||
VectorString currentConfSubcalls_;
|
VectorString currentConfSubcalls_;
|
||||||
|
|
||||||
std::unique_ptr<CallInformationListModel> callInformationListModel_;
|
std::unique_ptr<CallInformationListModel> callInformationListModel_;
|
||||||
|
|
|
@ -16,13 +16,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "currentcall.h"
|
#include "currentcall.h"
|
||||||
|
#include "qmlregister.h"
|
||||||
|
|
||||||
#include <api/callparticipantsmodel.h>
|
#include <api/callparticipantsmodel.h>
|
||||||
|
#include <api/devicemodel.h>
|
||||||
|
|
||||||
CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent)
|
CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, lrcInstance_(lrcInstance)
|
, lrcInstance_(lrcInstance)
|
||||||
{
|
{
|
||||||
|
participantsModel_.reset(new CallParticipantsModel(lrcInstance_, this));
|
||||||
|
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, participantsModel_.get(), "CallParticipantsModel");
|
||||||
|
|
||||||
connect(lrcInstance_,
|
connect(lrcInstance_,
|
||||||
&LRCInstance::currentAccountIdChanged,
|
&LRCInstance::currentAccountIdChanged,
|
||||||
this,
|
this,
|
||||||
|
@ -72,7 +77,17 @@ CurrentCall::updateId(QString callId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set the current id_ if there is a call.
|
// Set the current id_ if there is a call.
|
||||||
set_id((accInfo.callModel->hasCall(callId) ? callId : QString()));
|
auto hasCall = accInfo.callModel->hasCall(callId);
|
||||||
|
set_id((hasCall ? callId : QString()));
|
||||||
|
|
||||||
|
if (hasCall) {
|
||||||
|
try {
|
||||||
|
auto callInfo = accInfo.callModel->getCall(callId);
|
||||||
|
participantsModel_->setParticipants(id_, getConferencesInfos());
|
||||||
|
participantsModel_->setConferenceLayout(static_cast<int>(callInfo.layout), id_);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -105,6 +120,88 @@ CurrentCall::updateParticipants()
|
||||||
set_isConference(uris.size());
|
set_isConference(uris.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurrentCall::onParticipantAdded(const QString& callId, int index)
|
||||||
|
{
|
||||||
|
if (callId != id_)
|
||||||
|
return;
|
||||||
|
auto infos = getConferencesInfos();
|
||||||
|
if (index < infos.size())
|
||||||
|
participantsModel_->addParticipant(index, infos[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurrentCall::onParticipantRemoved(const QString& callId, int index)
|
||||||
|
{
|
||||||
|
if (callId != id_)
|
||||||
|
return;
|
||||||
|
participantsModel_->removeParticipant(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurrentCall::onParticipantUpdated(const QString& callId, int index)
|
||||||
|
{
|
||||||
|
if (callId != id_)
|
||||||
|
return;
|
||||||
|
auto infos = getConferencesInfos();
|
||||||
|
if (index < infos.size())
|
||||||
|
participantsModel_->updateParticipant(index, infos[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurrentCall::fillParticipantData(QJsonObject& participant) const
|
||||||
|
{
|
||||||
|
// TODO: getCurrentDeviceId should be part of CurrentAccount, and Current<thing>
|
||||||
|
// should be read accessible through LRCInstance ??
|
||||||
|
auto getCurrentDeviceId = [](const account::Info& accInfo) -> QString {
|
||||||
|
const auto& deviceList = accInfo.deviceModel->getAllDevices();
|
||||||
|
auto devIt = std::find_if(std::cbegin(deviceList),
|
||||||
|
std::cend(deviceList),
|
||||||
|
[](const Device& dev) { return dev.isCurrent; });
|
||||||
|
return devIt != deviceList.cend() ? devIt->id : QString();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
|
||||||
|
using namespace lrc::api::ParticipantsInfosStrings;
|
||||||
|
|
||||||
|
// If both the URI and the device Id match, we set the "is local" flag
|
||||||
|
// used to filter out the participant.
|
||||||
|
// TODO:
|
||||||
|
// - This filter should always be applied, and any local streams should render
|
||||||
|
// using local sinks. Local non-preview participants should have proxy participant
|
||||||
|
// items replaced into this model using their local sink Ids.
|
||||||
|
// - The app setting should remain and be used to control whether or not the preview
|
||||||
|
// sink partipcant is rendered.
|
||||||
|
auto uri = participant[URI].toString();
|
||||||
|
participant[ISLOCAL] = false;
|
||||||
|
if (uri == accInfo.profileInfo.uri && participant[DEVICE] == getCurrentDeviceId(accInfo)) {
|
||||||
|
participant[BESTNAME] = tr("Me");
|
||||||
|
participant[ISLOCAL] = true;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
participant[BESTNAME] = accInfo.contactModel->bestNameForContact(uri);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList
|
||||||
|
CurrentCall::getConferencesInfos() const
|
||||||
|
{
|
||||||
|
QVariantList map;
|
||||||
|
try {
|
||||||
|
auto callModel = lrcInstance_->getCurrentCallModel();
|
||||||
|
auto& participantsModel = callModel->getParticipantsInfos(id_);
|
||||||
|
for (int index = 0; index < participantsModel.getParticipants().size(); index++) {
|
||||||
|
auto participant = participantsModel.toQJsonObject(index);
|
||||||
|
fillParticipantData(participant);
|
||||||
|
map.push_back(QVariant(participant));
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CurrentCall::updateCallInfo()
|
CurrentCall::updateCallInfo()
|
||||||
{
|
{
|
||||||
|
@ -162,6 +259,7 @@ CurrentCall::updateCallInfo()
|
||||||
QStringList recorders {};
|
QStringList recorders {};
|
||||||
if (callModel->hasCall(id_)) {
|
if (callModel->hasCall(id_)) {
|
||||||
auto callInfo = callModel->getCall(id_);
|
auto callInfo = callModel->getCall(id_);
|
||||||
|
participantsModel_->setConferenceLayout(static_cast<int>(callInfo.layout), id_);
|
||||||
recorders = callInfo.recordingPeers;
|
recorders = callInfo.recordingPeers;
|
||||||
}
|
}
|
||||||
updateRecordingState(callModel->isRecording(id_));
|
updateRecordingState(callModel->isRecording(id_));
|
||||||
|
@ -230,6 +328,21 @@ CurrentCall::connectModel()
|
||||||
this,
|
this,
|
||||||
&CurrentCall::onRecordingStateChanged,
|
&CurrentCall::onRecordingStateChanged,
|
||||||
Qt::UniqueConnection);
|
Qt::UniqueConnection);
|
||||||
|
connect(callModel,
|
||||||
|
&CallModel::participantAdded,
|
||||||
|
this,
|
||||||
|
&CurrentCall::onParticipantAdded,
|
||||||
|
Qt::UniqueConnection);
|
||||||
|
connect(callModel,
|
||||||
|
&CallModel::participantRemoved,
|
||||||
|
this,
|
||||||
|
&CurrentCall::onParticipantRemoved,
|
||||||
|
Qt::UniqueConnection);
|
||||||
|
connect(callModel,
|
||||||
|
&CallModel::participantUpdated,
|
||||||
|
this,
|
||||||
|
&CurrentCall::onParticipantUpdated,
|
||||||
|
Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "lrcinstance.h"
|
#include "lrcinstance.h"
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
|
#include "callparticipantsmodel.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -56,6 +57,7 @@ class CurrentCall final : public QObject
|
||||||
public:
|
public:
|
||||||
explicit CurrentCall(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
explicit CurrentCall(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||||
~CurrentCall() = default;
|
~CurrentCall() = default;
|
||||||
|
Q_INVOKABLE QVariantList getConferencesInfos() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateId(QString callId = {});
|
void updateId(QString callId = {});
|
||||||
|
@ -65,6 +67,7 @@ private:
|
||||||
void updateRemoteRecorders(const QStringList& recorders);
|
void updateRemoteRecorders(const QStringList& recorders);
|
||||||
void updateRecordingState(bool state);
|
void updateRecordingState(bool state);
|
||||||
void connectModel();
|
void connectModel();
|
||||||
|
void fillParticipantData(QJsonObject& participant) const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void onCurrentConvIdChanged();
|
void onCurrentConvIdChanged();
|
||||||
|
@ -73,10 +76,14 @@ private Q_SLOTS:
|
||||||
void onCallInfosChanged(const QString& accountId, const QString& callId);
|
void onCallInfosChanged(const QString& accountId, const QString& callId);
|
||||||
void onCurrentCallChanged(const QString& callId);
|
void onCurrentCallChanged(const QString& callId);
|
||||||
void onParticipantsChanged(const QString& callId);
|
void onParticipantsChanged(const QString& callId);
|
||||||
|
void onParticipantAdded(const QString& callId, int index);
|
||||||
|
void onParticipantRemoved(const QString& callId, int index);
|
||||||
|
void onParticipantUpdated(const QString& callId, int index);
|
||||||
void onRemoteRecordersChanged(const QString& callId, const QStringList& recorders);
|
void onRemoteRecordersChanged(const QString& callId, const QStringList& recorders);
|
||||||
void onRecordingStateChanged(const QString& callId, bool state);
|
void onRecordingStateChanged(const QString& callId, bool state);
|
||||||
void onShowIncomingCallView(const QString& accountId, const QString& convUid);
|
void onShowIncomingCallView(const QString& accountId, const QString& convUid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LRCInstance* lrcInstance_;
|
LRCInstance* lrcInstance_;
|
||||||
|
QScopedPointer<CallParticipantsModel> participantsModel_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1628,6 +1628,21 @@ CallModelPimpl::slotOnConferenceInfosUpdated(const QString& confId,
|
||||||
if (it == calls.end() or not it->second)
|
if (it == calls.end() or not it->second)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO: remove when the rendez-vous UI will be done
|
||||||
|
// For now, the rendez-vous account can see ongoing calls
|
||||||
|
// And must be notified when a new
|
||||||
|
QStringList callList = CallManager::instance().getParticipantList(linked.owner.id, confId);
|
||||||
|
Q_FOREACH (const auto& call, callList) {
|
||||||
|
Q_EMIT linked.callAddedToConference(call, confId);
|
||||||
|
if (calls.find(call) == calls.end()) {
|
||||||
|
qWarning() << "Call not found";
|
||||||
|
} else {
|
||||||
|
calls[call]->videoMuted = it->second->videoMuted;
|
||||||
|
calls[call]->audioMuted = it->second->audioMuted;
|
||||||
|
Q_EMIT linked.callInfosChanged(linked.owner.id, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto participantIt = participantsModel.find(confId);
|
auto participantIt = participantsModel.find(confId);
|
||||||
if (participantIt == participantsModel.end())
|
if (participantIt == participantsModel.end())
|
||||||
participantIt = participantsModel
|
participantIt = participantsModel
|
||||||
|
@ -1657,20 +1672,6 @@ CallModelPimpl::slotOnConferenceInfosUpdated(const QString& confId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove when the rendez-vous UI will be done
|
|
||||||
// For now, the rendez-vous account can see ongoing calls
|
|
||||||
// And must be notified when a new
|
|
||||||
QStringList callList = CallManager::instance().getParticipantList(linked.owner.id, confId);
|
|
||||||
Q_FOREACH (const auto& call, callList) {
|
|
||||||
Q_EMIT linked.callAddedToConference(call, confId);
|
|
||||||
if (calls.find(call) == calls.end()) {
|
|
||||||
qWarning() << "Call not found";
|
|
||||||
} else {
|
|
||||||
calls[call]->videoMuted = it->second->videoMuted;
|
|
||||||
calls[call]->audioMuted = it->second->audioMuted;
|
|
||||||
Q_EMIT linked.callInfosChanged(linked.owner.id, call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Q_EMIT linked.callInfosChanged(linked.owner.id, confId);
|
Q_EMIT linked.callInfosChanged(linked.owner.id, confId);
|
||||||
Q_EMIT linked.participantsChanged(confId);
|
Q_EMIT linked.participantsChanged(confId);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue