fix #LINQT-1323 fix display name account list

close #LINQT-1324 display loss rate/ jitter buffer in call stats + use the correct stats (audio/video)
This commit is contained in:
Gaelle Braud 2024-10-04 16:28:38 +02:00
parent 11f8163e4b
commit 2b4960882f
7 changed files with 144 additions and 84 deletions

View file

@ -20,6 +20,8 @@
#include "AccountCore.hpp" #include "AccountCore.hpp"
#include "core/App.hpp" #include "core/App.hpp"
#include "model/object/VariantObject.hpp"
#include "model/tool/ToolModel.hpp"
#include "tool/Utils.hpp" #include "tool/Utils.hpp"
#include "tool/thread/SafeConnection.hpp" #include "tool/thread/SafeConnection.hpp"
#include <QHostInfo> #include <QHostInfo>
@ -49,10 +51,16 @@ AccountCore::AccountCore(const std::shared_ptr<linphone::Account> &account) : QO
// mUnreadNotifications = account->getUnreadChatMessageCount() + account->getMissedCallsCount(); // TODO // mUnreadNotifications = account->getUnreadChatMessageCount() + account->getMissedCallsCount(); // TODO
mUnreadNotifications = account->getMissedCallsCount(); mUnreadNotifications = account->getMissedCallsCount();
mDisplayName = Utils::coreStringToAppString(identityAddress->getDisplayName()); mDisplayName = Utils::coreStringToAppString(identityAddress->getDisplayName());
if (mDisplayName.isEmpty()) {
mDisplayName = ToolModel::getDisplayName(mIdentityAddress);
}
mRegisterEnabled = params->registerEnabled(); mRegisterEnabled = params->registerEnabled();
mMwiServerAddress = mMwiServerAddress =
params->getMwiServerAddress() ? Utils::coreStringToAppString(params->getMwiServerAddress()->asString()) : ""; params->getMwiServerAddress() ? Utils::coreStringToAppString(params->getMwiServerAddress()->asString()) : "";
mTransports << "TCP" << "UDP" << "TLS" << "DTLS"; mTransports << "TCP"
<< "UDP"
<< "TLS"
<< "DTLS";
mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(params->getTransport())); mTransport = LinphoneEnums::toString(LinphoneEnums::fromLinphone(params->getTransport()));
mServerAddress = mServerAddress =
params->getServerAddress() ? Utils::coreStringToAppString(params->getServerAddress()->asString()) : ""; params->getServerAddress() ? Utils::coreStringToAppString(params->getServerAddress()->asString()) : "";

View file

