1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-15 04:05:39 +02:00
jami-client-qt/src/libclient/codecmodel.cpp
Sébastien Blin d9aee635a7 misc: drop 'new' prefix from model names
Change-Id: Idc960c96e4647dbb6f8c1d64f545fe25c80bbaa5
2022-07-12 10:43:59 -04:00

379 lines
12 KiB
C++

/****************************************************************************
* Copyright (C) 2017-2022 Savoir-faire Linux Inc. *
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library 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 *
* Lesser 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 "api/codecmodel.h"
// LRC
#include "callbackshandler.h"
#include "dbus/configurationmanager.h"
// Daemon
#include <account_const.h>
// Qt
#include <QObject>
#include <QList>
// std
#include <mutex>
namespace lrc {
using namespace api;
class CodecModelPimpl : public QObject
{
Q_OBJECT
public:
CodecModelPimpl(const CodecModel& linked, const CallbacksHandler& callbacksHandler);
~CodecModelPimpl();
void loadFromDaemon();
QVector<unsigned int> codecsList_;
QList<Codec> videoCodecs;
std::mutex audioCodecsMtx;
QList<Codec> audioCodecs;
std::mutex videoCodecsMtx;
const CallbacksHandler& callbacksHandler;
const CodecModel& linked;
void setActiveCodecs();
void setCodecDetails(const Codec& codec, bool isAudio);
private:
void addCodec(const unsigned int& id, const QVector<unsigned int>& activeCodecs);
};
CodecModel::CodecModel(const account::Info& owner, const CallbacksHandler& callbacksHandler)
: owner(owner)
, pimpl_(std::make_unique<CodecModelPimpl>(*this, callbacksHandler))
{}
CodecModel::~CodecModel() {}
QList<Codec>
CodecModel::getAudioCodecs() const
{
return pimpl_->audioCodecs;
}
QList<Codec>
CodecModel::getVideoCodecs() const
{
return pimpl_->videoCodecs;
}
void
CodecModel::increasePriority(const unsigned int& codecId, bool isVideo)
{
auto& codecs = isVideo ? pimpl_->videoCodecs : pimpl_->audioCodecs;
auto& mutex = isVideo ? pimpl_->videoCodecsMtx : pimpl_->audioCodecsMtx;
{
std::unique_lock<std::mutex> lock(mutex);
auto it = codecs.begin();
if (codecs.begin()->id == codecId) {
// Already at top, abort
return;
}
while (it != codecs.end()) {
if (it->id == codecId) {
std::iter_swap(it, std::prev(it));
break;
}
it++;
}
}
pimpl_->setActiveCodecs();
}
void
CodecModel::decreasePriority(const unsigned int& codecId, bool isVideo)
{
auto& codecs = isVideo ? pimpl_->videoCodecs : pimpl_->audioCodecs;
auto& mutex = isVideo ? pimpl_->videoCodecsMtx : pimpl_->audioCodecsMtx;
{
std::unique_lock<std::mutex> lock(mutex);
auto it = codecs.begin();
if (codecs.size() > 0 && (codecs.end() - 1)->id == codecId) {
// Already at bottom, abort
return;
}
while (it != codecs.end()) {
if (it->id == codecId) {
std::iter_swap(it, std::next(it));
break;
}
it++;
}
}
pimpl_->setActiveCodecs();
}
bool
CodecModel::enable(const unsigned int& codecId, bool enabled)
{
auto redraw = false;
auto isAudio = true;
{
std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx);
auto allDisabled = true;
for (auto& codec : pimpl_->videoCodecs) {
if (codec.id == codecId) {
if (codec.enabled == enabled)
return redraw;
codec.enabled = enabled;
isAudio = false;
}
if (codec.enabled) {
allDisabled = false;
}
}
if (allDisabled) {
redraw = true;
}
}
if (isAudio) {
std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx);
auto allDisabled = true;
for (auto& codec : pimpl_->audioCodecs) {
if (codec.id == codecId) {
if (codec.enabled == enabled)
return redraw;
codec.enabled = enabled;
}
if (codec.enabled) {
allDisabled = false;
}
}
if (allDisabled) {
redraw = true;
}
}
pimpl_->setActiveCodecs();
return redraw;
}
void
CodecModel::autoQuality(const unsigned int& codecId, bool on)
{
auto isAudio = true;
Codec finalCodec;
{
std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx);
for (auto& codec : pimpl_->videoCodecs) {
if (codec.id == codecId) {
if (codec.auto_quality_enabled == on)
return;
codec.auto_quality_enabled = on;
isAudio = false;
finalCodec = codec;
break;
}
}
}
if (isAudio) {
std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx);
for (auto& codec : pimpl_->audioCodecs) {
if (codec.id == codecId) {
if (codec.auto_quality_enabled == on)
return;
codec.auto_quality_enabled = on;
finalCodec = codec;
break;
}
}
}
pimpl_->setCodecDetails(finalCodec, isAudio);
}
void
CodecModel::quality(const unsigned int& codecId, double quality)
{
auto isAudio = true;
auto qualityStr = toQString(static_cast<int>(quality));
Codec finalCodec;
{
std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx);
for (auto& codec : pimpl_->videoCodecs) {
if (codec.id == codecId) {
if (codec.quality == qualityStr)
return;
codec.quality = qualityStr;
isAudio = false;
finalCodec = codec;
break;
}
}
}
if (isAudio) {
std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx);
for (auto& codec : pimpl_->audioCodecs) {
if (codec.id == codecId) {
if (codec.quality == qualityStr)
return;
codec.quality = qualityStr;
finalCodec = codec;
break;
}
}
}
pimpl_->setCodecDetails(finalCodec, isAudio);
}
void
CodecModel::bitrate(const unsigned int& codecId, double bitrate)
{
auto isAudio = true;
auto bitrateStr = toQString(static_cast<int>(bitrate));
Codec finalCodec;
{
std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx);
for (auto& codec : pimpl_->videoCodecs) {
if (codec.id == codecId) {
if (codec.bitrate == bitrateStr)
return;
codec.bitrate = bitrateStr;
isAudio = false;
finalCodec = codec;
break;
}
}
}
if (isAudio) {
std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx);
for (auto& codec : pimpl_->audioCodecs) {
if (codec.id == codecId) {
if (codec.bitrate == bitrateStr)
return;
codec.bitrate = bitrateStr;
finalCodec = codec;
break;
}
}
}
pimpl_->setCodecDetails(finalCodec, isAudio);
}
CodecModelPimpl::CodecModelPimpl(const CodecModel& linked, const CallbacksHandler& callbacksHandler)
: linked(linked)
, callbacksHandler(callbacksHandler)
{
codecsList_ = ConfigurationManager::instance().getCodecList();
loadFromDaemon();
}
CodecModelPimpl::~CodecModelPimpl() {}
void
CodecModelPimpl::loadFromDaemon()
{
{
std::unique_lock<std::mutex> lock(audioCodecsMtx);
audioCodecs.clear();
}
{
std::unique_lock<std::mutex> lock(videoCodecsMtx);
videoCodecs.clear();
}
QVector<unsigned int> activeCodecs = ConfigurationManager::instance().getActiveCodecList(
linked.owner.id);
for (const auto& id : activeCodecs) {
addCodec(id, activeCodecs);
}
for (const auto& id : codecsList_) {
if (activeCodecs.indexOf(id) != -1)
continue;
addCodec(id, activeCodecs);
}
}
void
CodecModelPimpl::setActiveCodecs()
{
QVector<unsigned int> enabledCodecs;
{
std::unique_lock<std::mutex> lock(videoCodecsMtx);
for (auto& codec : videoCodecs) {
if (codec.enabled) {
enabledCodecs.push_back(codec.id);
}
}
}
{
std::unique_lock<std::mutex> lock(audioCodecsMtx);
for (auto& codec : audioCodecs) {
if (codec.enabled) {
enabledCodecs.push_back(codec.id);
}
}
}
ConfigurationManager::instance().setActiveCodecList(linked.owner.id, enabledCodecs);
// Refresh list from daemon
loadFromDaemon();
}
void
CodecModelPimpl::addCodec(const unsigned int& id, const QVector<unsigned int>& activeCodecs)
{
MapStringString details = ConfigurationManager::instance().getCodecDetails(linked.owner.id, id);
Codec codec;
codec.id = id;
codec.enabled = activeCodecs.indexOf(id) != -1;
codec.name = details[DRing::Account::ConfProperties::CodecInfo::NAME];
codec.samplerate = details[DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE];
codec.bitrate = details[DRing::Account::ConfProperties::CodecInfo::BITRATE];
codec.min_bitrate = details[DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE];
codec.max_bitrate = details[DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE];
codec.type = details[DRing::Account::ConfProperties::CodecInfo::TYPE];
codec.quality = details[DRing::Account::ConfProperties::CodecInfo::QUALITY];
codec.min_quality = details[DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY];
codec.max_quality = details[DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY];
codec.auto_quality_enabled
= details[DRing::Account::ConfProperties::CodecInfo::AUTO_QUALITY_ENABLED] == "true";
if (codec.type == "AUDIO") {
std::unique_lock<std::mutex> lock(audioCodecsMtx);
audioCodecs.push_back(codec);
} else {
std::unique_lock<std::mutex> lock(videoCodecsMtx);
videoCodecs.push_back(codec);
}
}
void
CodecModelPimpl::setCodecDetails(const Codec& codec, bool isAudio)
{
MapStringString details;
details[DRing::Account::ConfProperties::CodecInfo::NAME] = codec.name;
details[DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE] = codec.samplerate;
details[DRing::Account::ConfProperties::CodecInfo::BITRATE] = codec.bitrate;
details[DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE] = codec.min_bitrate;
details[DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE] = codec.max_bitrate;
details[DRing::Account::ConfProperties::CodecInfo::TYPE] = isAudio ? "AUDIO" : "VIDEO";
details[DRing::Account::ConfProperties::CodecInfo::QUALITY] = codec.quality;
details[DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY] = codec.min_quality;
details[DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY] = codec.max_quality;
details[DRing::Account::ConfProperties::CodecInfo::AUTO_QUALITY_ENABLED]
= codec.auto_quality_enabled ? "true" : "false";
ConfigurationManager::instance().setCodecDetails(linked.owner.id, codec.id, details);
}
} // namespace lrc
#include "codecmodel.moc"
#include "api/moc_codecmodel.cpp"