mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-02-07 15:08:24 +00:00
- Part fix previews for this case. Fix download text for outgoing files after the restart of the application. Update SDK to 5.2.88
314 lines
12 KiB
C++
314 lines
12 KiB
C++
/*
|
|
* Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <QQmlApplicationEngine>
|
|
#include <algorithm>
|
|
|
|
#include "app/App.hpp"
|
|
|
|
#include "ParticipantDeviceListModel.hpp"
|
|
#include "utils/Utils.hpp"
|
|
|
|
#include "components/Components.hpp"
|
|
|
|
// =============================================================================
|
|
|
|
ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr<linphone::Participant> participant, QObject *parent) : ProxyListModel(parent) {
|
|
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
|
|
mCallModel = nullptr;
|
|
for(auto device : devices){
|
|
auto deviceModel = ParticipantDeviceModel::create(mCallModel, device, isMe(device));
|
|
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
|
|
connect(deviceModel.get(), &ParticipantDeviceModel::isSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceSpeaking);
|
|
mList << deviceModel;
|
|
}
|
|
mInitialized = true;
|
|
}
|
|
|
|
ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, QObject *parent) : ProxyListModel(parent) {
|
|
if(callModel && callModel->isConference()) {
|
|
mCallModel = callModel;
|
|
connect(mCallModel, &CallModel::conferenceModelChanged, this, &ParticipantDeviceListModel::onConferenceModelChanged);
|
|
initConferenceModel();
|
|
}
|
|
}
|
|
|
|
ParticipantDeviceListModel::~ParticipantDeviceListModel(){
|
|
}
|
|
|
|
void ParticipantDeviceListModel::initConferenceModel(){
|
|
if(!mInitialized && mCallModel){
|
|
auto conferenceModel = mCallModel->getConferenceSharedModel();
|
|
if(conferenceModel){
|
|
updateDevices(conferenceModel->getConference()->getMe()->getDevices(), true);
|
|
updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false);
|
|
|
|
qDebug() << "Conference have " << mList.size() << " devices";
|
|
connect(conferenceModel.get(), &ConferenceModel::activeSpeakerParticipantDevice, this, &ParticipantDeviceListModel::onActiveSpeakerParticipantDevice);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this, &ParticipantDeviceListModel::onParticipantDeviceRemoved);
|
|
connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged);
|
|
connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged);
|
|
mActiveSpeaker = get(conferenceModel->getConference()->getActiveSpeakerParticipantDevice());
|
|
mInitialized = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParticipantDeviceListModel::updateDevices(std::shared_ptr<linphone::Participant> participant){
|
|
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
|
|
bool meAdded = false;
|
|
beginResetModel();
|
|
qDebug() << "Update devices from participant";
|
|
mList.clear();
|
|
for(auto device : devices){
|
|
bool addMe = isMe(device);
|
|
auto deviceModel = ParticipantDeviceModel::create(mCallModel, device, addMe);
|
|
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
|
|
connect(deviceModel.get(), &ParticipantDeviceModel::isSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceSpeaking);
|
|
mList << deviceModel;
|
|
if( addMe)
|
|
meAdded = true;
|
|
}
|
|
endResetModel();
|
|
if( meAdded)
|
|
emit meChanged();
|
|
}
|
|
|
|
void ParticipantDeviceListModel::updateDevices(const std::list<std::shared_ptr<linphone::ParticipantDevice>>& devices, const bool& isMe){
|
|
for(auto device : devices){
|
|
add(device);
|
|
}
|
|
}
|
|
|
|
bool ParticipantDeviceListModel::add(std::shared_ptr<linphone::ParticipantDevice> deviceToAdd){
|
|
auto deviceToAddAddr = deviceToAdd->getAddress();
|
|
int row = 0;
|
|
qDebug() << "Adding device " << deviceToAdd->getAddress()->asString().c_str();
|
|
for(auto item : mList) {
|
|
auto deviceModel = item.objectCast<ParticipantDeviceModel>();
|
|
if(deviceModel->getDevice() == deviceToAdd) {
|
|
qDebug() << "Device already exist. Send video update event";
|
|
deviceModel->updateVideoEnabled();
|
|
return false;
|
|
}else if(deviceToAddAddr->equal(deviceModel->getDevice()->getAddress())){// Address is the same (same device) but the model is using another linphone object. Replace it.
|
|
qDebug() << "Replacing device : Device exists but the model is using another linphone object.";
|
|
deviceModel->updateVideoEnabled();
|
|
removeRow(row);
|
|
break;
|
|
}
|
|
++row;
|
|
}
|
|
bool addMe = isMe(deviceToAdd);
|
|
auto deviceModel = ParticipantDeviceModel::create(mCallModel, deviceToAdd, addMe);
|
|
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
|
|
connect(deviceModel.get(), &ParticipantDeviceModel::isSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceSpeaking);
|
|
ProxyListModel::add<ParticipantDeviceModel>(deviceModel);
|
|
qDebug() << "Device added. Count=" << mList.count();
|
|
QStringList debugDevices;
|
|
for(auto i : mList){
|
|
auto item = i.objectCast<ParticipantDeviceModel>();
|
|
debugDevices.push_back( item->getAddress());
|
|
}
|
|
qDebug() << debugDevices.join("\n");
|
|
if( addMe){
|
|
qDebug() << "Added a me device";
|
|
emit meChanged();
|
|
}else if(mList.size() == 1 || (mList.size() == 2 && isMe(mList.front().objectCast<ParticipantDeviceModel>()->getDevice()))){
|
|
mActiveSpeaker = mList.back().objectCast<ParticipantDeviceModel>();
|
|
emit activeSpeakerChanged();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ParticipantDeviceListModel::remove(std::shared_ptr<const linphone::ParticipantDevice> deviceToRemove){
|
|
int row = 0;
|
|
for(auto item : mList){
|
|
auto device = item.objectCast<ParticipantDeviceModel>();
|
|
if( device->getDevice() == deviceToRemove){
|
|
device->updateVideoEnabled();
|
|
removeRow(row);
|
|
return true;
|
|
}else
|
|
++row;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
QSharedPointer<ParticipantDeviceModel> ParticipantDeviceListModel::get(std::shared_ptr<const linphone::ParticipantDevice> deviceToGet, int * index){
|
|
int row = 0;
|
|
for(auto item : mList){
|
|
auto device = item.objectCast<ParticipantDeviceModel>();
|
|
if( device->getDevice() == deviceToGet){
|
|
if(index)
|
|
*index = row;
|
|
return device;
|
|
}else
|
|
++row;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
QSharedPointer<ParticipantDeviceModel> ParticipantDeviceListModel::getMe(int * index)const{
|
|
int row = 0;
|
|
for(auto item : mList){
|
|
auto device = item.objectCast<ParticipantDeviceModel>();
|
|
if( device->isMe() && device->isLocal()){
|
|
if(index)
|
|
*index = row;
|
|
return device;
|
|
}else
|
|
++row;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
ParticipantDeviceModel* ParticipantDeviceListModel::getActiveSpeakerModel() const{
|
|
return mActiveSpeaker.get();
|
|
}
|
|
|
|
bool ParticipantDeviceListModel::isMe(std::shared_ptr<linphone::ParticipantDevice> deviceToCheck)const{
|
|
if(mCallModel){
|
|
auto devices = mCallModel->getConferenceSharedModel()->getConference()->getMe()->getDevices();
|
|
auto deviceToCheckAddress = deviceToCheck->getAddress();
|
|
for(auto device : devices){
|
|
if(deviceToCheckAddress == device->getAddress())
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ParticipantDeviceListModel::isMeAlone() const{
|
|
for(auto item : mList){
|
|
auto device = item.objectCast<ParticipantDeviceModel>();
|
|
if( !isMe(device->getDevice()))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onConferenceModelChanged (){
|
|
if(!mInitialized){
|
|
initConferenceModel();
|
|
}
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device){
|
|
emit securityLevelChanged(device);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------
|
|
void ParticipantDeviceListModel::onParticipantAdded(const std::shared_ptr<const linphone::Participant> & participant){
|
|
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
|
|
if(devices.size() == 0)
|
|
qDebug() << "Participant has no device. It will not be added : " << participant->getAddress()->asString().c_str();
|
|
else
|
|
for(auto device : devices)
|
|
add(device);
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantRemoved(const std::shared_ptr<const linphone::Participant> & participant){
|
|
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
|
|
for(auto device : devices)
|
|
remove(device);
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
|
qDebug() << "Adding new device : " << mList.count();
|
|
auto conferenceModel = mCallModel->getConferenceSharedModel();
|
|
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices;
|
|
for(int i = 0 ; i < 2 ; ++i){
|
|
if( i == 0)
|
|
devices = conferenceModel->getConference()->getParticipantDeviceList();// Active devices.
|
|
else
|
|
devices = conferenceModel->getConference()->getMe()->getDevices();
|
|
for(auto realParticipantDevice : devices){
|
|
if( realParticipantDevice == participantDevice){
|
|
add(realParticipantDevice);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
qDebug() << "No participant device found from linphone::ParticipantDevice at onParticipantDeviceAdded";
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
|
qDebug() << "Removing participant device : " << mList.count();
|
|
if(!remove(participantDevice))
|
|
qDebug() << "No participant device found from linphone::ParticipantDevice at onParticipantDeviceRemoved";
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onConferenceStateChanged(linphone::Conference::State newState){
|
|
if(newState == linphone::Conference::State::Created){
|
|
if(mCallModel && mCallModel->isConference()) {
|
|
auto conferenceModel = mCallModel->getConferenceSharedModel();
|
|
updateDevices(conferenceModel->getConference()->getMe()->getDevices(), true);
|
|
updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false);
|
|
}
|
|
emit conferenceCreated();
|
|
}
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
|
auto device = get(participantDevice);
|
|
if(device)
|
|
device->updateVideoEnabled();
|
|
else
|
|
onParticipantDeviceAdded(participantDevice);
|
|
|
|
device = get(participantDevice);
|
|
if( device && device->isMe()){ // Capability change for me. Update all videos.
|
|
for(auto item : mList) {
|
|
auto device = item.objectCast<ParticipantDeviceModel>();
|
|
device->updateVideoEnabled();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
|
auto device = get(participantDevice);
|
|
if(device)
|
|
device->updateVideoEnabled();
|
|
else
|
|
onParticipantDeviceAdded(participantDevice);
|
|
}
|
|
void ParticipantDeviceListModel::onActiveSpeakerParticipantDevice(const std::shared_ptr<const linphone::ParticipantDevice>& participantDevice){
|
|
auto device = get(participantDevice);
|
|
if( device){
|
|
mActiveSpeaker = device;
|
|
emit activeSpeakerChanged();
|
|
}
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking){
|
|
auto device = get(participantDevice);
|
|
if( device)
|
|
emit participantSpeaking(device.get());
|
|
}
|
|
|
|
void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){
|
|
|
|
}
|