@ -31,52 +31,59 @@ DEFINE_ABSTRACT_OBJECT(CallCore)
/***********************************************************************/ /***********************************************************************/
ZrtpStats ZrtpStats::operator=(ZrtpStats s) { ZrtpStats ZrtpStats::operator=(ZrtpStats s) {
cipherAlgorithm = s.cipherAlgorithm; mCipherAlgorithm = s.mCipherAlgorithm;
keyAgreementAlgorithm = s.keyAgreementAlgorithm; mKeyAgreementAlgorithm = s.mKeyAgreementAlgorithm;
hashAlgorithm = s.hashAlgorithm; mHashAlgorithm = s.mHashAlgorithm;
authenticationAlgorithm = s.authenticationAlgorithm; mAuthenticationAlgorithm = s.mAuthenticationAlgorithm;
sasAlgorithm = s.sasAlgorithm; mSasAlgorithm = s.mSasAlgorithm;
isPostQuantum = s.isPostQuantum; mIsPostQuantum = s.mIsPostQuantum;
return *this; return *this;
} }
bool ZrtpStats::operator==(ZrtpStats s) { bool ZrtpStats::operator==(ZrtpStats s) {
return s.cipherAlgorithm == cipherAlgorithm && s.keyAgreementAlgorithm == keyAgreementAlgorithm && return s.mCipherAlgorithm == mCipherAlgorithm && s.mKeyAgreementAlgorithm == mKeyAgreementAlgorithm &&
s.hashAlgorithm == hashAlgorithm && s.authenticationAlgorithm == authenticationAlgorithm && s.mHashAlgorithm == mHashAlgorithm && s.mAuthenticationAlgorithm == mAuthenticationAlgorithm &&
s.sasAlgorithm == sasAlgorithm && s.isPostQuantum == isPostQuantum; s.mSasAlgorithm == mSasAlgorithm && s.mIsPostQuantum == mIsPostQuantum;
} }
bool ZrtpStats::operator!=(ZrtpStats s) { bool ZrtpStats::operator!=(ZrtpStats s) {
return s.cipherAlgorithm != cipherAlgorithm || s.keyAgreementAlgorithm != keyAgreementAlgorithm || return s.mCipherAlgorithm != mCipherAlgorithm || s.mKeyAgreementAlgorithm != mKeyAgreementAlgorithm ||
s.hashAlgorithm != hashAlgorithm || s.authenticationAlgorithm != authenticationAlgorithm || s.mHashAlgorithm != mHashAlgorithm || s.mAuthenticationAlgorithm != mAuthenticationAlgorithm ||
s.sasAlgorithm != sasAlgorithm || s.isPostQuantum != isPostQuantum; s.mSasAlgorithm != mSasAlgorithm || s.mIsPostQuantum != mIsPostQuantum;
} }
AudioStats AudioStats::operator=(AudioStats s) { AudioStats AudioStats::operator=(AudioStats s) {
codec = s.codec; mCodec = s.mCodec;
bandwidth = s.bandwidth; mBandwidth = s.mBandwidth;
mJitterBufferSize = s.mJitterBufferSize;
mLossRate = s.mLossRate;
return *this; return *this;
} }
bool AudioStats::operator==(AudioStats s) { bool AudioStats::operator==(AudioStats s) {
return s.codec == codec && s.bandwidth == bandwidth; return s.mCodec == mCodec && s.mBandwidth == mBandwidth && s.mLossRate == mLossRate &&
s.mJitterBufferSize == mJitterBufferSize;
} }
bool AudioStats::operator!=(AudioStats s) { bool AudioStats::operator!=(AudioStats s) {
return s.codec != codec || s.bandwidth != bandwidth; return s.mCodec != mCodec || s.mBandwidth != mBandwidth || s.mLossRate != mLossRate ||
s.mJitterBufferSize != mJitterBufferSize;
} }
VideoStats VideoStats::operator=(VideoStats s) { VideoStats VideoStats::operator=(VideoStats s) {
codec = s.codec; mCodec = s.mCodec;
bandwidth = s.bandwidth; mBandwidth = s.mBandwidth;
resolution = s.resolution; mResolution = s.mResolution;
fps = s.fps; mFps = s.mFps;
mLossRate = s.mLossRate;
return *this; return *this;
} }
bool VideoStats::operator==(VideoStats s) { bool VideoStats::operator==(VideoStats s) {
return s.codec == codec && s.bandwidth == bandwidth && s.resolution == resolution && s.fps == fps; return s.mCodec == mCodec && s.mBandwidth == mBandwidth && s.mResolution == mResolution && s.mFps == mFps &&
s.mLossRate == mLossRate;
} }
bool VideoStats::operator!=(VideoStats s) { bool VideoStats::operator!=(VideoStats s) {
return s.codec != codec || s.bandwidth != bandwidth || s.resolution != resolution || s.fps != fps; return s.mCodec != mCodec || s.mBandwidth != mBandwidth || s.mResolution != mResolution || s.mFps != mFps ||
s.mLossRate != mLossRate;
} }
/***********************************************************************/ /***********************************************************************/
@ -128,11 +135,11 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
if (mEncryption == LinphoneEnums::MediaEncryption::Zrtp) { if (mEncryption == LinphoneEnums::MediaEncryption::Zrtp) {
auto stats = call->getStats(linphone::StreamType::Audio); auto stats = call->getStats(linphone::StreamType::Audio);
if (stats) { if (stats) {
mZrtpStats.cipherAlgorithm = Utils::coreStringToAppString(stats->getZrtpCipherAlgo()); mZrtpStats.mCipherAlgorithm = Utils::coreStringToAppString(stats->getZrtpCipherAlgo());
mZrtpStats.keyAgreementAlgorithm = Utils::coreStringToAppString(stats->getZrtpKeyAgreementAlgo()); mZrtpStats.mKeyAgreementAlgorithm = Utils::coreStringToAppString(stats->getZrtpKeyAgreementAlgo());
mZrtpStats.hashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo()); mZrtpStats.mHashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo());
mZrtpStats.authenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo()); mZrtpStats.mAuthenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo());
mZrtpStats.sasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo()); mZrtpStats.mSasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo());
} }
} }
auto conference = call->getConference(); auto conference = call->getConference();
@ -320,11 +327,11 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
if (mediaEncryption == linphone::MediaEncryption::ZRTP) { if (mediaEncryption == linphone::MediaEncryption::ZRTP) {
auto stats = call->getAudioStats(); auto stats = call->getAudioStats();
ZrtpStats zrtpStats; ZrtpStats zrtpStats;
zrtpStats.cipherAlgorithm = Utils::coreStringToAppString(stats->getZrtpCipherAlgo()); zrtpStats.mCipherAlgorithm = Utils::coreStringToAppString(stats->getZrtpCipherAlgo());
zrtpStats.keyAgreementAlgorithm = Utils::coreStringToAppString(stats->getZrtpKeyAgreementAlgo()); zrtpStats.mKeyAgreementAlgorithm = Utils::coreStringToAppString(stats->getZrtpKeyAgreementAlgo());
zrtpStats.hashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo()); zrtpStats.mHashAlgorithm = Utils::coreStringToAppString(stats->getZrtpHashAlgo());
zrtpStats.authenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo()); zrtpStats.mAuthenticationAlgorithm = Utils::coreStringToAppString(stats->getZrtpAuthTagAlgo());
zrtpStats.sasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo()); zrtpStats.mSasAlgorithm = Utils::coreStringToAppString(stats->getZrtpSasAlgo());
mCallModelConnection->invokeToCore([this, zrtpStats]() { setZrtpStats(zrtpStats); }); mCallModelConnection->invokeToCore([this, zrtpStats]() { setZrtpStats(zrtpStats); });
} }
}); });
@ -403,13 +410,20 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
auto playloadType = call->getCurrentParams()->getUsedAudioPayloadType(); auto playloadType = call->getCurrentParams()->getUsedAudioPayloadType();
auto codecType = playloadType ? playloadType->getMimeType() : ""; auto codecType = playloadType ? playloadType->getMimeType() : "";
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0; auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
audioStats.codec = tr("Codec: %1 / %2 kHz").arg(Utils::coreStringToAppString(codecType)).arg(codecRate); audioStats.mCodec =
if (stats) { tr("Codec: %1 / %2 kHz").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
audioStats.bandwidth = tr("Bande passante : %1 %2 %3 %4") auto linAudioStats = call->getAudioStats();
.arg("") if (linAudioStats) {
.arg(stats->getUploadBandwidth()) audioStats.mBandwidth = tr("Bande passante : %1 %2 %3 %4")
.arg("") .arg("")
.arg(stats->getDownloadBandwidth()); .arg(linAudioStats->getUploadBandwidth())
.arg("")
.arg(linAudioStats->getDownloadBandwidth());
audioStats.mLossRate = tr("Taux de perte: %1 \% %2 \%")
.arg(linAudioStats->getSenderLossRate())
.arg(linAudioStats->getReceiverLossRate());
audioStats.mJitterBufferSize =
tr("Tampon de gigue: %1 ms").arg(linAudioStats->getJitterBufferSizeMs());
} }
setAudioStats(audioStats); setAudioStats(audioStats);
} else if (stats->getType() == linphone::StreamType::Video) { } else if (stats->getType() == linphone::StreamType::Video) {
@ -418,24 +432,29 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
auto playloadType = params->getUsedVideoPayloadType(); auto playloadType = params->getUsedVideoPayloadType();
auto codecType = playloadType ? playloadType->getMimeType() : ""; auto codecType = playloadType ? playloadType->getMimeType() : "";
auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0; auto codecRate = playloadType ? playloadType->getClockRate() / 1000 : 0;
videoStats.codec = tr("Codec: %1 / %2 kHz").arg(Utils::coreStringToAppString(codecType)).arg(codecRate); videoStats.mCodec =
tr("Codec: %1 / %2 kHz").arg(Utils::coreStringToAppString(codecType)).arg(codecRate);
auto linVideoStats = call->getVideoStats();
if (stats) { if (stats) {
videoStats.bandwidth = tr("Bande passante : %1 %2 %3 %4") videoStats.mBandwidth = tr("Bande passante : %1 %2 %3 %4")
.arg("") .arg("")
.arg(stats->getUploadBandwidth()) .arg(linVideoStats->getUploadBandwidth())
.arg("") .arg("")
.arg(stats->getDownloadBandwidth()); .arg(linVideoStats->getDownloadBandwidth());
videoStats.mLossRate = tr("Taux de perte: %1 \% %2 \%")
.arg(linVideoStats->getSenderLossRate())
.arg(linVideoStats->getReceiverLossRate());
} }
auto sentResolution = auto sentResolution =
params->getSentVideoDefinition() ? params->getSentVideoDefinition()->getName() : ""; params->getSentVideoDefinition() ? params->getSentVideoDefinition()->getName() : "";
auto receivedResolution = auto receivedResolution =
params->getReceivedVideoDefinition() ? params->getReceivedVideoDefinition()->getName() : ""; params->getReceivedVideoDefinition() ? params->getReceivedVideoDefinition()->getName() : "";
videoStats.resolution = tr("Définition vidéo : %1 %2 %3 %4") videoStats.mResolution = tr("Définition vidéo : %1 %2 %3 %4")
.arg("", Utils::coreStringToAppString(sentResolution), "", .arg("", Utils::coreStringToAppString(sentResolution), "",
Utils::coreStringToAppString(receivedResolution)); Utils::coreStringToAppString(receivedResolution));
auto sentFps = params->getSentFramerate(); auto sentFps = params->getSentFramerate();
auto receivedFps = params->getReceivedFramerate(); auto receivedFps = params->getReceivedFramerate();
videoStats.fps = tr("FPS : %1 %2 %3 %4").arg("").arg(sentFps).arg("").arg(receivedFps); videoStats.mFps = tr("FPS : %1 %2 %3 %4").arg("").arg(sentFps).arg("").arg(receivedFps);
setVideoStats(videoStats); setVideoStats(videoStats);
} }
}); });

