/* * Copyright (c) 2024 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). * * 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 . */ #include "ParticipantDeviceList.hpp" #include "core/App.hpp" #include "core/participant/ParticipantDeviceCore.hpp" #include "core/participant/ParticipantDeviceGui.hpp" #include "tool/Utils.hpp" #include #include DEFINE_ABSTRACT_OBJECT(ParticipantDeviceList) QSharedPointer ParticipantDeviceList::create() { auto model = QSharedPointer(new ParticipantDeviceList(), &QObject::deleteLater); model->moveToThread(App::getInstance()->thread()); model->setSelf(model); return model; } QSharedPointer ParticipantDeviceList::create(const std::shared_ptr &conferenceModel) { auto model = create(); model->setConferenceModel(conferenceModel); return model; } ParticipantDeviceList::ParticipantDeviceList() { App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership); } ParticipantDeviceList::~ParticipantDeviceList() { } QList> ParticipantDeviceList::buildDevices(const std::shared_ptr &conferenceModel) const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); QList> devices; auto lDevices = conferenceModel->getMonitor()->getParticipantDeviceList(); bool haveMe = false; for (auto device : lDevices) { auto deviceCore = ParticipantDeviceCore::create(device); devices << deviceCore; if (deviceCore->isMe()) haveMe = true; } if (!haveMe) { } return devices; } QSharedPointer ParticipantDeviceList::getMe() const { if (mList.size() > 0) { return mList[0].objectCast(); } else return nullptr; } void ParticipantDeviceList::setDevices(QList> devices) { mustBeInMainThread(log().arg(Q_FUNC_INFO)); resetData(devices); lDebug() << log().arg("Add %1 devices").arg(devices.size()); } QSharedPointer ParticipantDeviceList::findDeviceByUniqueAddress(const QString &address) { lDebug() << "address to find" << address; auto found = std::find_if(mList.begin(), mList.end(), [address](const QSharedPointer &obj) { auto device = qobject_cast>(obj); lDebug() << "address" << device->getUniqueAddress(); return device && device->getUniqueAddress() == address; }); if (found != mList.end()) { return qobject_cast>(*found); } else return nullptr; } void ParticipantDeviceList::setConferenceModel(const std::shared_ptr &conferenceModel) { mustBeInMainThread(log().arg(Q_FUNC_INFO)); if (mConferenceModel != conferenceModel) { mConferenceModel = conferenceModel; lDebug() << log().arg("Set Conference %1").arg((quint64)mConferenceModel.get()); if (mConferenceModelConnection->mCore.lock()) { // Ensure to get myself auto oldConnect = mConferenceModelConnection->mCore; // Setself rebuild safepointer setSelf(mConferenceModelConnection->mCore.mQData); // reset connections oldConnect.unlock(); } beginResetModel(); mList.clear(); endResetModel(); if (mConferenceModel) { lDebug() << "[ParticipantDeviceList] : request devices"; mConferenceModelConnection->invokeToModel([this]() { lDebug() << "[ParticipantDeviceList] : build devices"; auto devices = buildDevices(mConferenceModel); mConferenceModelConnection->invokeToCore([this, devices]() { lDebug() << "[ParticipantDeviceList] : set devices"; setDevices(devices); }); }); } } } void ParticipantDeviceList::setSelf(QSharedPointer me) { if (mConferenceModelConnection) mConferenceModelConnection->disconnect(); mConferenceModelConnection = SafeConnection::create(me, mConferenceModel); if (mConferenceModel) { mConferenceModelConnection->makeConnectToModel( &ConferenceModel::participantDeviceAdded, [this](const std::shared_ptr &device) { auto deviceCore = ParticipantDeviceCore::create(device); mConferenceModelConnection->invokeToCore([this, deviceCore]() { lDebug() << "[ParticipantDeviceList] : add a device"; add(deviceCore); }); }); mConferenceModelConnection->makeConnectToModel( &ConferenceModel::participantDeviceRemoved, [this](const std::shared_ptr &conference, const std::shared_ptr &participantDevice) { QString uniqueAddress = Utils::coreStringToAppString(participantDevice->getAddress()->asString().c_str()); auto deviceCore = findDeviceByUniqueAddress(uniqueAddress); mConferenceModelConnection->invokeToCore([this, deviceCore]() { lDebug() << "[ParticipantDeviceList] : remove a device" << deviceCore; if (!remove(deviceCore)) lWarning() << log().arg("Unable to remove") << deviceCore << "as it is not part of the list"; }); }); mConferenceModelConnection->makeConnectToModel( &ConferenceModel::conferenceStateChanged, [this](const std::shared_ptr &conference, linphone::Conference::State state) { lDebug() << "[ParticipantDeviceList] new state = " << (int)state; if (state == linphone::Conference::State::Created) { lDebug() << "[ParticipantDeviceList] : build devices"; auto devices = buildDevices(mConferenceModel); mConferenceModelConnection->invokeToCore([this, devices]() { lDebug() << "[ParticipantDeviceList] : set devices" << devices.size(); setDevices(devices); }); } }); mConferenceModelConnection->makeConnectToCore( &ParticipantDeviceList::lSetConferenceModel, [this](const std::shared_ptr &conferenceModel) { mConferenceModelConnection->invokeToCore( [this, conferenceModel]() { setConferenceModel(conferenceModel); }); }); } } QVariant ParticipantDeviceList::data(const QModelIndex &index, int role) const { int row = index.row(); if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant(); if (role == Qt::DisplayRole) return QVariant::fromValue(new ParticipantDeviceGui(mList[row].objectCast())); return QVariant(); }