mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-15 12:15:49 +02:00
381 lines
12 KiB
C++
381 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/newcodecmodel.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 NewCodecModelPimpl : public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
NewCodecModelPimpl(const NewCodecModel& linked, const CallbacksHandler& callbacksHandler);
|
||
|
~NewCodecModelPimpl();
|
||
|
|
||
|
void loadFromDaemon();
|
||
|
|
||
|
QVector<unsigned int> codecsList_;
|
||
|
QList<Codec> videoCodecs;
|
||
|
std::mutex audioCodecsMtx;
|
||
|
QList<Codec> audioCodecs;
|
||
|
std::mutex videoCodecsMtx;
|
||
|
|
||
|
const CallbacksHandler& callbacksHandler;
|
||
|
const NewCodecModel& linked;
|
||
|
|
||
|
void setActiveCodecs();
|
||
|
void setCodecDetails(const Codec& codec, bool isAudio);
|
||
|
|
||
|
private:
|
||
|
void addCodec(const unsigned int& id, const QVector<unsigned int>& activeCodecs);
|
||
|
};
|
||
|
|
||
|
NewCodecModel::NewCodecModel(const account::Info& owner, const CallbacksHandler& callbacksHandler)
|
||
|
: owner(owner)
|
||
|
, pimpl_(std::make_unique<NewCodecModelPimpl>(*this, callbacksHandler))
|
||
|
{}
|
||
|
|
||
|
NewCodecModel::~NewCodecModel() {}
|
||
|
|
||
|
QList<Codec>
|
||
|
NewCodecModel::getAudioCodecs() const
|
||
|
{
|
||
|
return pimpl_->audioCodecs;
|
||
|
}
|
||
|
|
||
|
QList<Codec>
|
||
|
NewCodecModel::getVideoCodecs() const
|
||
|
{
|
||
|
return pimpl_->videoCodecs;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
NewCodecModel::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
|
||
|
NewCodecModel::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
|
||
|
NewCodecModel::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
|
||
|
NewCodecModel::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
|
||
|
NewCodecModel::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
|
||
|
NewCodecModel::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);
|
||
|
}
|
||
|
|
||
|
NewCodecModelPimpl::NewCodecModelPimpl(const NewCodecModel& linked,
|
||
|
const CallbacksHandler& callbacksHandler)
|
||
|
: linked(linked)
|
||
|
, callbacksHandler(callbacksHandler)
|
||
|
{
|
||
|
codecsList_ = ConfigurationManager::instance().getCodecList();
|
||
|
loadFromDaemon();
|
||
|
}
|
||
|
|
||
|
NewCodecModelPimpl::~NewCodecModelPimpl() {}
|
||
|
|
||
|
void
|
||
|
NewCodecModelPimpl::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
|
||
|
NewCodecModelPimpl::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
|
||
|
NewCodecModelPimpl::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
|
||
|
NewCodecModelPimpl::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 "newcodecmodel.moc"
|
||
|
#include "api/moc_newcodecmodel.cpp"
|