View file

@ -34,19 +34,19 @@
struct ZrtpStats { struct ZrtpStats {
Q_GADGET Q_GADGET
Q_PROPERTY(QString cipherAlgo MEMBER cipherAlgorithm) Q_PROPERTY(QString cipherAlgo MEMBER mCipherAlgorithm)
Q_PROPERTY(QString keyAgreementAlgo MEMBER keyAgreementAlgorithm) Q_PROPERTY(QString keyAgreementAlgo MEMBER mKeyAgreementAlgorithm)
Q_PROPERTY(QString hashAlgo MEMBER hashAlgorithm) Q_PROPERTY(QString hashAlgo MEMBER mHashAlgorithm)
Q_PROPERTY(QString authenticationAlgo MEMBER authenticationAlgorithm) Q_PROPERTY(QString authenticationAlgo MEMBER mAuthenticationAlgorithm)
Q_PROPERTY(QString sasAlgo MEMBER sasAlgorithm) Q_PROPERTY(QString sasAlgo MEMBER mSasAlgorithm)
Q_PROPERTY(bool isPostQuantum MEMBER isPostQuantum) Q_PROPERTY(bool isPostQuantum MEMBER mIsPostQuantum)
public: public:
bool isPostQuantum = false; bool mIsPostQuantum = false;
QString cipherAlgorithm; QString mCipherAlgorithm;
QString keyAgreementAlgorithm; QString mKeyAgreementAlgorithm;
QString hashAlgorithm; QString mHashAlgorithm;
QString authenticationAlgorithm; QString mAuthenticationAlgorithm;
QString sasAlgorithm; QString mSasAlgorithm;
ZrtpStats operator=(ZrtpStats s); ZrtpStats operator=(ZrtpStats s);
bool operator==(ZrtpStats s); bool operator==(ZrtpStats s);
@ -55,12 +55,16 @@ public:
struct AudioStats { struct AudioStats {
Q_GADGET Q_GADGET
Q_PROPERTY(QString codec MEMBER codec) Q_PROPERTY(QString codec MEMBER mCodec)
Q_PROPERTY(QString bandwidth MEMBER bandwidth) Q_PROPERTY(QString bandwidth MEMBER mBandwidth)
Q_PROPERTY(QString lossRate MEMBER mLossRate)
Q_PROPERTY(QString jitterBufferSize MEMBER mJitterBufferSize)
public: public:
QString codec; QString mCodec;
QString bandwidth; QString mBandwidth;
QString mLossRate;
QString mJitterBufferSize;
AudioStats operator=(AudioStats s); AudioStats operator=(AudioStats s);
@ -70,16 +74,18 @@ public:
struct VideoStats { struct VideoStats {
Q_GADGET Q_GADGET
Q_PROPERTY(QString codec MEMBER codec) Q_PROPERTY(QString codec MEMBER mCodec)
Q_PROPERTY(QString bandwidth MEMBER bandwidth) Q_PROPERTY(QString bandwidth MEMBER mBandwidth)
Q_PROPERTY(QString resolution MEMBER resolution) Q_PROPERTY(QString resolution MEMBER mResolution)
Q_PROPERTY(QString fps MEMBER fps) Q_PROPERTY(QString fps MEMBER mFps)
Q_PROPERTY(QString lossRate MEMBER mLossRate)
public: public:
QString codec; QString mCodec;
QString bandwidth; QString mBandwidth;
QString resolution; QString mResolution;
QString fps; QString mFps;
QString mLossRate;
VideoStats operator=(VideoStats s); VideoStats operator=(VideoStats s);
bool operator==(VideoStats s); bool operator==(VideoStats s);

View file

@ -48,8 +48,7 @@ ParticipantDeviceCore::ParticipantDeviceCore(const std::shared_ptr<linphone::Par
mAddress = Utils::coreStringToAppString(deviceAddress->asStringUriOnly()); mAddress = Utils::coreStringToAppString(deviceAddress->asStringUriOnly());
mDisplayName = Utils::coreStringToAppString(deviceAddress->getDisplayName()); mDisplayName = Utils::coreStringToAppString(deviceAddress->getDisplayName());
if (mDisplayName.isEmpty()) { if (mDisplayName.isEmpty()) {
auto name = Utils::getDisplayName(mAddress); mDisplayName = ToolModel::getDisplayName(mAddress);
if (name) mDisplayName = name->getValue().toString();
} }
mIsMuted = device->getIsMuted(); mIsMuted = device->getIsMuted();
mIsMe = isMe; mIsMe = isMe;

View file

@ -36,8 +36,11 @@ AccountModel::AccountModel(const std::shared_ptr<linphone::Account> &account, QO
&AccountModel::onDefaultAccountChanged); &AccountModel::onDefaultAccountChanged);
// Hack because Account doesn't provide callbacks on updated data // Hack because Account doesn't provide callbacks on updated data
connect(this, &AccountModel::defaultAccountChanged, this, connect(this, &AccountModel::defaultAccountChanged, this, [this]() {
[this]() { emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri())); }); emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri()));
emit displayNameChanged(
Utils::coreStringToAppString(mMonitor->getParams()->getIdentityAddress()->getDisplayName()));
});
connect(CoreModel::getInstance().get(), &CoreModel::unreadNotificationsChanged, this, [this]() { connect(CoreModel::getInstance().get(), &CoreModel::unreadNotificationsChanged, this, [this]() {
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/, emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
@ -132,7 +135,10 @@ void AccountModel::setDisplayName(QString displayName) {
address->setDisplayName(Utils::appStringToCoreString(displayName)); address->setDisplayName(Utils::appStringToCoreString(displayName));
params->setIdentityAddress(address); params->setIdentityAddress(address);
mMonitor->setParams(params); mMonitor->setParams(params);
emit displayNameChanged(displayName); // Hack because Account doesn't provide callbacks on updated data
// emit displayNameChanged(displayName);
auto core = CoreModel::getInstance()->getCore();
emit CoreModel::getInstance()->defaultAccountChanged(core, core->getDefaultAccount());
} }
void AccountModel::setDialPlan(int index) { void AccountModel::setDialPlan(int index) {

View file

@ -9,8 +9,7 @@ import SettingsCpp
ColumnLayout{ ColumnLayout{
id: mainItem id: mainItem
property AccountGui account: null property AccountGui account: null
property var displayName: account ? UtilsCpp.getDisplayName(account.core.identityAddress) : "" property string topText: account ? account.core.displayName : ""
property string topText: displayName ? displayName.value : ""
property string bottomText: account ? SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(account.core.identityAddress) : account.core.identityAddress : "" property string bottomText: account ? SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(account.core.identityAddress) : account.core.identityAddress : ""
spacing: 0 spacing: 0
width: topTextItem.implicitWidth width: topTextItem.implicitWidth

View file

@ -1189,7 +1189,7 @@ AbstractWindow {
} }
} }
ColumnLayout { ColumnLayout {
spacing: 7 * DefaultStyle.dp spacing: 8 * DefaultStyle.dp
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Text { Text {
text: mainWindow.call ? mainWindow.call.core.audioStats.codec : "" text: mainWindow.call ? mainWindow.call.core.audioStats.codec : ""
@ -1207,6 +1207,22 @@ AbstractWindow {
weight: 500 * DefaultStyle.dp weight: 500 * DefaultStyle.dp
} }
} }
Text {
text: mainWindow.call ? mainWindow.call.core.audioStats.lossRate : ""
Layout.alignment: Qt.AlignHCenter
font {
pixelSize: 12 * DefaultStyle.dp
weight: 500 * DefaultStyle.dp
}
}
Text {
text: mainWindow.call ? mainWindow.call.core.audioStats.jitterBufferSize : ""
Layout.alignment: Qt.AlignHCenter
font {
pixelSize: 12 * DefaultStyle.dp
weight: 500 * DefaultStyle.dp
}
}
} }
} }
} }
@ -1217,7 +1233,6 @@ AbstractWindow {
topPadding: 13 * DefaultStyle.dp topPadding: 13 * DefaultStyle.dp
bottomPadding: 13 * DefaultStyle.dp bottomPadding: 13 * DefaultStyle.dp
Layout.topMargin: 13 * DefaultStyle.dp
Layout.leftMargin: 16 * DefaultStyle.dp Layout.leftMargin: 16 * DefaultStyle.dp
Layout.rightMargin: 16 * DefaultStyle.dp Layout.rightMargin: 16 * DefaultStyle.dp
@ -1235,7 +1250,7 @@ AbstractWindow {
} }
} }
ColumnLayout { ColumnLayout {
spacing: 7 * DefaultStyle.dp spacing: 8 * DefaultStyle.dp
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Text { Text {
text: mainWindow.call ? mainWindow.call.core.videoStats.codec : "" text: mainWindow.call ? mainWindow.call.core.videoStats.codec : ""
@ -1253,6 +1268,14 @@ AbstractWindow {
weight: 500 * DefaultStyle.dp weight: 500 * DefaultStyle.dp
} }
} }
Text {
text: mainWindow.call ? mainWindow.call.core.videoStats.lossRate : ""
Layout.alignment: Qt.AlignHCenter
font {
pixelSize: 12 * DefaultStyle.dp
weight: 500 * DefaultStyle.dp
}
}
Text { Text {
text: mainWindow.call ? mainWindow.call.core.videoStats.resolution : "" text: mainWindow.call ? mainWindow.call.core.videoStats.resolution : ""
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter