/*
* 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 .
*/
#include "ParticipantDeviceList.hpp"
#include "core/App.hpp"
#include "core/participant/ParticipantCore.hpp"
#include
#include
DEFINE_ABSTRACT_OBJECT(ParticipantDeviceList)
QSharedPointer
ParticipantDeviceList::create(const std::shared_ptr &participant) {
auto model = QSharedPointer(new ParticipantDeviceList(participant), &QObject::deleteLater);
model->moveToThread(App::getInstance()->thread());
model->setSelf(model);
return model;
}
QSharedPointer ParticipantDeviceList::create() {
auto model = QSharedPointer(new ParticipantDeviceList(), &QObject::deleteLater);
model->moveToThread(App::getInstance()->thread());
model->setSelf(model);
return model;
}
ParticipantDeviceList::ParticipantDeviceList(const std::shared_ptr &participant, QObject *parent)
: ListProxy(parent) {
std::list> devices = participant->getDevices();
for (auto device : devices) {
auto deviceModel = ParticipantDeviceCore::create(device, isMe(device));
// connect(this, &ParticipantDeviceList::securityLevelChanged, deviceModel.get(),
// &ParticipantDeviceCore::onSecurityLevelChanged);
connect(deviceModel.get(), &ParticipantDeviceCore::isSpeakingChanged, this,
&ParticipantDeviceList::onParticipantDeviceSpeaking);
mList << deviceModel;
}
mInitialized = true;
}
ParticipantDeviceList::ParticipantDeviceList(QObject *parent) {
mustBeInMainThread(getClassName());
}
// ParticipantDeviceList::ParticipantDeviceList(CallModel *callModel, QObject *parent) : ProxyListModel(parent) {
// if (callModel && callModel->isConference()) {
// mCallModel = callModel;
// connect(mCallModel, &CallModel::conferenceModelChanged, this, &ParticipantDeviceList::onConferenceModelChanged);
// initConferenceModel();
// }
// }
ParticipantDeviceList::~ParticipantDeviceList() {
mustBeInMainThread(getClassName());
}
void ParticipantDeviceList::setSelf(QSharedPointer me) {
}
void ParticipantDeviceList::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,
// &ParticipantDeviceList::onActiveSpeakerParticipantDevice);
// connect(conferenceModel.get(), &ConferenceModel::participantAdded, this,
// &ParticipantDeviceList::onParticipantAdded);
// connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this,
// &ParticipantDeviceList::onParticipantRemoved);
// connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this,
// &ParticipantDeviceList::onParticipantDeviceAdded);
// connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this,
// &ParticipantDeviceList::onParticipantDeviceRemoved);
// connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this,
// &ParticipantDeviceList::onConferenceStateChanged);
// connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this,
// &ParticipantDeviceList::onParticipantDeviceMediaCapabilityChanged);
// connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this,
// &ParticipantDeviceList::onParticipantDeviceMediaAvailabilityChanged);
// connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this,
// &ParticipantDeviceList::onParticipantDeviceIsSpeakingChanged);
// mActiveSpeaker = get(conferenceModel->getConference()->getActiveSpeakerParticipantDevice());
// mInitialized = true;
// }
// }
}
void ParticipantDeviceList::updateDevices(std::shared_ptr participant) {
std::list> devices = participant->getDevices();
bool meAdded = false;
beginResetModel();
qDebug() << "Update devices from participant";
mList.clear();
for (auto device : devices) {
bool addMe = isMe(device);
auto deviceModel = ParticipantDeviceCore::create(device, addMe);
// connect(this, &ParticipantDeviceList::securityLevelChanged, deviceModel.get(),
// &ParticipantDeviceCore::onSecurityLevelChanged);
connect(deviceModel.get(), &ParticipantDeviceCore::isSpeakingChanged, this,
&ParticipantDeviceList::onParticipantDeviceSpeaking);
mList << deviceModel;
if (addMe) meAdded = true;
}
endResetModel();
if (meAdded) emit meChanged();
}
void ParticipantDeviceList::updateDevices(const std::list> &devices,
const bool &isMe) {
for (auto device : devices) {
add(device);
}
}
bool ParticipantDeviceList::add(const QSharedPointer &deviceToAdd) {
auto deviceToAddAddr = deviceToAdd->getAddress();
int row = 0;
qDebug() << "Adding device " << deviceToAdd->getAddress();
for (auto item : mList) {
auto deviceCore = item.objectCast();
if (deviceCore == deviceToAdd) {
qDebug() << "Device already exist. Send video update event";
// deviceCore->updateVideoEnabled();
return false;
} else if (deviceToAddAddr == deviceCore->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.";
// deviceCore->updateVideoEnabled();
removeRow(row);
break;
}
++row;
}
bool addMe = isMe(deviceToAdd);
auto deviceModel = ParticipantDeviceCore::create(deviceToAdd, addMe);
// connect(this, &ParticipantDeviceList::securityLevelChanged, deviceModel.get(),
// &ParticipantDeviceCore::onSecurityLevelChanged);
connect(deviceModel.get(), &ParticipantDeviceCore::isSpeakingChanged, this,
&ParticipantDeviceList::onParticipantDeviceSpeaking);
ListProxy::add(deviceModel);
qDebug() << "Device added. Count=" << mList.count();
QStringList debugDevices;
for (auto i : mList) {
auto item = i.objectCast();
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()->getDevice()))) {
mActiveSpeaker = mList.back().objectCast();
emit activeSpeakerChanged();
}
return true;
}
bool ParticipantDeviceList::remove(std::shared_ptr deviceToRemove) {
int row = 0;
for (auto item : mList) {
auto device = item.objectCast();
if (device->getDevice() == deviceToRemove) {
// device->updateVideoEnabled();
removeRow(row);
return true;
} else ++row;
}
return false;
}
QSharedPointer
ParticipantDeviceList::get(std::shared_ptr deviceToGet, int *index) {
int row = 0;
for (auto item : mList) {
auto device = item.objectCast();
if (device->getDevice() == deviceToGet) {
if (index) *index = row;
return device;
} else ++row;
}
return nullptr;
}
QSharedPointer ParticipantDeviceList::getMe(int *index) const {
int row = 0;
for (auto item : mList) {
auto device = item.objectCast();
if (device->isMe() && device->isLocal()) {
if (index) *index = row;
return device;
} else ++row;
}
return nullptr;
}
ParticipantDeviceCore *ParticipantDeviceList::getActiveSpeakerModel() const {
return mActiveSpeaker.get();
}
bool ParticipantDeviceList::isMe(std::shared_ptr 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 ParticipantDeviceList::isMeAlone() const {
for (auto item : mList) {
auto device = item.objectCast();
if (!isMe(device->getDevice())) return false;
}
return true;
}
void ParticipantDeviceList::onConferenceModelChanged() {
if (!mInitialized) {
initConferenceModel();
}
}
void ParticipantDeviceList::onSecurityLevelChanged(std::shared_ptr device) {
emit securityLevelChanged(device);
}
//----------------------------------------------------------------------------------------------------------
void ParticipantDeviceList::onParticipantAdded(const std::shared_ptr &participant) {
std::list> 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 ParticipantDeviceList::onParticipantRemoved(const std::shared_ptr &participant) {
std::list> devices = participant->getDevices();
for (auto device : devices)
remove(device);
}
void ParticipantDeviceList::onParticipantDeviceAdded(
const std::shared_ptr &participantDevice) {
qDebug() << "Adding new device : " << mList.count();
// auto conferenceModel = mCallModel->getConferenceSharedModel();
std::list> 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 ParticipantDeviceList::onParticipantDeviceRemoved(
const std::shared_ptr &participantDevice) {
qDebug() << "Removing participant device : " << mList.count();
if (!remove(participantDevice))
qDebug() << "No participant device found from linphone::ParticipantDevice at onParticipantDeviceRemoved";
}
void ParticipantDeviceList::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 ParticipantDeviceList::onParticipantDeviceMediaCapabilityChanged(
const std::shared_ptr &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();
// device->updateVideoEnabled();
// }
// }
}
void ParticipantDeviceList::onParticipantDeviceMediaAvailabilityChanged(
const std::shared_ptr &participantDevice) {
// auto device = get(participantDevice);
// if (device) device->updateVideoEnabled();
// else onParticipantDeviceAdded(participantDevice);
}
void ParticipantDeviceList::onActiveSpeakerParticipantDevice(
const std::shared_ptr &participantDevice) {
// auto device = get(participantDevice);
// if (device) {
// mActiveSpeaker = device;
// emit activeSpeakerChanged();
// }
}
void ParticipantDeviceList::onParticipantDeviceIsSpeakingChanged(
const std::shared_ptr &participantDevice, bool isSpeaking) {
auto device = get(participantDevice);
if (device) emit participantSpeaking(device.get());
}
void ParticipantDeviceList::onParticipantDeviceSpeaking() {
}