From 7e9dce9c00230a8b627d400e49fd220c63b6e28d Mon Sep 17 00:00:00 2001 From: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> Date: Tue, 25 Oct 2022 11:25:14 -0400 Subject: [PATCH] feature: Add 'advanced information' call overlay Change-Id: Ia54d01ec56e01d0c04e360ec06da87aa37fe74fe GitLab: #510 --- src/app/avadapter.cpp | 11 + src/app/avadapter.h | 2 + src/app/calladapter.cpp | 28 +++ src/app/calladapter.h | 5 + src/app/constant/JamiStrings.qml | 1 + src/app/constant/JamiTheme.qml | 7 + .../components/CallInformationWindow.qml | 213 ++++++++++++++++++ src/app/mainview/components/CallOverlay.qml | 9 + .../components/CallViewContextMenu.qml | 12 + .../mainview/components/OngoingCallPage.qml | 1 + src/app/qml.qrc | 1 + src/libclient/CMakeLists.txt | 2 - src/libclient/api/avmodel.h | 9 + src/libclient/api/callmodel.h | 6 + src/libclient/avmodel.cpp | 25 +- src/libclient/callmodel.cpp | 31 +++ src/libclient/directrenderer.cpp | 19 ++ src/libclient/private/smartInfoHub_p.h | 1 - src/libclient/qtwrapper/conversions_wrap.hpp | 10 + src/libclient/renderer.cpp | 22 ++ src/libclient/renderer.h | 19 ++ src/libclient/shmrenderer.cpp | 7 +- src/libclient/smartinfohub.cpp | 178 --------------- src/libclient/smartinfohub.h | 65 ------ 24 files changed, 432 insertions(+), 252 deletions(-) create mode 100644 src/app/mainview/components/CallInformationWindow.qml delete mode 100644 src/libclient/smartinfohub.cpp delete mode 100644 src/libclient/smartinfohub.h diff --git a/src/app/avadapter.cpp b/src/app/avadapter.cpp index f3fe0ed57..9c68deb19 100644 --- a/src/app/avadapter.cpp +++ b/src/app/avadapter.cpp @@ -46,6 +46,10 @@ AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent) &lrc::api::AVModel::rendererStarted, this, &AvAdapter::onRendererStarted); + connect(&lrcInstance_->avModel(), + &lrc::api::AVModel::onRendererInfosUpdated, + this, + &AvAdapter::setRenderersInfoList); } // The top left corner of primary screen is (0, 0). @@ -415,8 +419,15 @@ AvAdapter::getHardwareAcceleration() { return lrcInstance_->avModel().getHardwareAcceleration(); } + void AvAdapter::setHardwareAcceleration(bool accelerate) { lrcInstance_->avModel().setHardwareAcceleration(accelerate); } + +void +AvAdapter::setRenderersInfoList(QVariantList renderersInfo) +{ + set_renderersInfoList(renderersInfo); +} diff --git a/src/app/avadapter.h b/src/app/avadapter.h index f565ce59a..2f115cf8a 100644 --- a/src/app/avadapter.h +++ b/src/app/avadapter.h @@ -36,6 +36,7 @@ class AvAdapter final : public QmlAdapterBase QML_PROPERTY(bool, muteCamera) QML_RO_PROPERTY(QStringList, windowsNames) QML_RO_PROPERTY(QList<QVariant>, windowsIds) + QML_RO_PROPERTY(QVariantList, renderersInfoList) public: explicit AvAdapter(LRCInstance* instance, QObject* parent = nullptr); @@ -107,6 +108,7 @@ protected: Q_INVOKABLE void setHardwareAcceleration(bool accelerate); private Q_SLOTS: + void setRenderersInfoList(QVariantList renderersInfo); void onAudioDeviceEvent(); void onRendererStarted(const QString& id, const QSize& size); diff --git a/src/app/calladapter.cpp b/src/app/calladapter.cpp index d266673f5..25c473c58 100644 --- a/src/app/calladapter.cpp +++ b/src/app/calladapter.cpp @@ -41,6 +41,9 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* : QmlAdapterBase(instance, parent) , systemTray_(systemTray) { + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation); + participantsModel_.reset(new CallParticipantsModel(lrcInstance_, this)); QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, participantsModel_.get(), "CallParticipantsModel"); @@ -95,6 +98,19 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* &CallAdapter::saveConferenceSubcalls); } +void +CallAdapter::startTimerInformation() +{ + updateAdvancedInformation(); + timer->start(1000); +} + +void +CallAdapter::stopTimerInformation() +{ + timer->stop(); +} + void CallAdapter::onAccountChanged() { @@ -1147,6 +1163,18 @@ CallAdapter::getCallDurationTime(const QString& accountId, const QString& convUi return QString(); } +void +CallAdapter::updateAdvancedInformation() +{ + try { + auto& callModel = lrcInstance_->accountModel().getAccountInfo(accountId_).callModel; + if (callModel) + set_callInformation(QVariantList::fromList(callModel->getAdvancedInformation())); + } catch (const std::exception& e) { + qWarning() << e.what(); + } +} + void CallAdapter::preventScreenSaver(bool state) { diff --git a/src/app/calladapter.h b/src/app/calladapter.h index 0e18614b5..88e375cb1 100644 --- a/src/app/calladapter.h +++ b/src/app/calladapter.h @@ -37,8 +37,10 @@ class CallAdapter final : public QmlAdapterBase { Q_OBJECT QML_PROPERTY(bool, hasCall) + QML_RO_PROPERTY(QVariantList, callInformation) public: + QTimer* timer; enum MuteStates { UNMUTED, LOCAL_MUTED, MODERATOR_MUTED, BOTH_MUTED }; Q_ENUM(MuteStates) @@ -49,6 +51,8 @@ protected: void safeInit() override {}; public: + Q_INVOKABLE void startTimerInformation(); + Q_INVOKABLE void stopTimerInformation(); Q_INVOKABLE void placeAudioOnlyCall(); Q_INVOKABLE void placeCall(); Q_INVOKABLE void hangUpACall(const QString& accountId, const QString& convUid); @@ -88,6 +92,7 @@ public: const QString& accountId = {}, bool forceCallOnly = false); Q_INVOKABLE QString getCallDurationTime(const QString& accountId, const QString& convUid); + Q_INVOKABLE void updateAdvancedInformation(); Q_SIGNALS: void callStatusChanged(int index, const QString& accountId, const QString& convUid); diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml index 7ab85e0cd..df70ac49c 100644 --- a/src/app/constant/JamiStrings.qml +++ b/src/app/constant/JamiStrings.qml @@ -291,6 +291,7 @@ Item { property string shareFile: qsTr("Share file") property string selectShareMethod: qsTr("Select sharing method") property string viewPlugin: qsTr("View plugin") + property string advancedInformation: qsTr("Advanced information") property string noVideoDevice: qsTr("No video device") property string notAvailable: qsTr("Unavailable") property string lowerHand: qsTr("Lower hand") diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index f80e128f9..994eb68c4 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -344,6 +344,13 @@ Item { property real swarmDetailsPageDocumentsPaperClipSize: 24 property real swarmDetailsPageDocumentsMediaSize: 175 + //Call information + property real textFontPointSize: calcSize(10) + property real titleFontPointSize: calcSize(13) + property color callInfoColor: chatviewTextColor + property int callInformationElementsSpacing: 5 + property int callInformationBlockSpacing: 25 + // Jami switch property real switchIndicatorRadius: 30 property real switchPreferredHeight: 25 diff --git a/src/app/mainview/components/CallInformationWindow.qml b/src/app/mainview/components/CallInformationWindow.qml new file mode 100644 index 000000000..533434950 --- /dev/null +++ b/src/app/mainview/components/CallInformationWindow.qml @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> + * + * 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 <https://www.gnu.org/licenses/>. + */ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 +import Qt5Compat.GraphicalEffects + +import "../../commoncomponents" + +Window { + id: root + + width: parent.width * 2 / 3 + height: parent.height * 2 / 3 + property var advancedList + property var fps + + onClosing: { + CallAdapter.stopTimerInformation() + } + + Rectangle { + id: container + + anchors.fill: parent + color: JamiTheme.secondaryBackgroundColor + + RowLayout { + id: windowContent + + anchors.fill: parent + + ColumnLayout { + spacing: JamiTheme.callInformationBlockSpacing + + Text{ + color: JamiTheme.callInfoColor + text: "Call information" + font.pointSize: JamiTheme.titleFontPointSize + } + + Item { + id: itemCallInformation + + Layout.fillHeight: true + Layout.fillWidth: true + clip: true + + ListView { + model: advancedList + width: parent.width + height: root.height + spacing: JamiTheme.callInformationBlockSpacing + + delegate: Column { + spacing: JamiTheme.callInformationElementsSpacing + + Text { + color: JamiTheme.callInfoColor + text: "Call id: " + modelData.CALL_ID + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Video codec: " + modelData.VIDEO_CODEC + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Audio codec: " + modelData.AUDIO_CODEC + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + function stringWithoutRing(peerNumber){ + return peerNumber.replace("@ring.dht","") ; + } + color: JamiTheme.callInfoColor + text: "PEER_NUMBER: " + stringWithoutRing(modelData.PEER_NUMBER) + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Hardware acceleration: " + modelData.HARDWARE_ACCELERATION + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Video min bitrate: " + modelData.VIDEO_MIN_BITRATE + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Video max bitrate: " + modelData.VIDEO_MAX_BITRATE + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Video bitrate: " + modelData.VIDEO_BITRATE + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Sockets: " + modelData.SOCKETS + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemCallInformation.width + } + + } + } + } + } + + ColumnLayout { + spacing: JamiTheme.callInformationBlockSpacing + + Text { + color: JamiTheme.callInfoColor + text: "Renderers information" + font.pointSize: JamiTheme.titleFontPointSize + } + + Item { + id: itemParticipantInformation + + Layout.fillHeight: true + Layout.fillWidth: true + clip: true + + + ListView { + width: parent.width + height: root.height + spacing: JamiTheme.callInformationBlockSpacing + model: fps + + delegate: Column { + spacing: JamiTheme.callInformationElementsSpacing + + Text{ + color: JamiTheme.callInfoColor + text: "Renderer id: " + modelData.ID + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemParticipantInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Fps: " + modelData.FPS + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemParticipantInformation.width + } + + Text { + color: JamiTheme.callInfoColor + text: "Resolution: " + modelData.RES + font.pointSize: JamiTheme.textFontPointSize + wrapMode: Text.WrapAnywhere + width: itemParticipantInformation.width + } + + } + } + } + } + } + } +} diff --git a/src/app/mainview/components/CallOverlay.qml b/src/app/mainview/components/CallOverlay.qml index 86f6b50d1..87f8f2e79 100644 --- a/src/app/mainview/components/CallOverlay.qml +++ b/src/app/mainview/components/CallOverlay.qml @@ -83,6 +83,7 @@ Item { SelectScreenWindowCreation.destroySelectScreenWindow() ScreenRubberBandCreation.destroyScreenRubberBandWindow() PluginHandlerPickerCreation.closePluginHandlerPicker() + callInformationWindow.close() } // x, y position does not need to be translated @@ -123,6 +124,14 @@ Item { y: root.height / 2 - sipInputPanel.height / 2 } + CallInformationWindow { + id: callInformationWindow + + visible: false + advancedList: CallAdapter.callInformation + fps: AvAdapter.renderersInfoList + } + JamiFileDialog { id: jamiFileDialog diff --git a/src/app/mainview/components/CallViewContextMenu.qml b/src/app/mainview/components/CallViewContextMenu.qml index 8e607242a..1b8e86c42 100644 --- a/src/app/mainview/components/CallViewContextMenu.qml +++ b/src/app/mainview/components/CallViewContextMenu.qml @@ -176,6 +176,18 @@ ContextMenuAutoLoader { onClicked: { root.pluginItemClicked() } + }, + GeneralMenuItem { + id: advancedInformation + + canTrigger: true + itemName: JamiStrings.advancedInformation + iconSource: JamiResources.settings_24dp_svg + + onClicked: { + CallAdapter.startTimerInformation(); + callInformationWindow.show() + } } ] diff --git a/src/app/mainview/components/OngoingCallPage.qml b/src/app/mainview/components/OngoingCallPage.qml index 5917cfa9e..93e0b2434 100644 --- a/src/app/mainview/components/OngoingCallPage.qml +++ b/src/app/mainview/components/OngoingCallPage.qml @@ -151,6 +151,7 @@ Rectangle { Rectangle { id: callPageMainRect + SplitView.preferredHeight: mainColumnLayout.isHorizontal ? root.height : (root.height / 3) * 2 SplitView.preferredWidth: mainColumnLayout.isHorizontal ? (root.width / 3) * 2 : root.width SplitView.minimumHeight: root.height / 2 + 20 diff --git a/src/app/qml.qrc b/src/app/qml.qrc index 8f558284d..fd4cdc7d7 100644 --- a/src/app/qml.qrc +++ b/src/app/qml.qrc @@ -212,5 +212,6 @@ <file>mainview/components/DocumentsScrollview.qml</file> <file>mainview/components/FilePreview.qml</file> <file>mainview/components/MediaPreview.qml</file> + <file>mainview/components/CallInformationWindow.qml</file> </qresource> </RCC> diff --git a/src/libclient/CMakeLists.txt b/src/libclient/CMakeLists.txt index 2676c9c4c..99780f5fa 100644 --- a/src/libclient/CMakeLists.txt +++ b/src/libclient/CMakeLists.txt @@ -278,7 +278,6 @@ set(LIBCLIENT_SOURCES avmodel.cpp pluginmodel.cpp namedirectory.cpp - smartinfohub.cpp renderer.cpp) set(LIBCLIENT_HEADERS @@ -286,7 +285,6 @@ set(LIBCLIENT_HEADERS globalinstances.h pixmapmanipulatordefault.h dbuserrorhandlerdefault.h - smartinfohub.h vcard.h namedirectory.h messagelistmodel.h diff --git a/src/libclient/api/avmodel.h b/src/libclient/api/avmodel.h index d0ab442e2..1e0a782f7 100644 --- a/src/libclient/api/avmodel.h +++ b/src/libclient/api/avmodel.h @@ -276,8 +276,17 @@ public: QSize getRendererSize(const QString& id); video::Frame getRendererFrame(const QString& id); bool useDirectRenderer() const; + /** + * Update renderers information list + */ + Q_SLOT void updateRenderersInfo(); Q_SIGNALS: + /** + * Emitted after an update of renderers information + * @param renderersInfoList Information on all renderers (RES, ID, FPS) + */ + void onRendererInfosUpdated(QVariantList renderersInfoList); /** * Emitted when a renderer is started * @param id of the renderer diff --git a/src/libclient/api/callmodel.h b/src/libclient/api/callmodel.h index 4b152bf3d..e635617e5 100644 --- a/src/libclient/api/callmodel.h +++ b/src/libclient/api/callmodel.h @@ -391,6 +391,12 @@ public: QString getDisplay(const QString& windowId); void emplaceConversationConference(const QString& callId); + + /** + * Get advanced information from every current call + */ + QList<QVariant> getAdvancedInformation() const; + Q_SIGNALS: /** diff --git a/src/libclient/avmodel.cpp b/src/libclient/avmodel.cpp index 2f1e934d8..67ade3482 100644 --- a/src/libclient/avmodel.cpp +++ b/src/libclient/avmodel.cpp @@ -168,6 +168,23 @@ AVModel::~AVModel() } } +void +AVModel::updateRenderersInfo() +{ + QVariantList renderersInfoList; + + for (auto r = pimpl_->renderers_.begin(); r != pimpl_->renderers_.end(); r++) { + QVariantMap qmap; + auto& rend = r->second; + MapStringString mapInfo = rend->getInfos(); + qmap.insert(rend->RES, mapInfo["RES"]); + qmap.insert(rend->ID, mapInfo["ID"]); + qmap.insert(rend->FPS, mapInfo["FPS"]); + renderersInfoList.append(qmap); + } + Q_EMIT onRendererInfosUpdated(renderersInfoList); +} + bool AVModel::getDecodingAccelerated() const { @@ -197,7 +214,7 @@ AVModel::setEncodingAccelerated(bool accelerate) bool AVModel::getHardwareAcceleration() const { - bool result = getDecodingAccelerated() & getEncodingAccelerated(); + bool result = getDecodingAccelerated() && getEncodingAccelerated(); return result; } void @@ -825,6 +842,12 @@ void AVModelPimpl::addRenderer(const QString& id, const QSize& res, const QString& shmPath) { auto connectRenderer = [this](Renderer* renderer, const QString& id) { + connect( + renderer, + &Renderer::fpsChanged, + this, + [this, id](void) { Q_EMIT linked_.updateRenderersInfo(); }, + Qt::DirectConnection); connect( renderer, &Renderer::started, diff --git a/src/libclient/callmodel.cpp b/src/libclient/callmodel.cpp index 5f1e4b117..e5fe8c8a2 100644 --- a/src/libclient/callmodel.cpp +++ b/src/libclient/callmodel.cpp @@ -55,8 +55,12 @@ using namespace libjami::Media; +constexpr static const char HARDWARE_ACCELERATION[] = "HARDWARE_ACCELERATION"; +constexpr static const char CALL_ID[] = "CALL_ID"; + static std::uniform_int_distribution<int> dis {0, std::numeric_limits<int>::max()}; static const std::map<short, QString> + sip_call_status_code_map {{0, QObject::tr("Null")}, {100, QObject::tr("Trying")}, {180, QObject::tr("Ringing")}, @@ -128,6 +132,8 @@ public: const BehaviorController& behaviorController); ~CallModelPimpl(); + QVariantList callAdvancedInformation(); + /** * Send the profile VCard into a call * @param callId @@ -397,6 +403,12 @@ CallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringStrin return callId; } +QList<QVariant> +CallModel::getAdvancedInformation() const +{ + return pimpl_->callAdvancedInformation(); +} + void CallModel::muteMedia(const QString& callId, const QString& label, bool mute) { @@ -950,6 +962,25 @@ CallModelPimpl::CallModelPimpl(const CallModel& linked, CallModelPimpl::~CallModelPimpl() {} +QVariantList +CallModelPimpl::callAdvancedInformation() +{ + QVariantList advancedInformationList; + + QStringList callList = CallManager::instance().getCallList(linked.owner.id); + for (const auto& callId : callList) { + MapStringString mapStringDetailsList = CallManager::instance() + .getCallDetails(linked.owner.id, callId); + QVariantMap detailsList = mapStringStringToQVariantMap(mapStringDetailsList); + + detailsList.insert(CALL_ID, callId); + detailsList.insert(HARDWARE_ACCELERATION, lrc.getAVModel().getHardwareAcceleration()); + advancedInformationList.append(detailsList); + } + + return advancedInformationList; +} + void CallModelPimpl::initCallFromDaemon() { diff --git a/src/libclient/directrenderer.cpp b/src/libclient/directrenderer.cpp index a6a292e5f..47df29f2a 100644 --- a/src/libclient/directrenderer.cpp +++ b/src/libclient/directrenderer.cpp @@ -33,10 +33,19 @@ using namespace lrc::api::video; struct DirectRenderer::Impl : public QObject { Q_OBJECT +private: + int fpsC; + int fps; + public: + std::chrono::time_point<std::chrono::system_clock> lastFrameDebug; + Impl(DirectRenderer* parent) : QObject(nullptr) , parent_(parent) + , fpsC(0) + , fps(0) + , lastFrameDebug(std::chrono::system_clock::now()) { configureTarget(); if (!VideoManager::instance().registerSinkTarget(parent_->id(), target)) @@ -81,6 +90,16 @@ public: QMutexLocker lk(&mutex); frameBufferPtr = std::move(buf); } + // compute FPS + ++fpsC; + auto currentTime = std::chrono::system_clock::now(); + const std::chrono::duration<double> seconds = currentTime - lastFrameDebug; + if (seconds.count() >= FPS_RATE_SEC) { + fps = static_cast<int>(fpsC / seconds.count()); + fpsC = 0; + lastFrameDebug = currentTime; + parent_->setFPS(fps); + } Q_EMIT parent_->frameUpdated(); }; diff --git a/src/libclient/private/smartInfoHub_p.h b/src/libclient/private/smartInfoHub_p.h index 83b90c5b1..8dd19065e 100644 --- a/src/libclient/private/smartInfoHub_p.h +++ b/src/libclient/private/smartInfoHub_p.h @@ -18,7 +18,6 @@ /* widget_p.h (_p means private) */ #include <QObject> -#include "../smartinfohub.h" #include "typedefs.h" #pragma once diff --git a/src/libclient/qtwrapper/conversions_wrap.hpp b/src/libclient/qtwrapper/conversions_wrap.hpp index cf20d60d1..7389dc596 100644 --- a/src/libclient/qtwrapper/conversions_wrap.hpp +++ b/src/libclient/qtwrapper/conversions_wrap.hpp @@ -43,6 +43,16 @@ #define LOG_LIBJAMI_SIGNAL4(name, arg, arg2, arg3, arg4) #endif +inline QVariantMap +mapStringStringToQVariantMap(const MapStringString& map) +{ + QVariantMap convertedMap; + for (auto i = map.begin(); i != map.end(); i++) { + convertedMap.insert(i.key(), i.value()); + } + return convertedMap; +} + inline MapStringString convertMap(const std::map<std::string, std::string>& m) { diff --git a/src/libclient/renderer.cpp b/src/libclient/renderer.cpp index 22f6fea4a..e79ceb51f 100644 --- a/src/libclient/renderer.cpp +++ b/src/libclient/renderer.cpp @@ -34,6 +34,12 @@ Renderer::Renderer(const QString& id, const QSize& res) Renderer::~Renderer() {} +int +Renderer::fps() const +{ + return fps_; +} + QString Renderer::id() const { @@ -45,6 +51,22 @@ Renderer::size() const { return size_; } +void +Renderer::setFPS(int fps) +{ + fps_ = fps; + Q_EMIT fpsChanged(); +} + +MapStringString +Renderer::getInfos() const +{ + MapStringString map; + map[ID] = id(); + map[FPS] = QString::number(fps()); + map[RES] = QString::number(size().width()) + " * " + QString::number(size().height()); + return map; +} } // namespace video } // namespace lrc diff --git a/src/libclient/renderer.h b/src/libclient/renderer.h index df7419768..f850e2f77 100644 --- a/src/libclient/renderer.h +++ b/src/libclient/renderer.h @@ -36,9 +36,19 @@ class Renderer : public QObject { Q_OBJECT public: + constexpr static const char ID[] = "ID"; + constexpr static const char FPS[] = "FPS"; + constexpr static const char RES[] = "RES"; + constexpr static const int FPS_RATE_SEC = 1; + Renderer(const QString& id, const QSize& res); virtual ~Renderer(); + /** + * @return renderer's fps + */ + int fps() const; + /** * @return renderer's id */ @@ -54,6 +64,13 @@ public: */ virtual lrc::api::video::Frame currentFrame() const = 0; + /** + * set fps + */ + void setFPS(int fps); + + MapStringString getInfos() const; + public Q_SLOTS: virtual void startRendering() = 0; virtual void stopRendering() = 0; @@ -63,10 +80,12 @@ Q_SIGNALS: void stopped(); void started(const QSize& size); void frameBufferRequested(AVFrame* avFrame); + void fpsChanged(); private: QString id_; QSize size_; + int fps_; }; } // namespace video diff --git a/src/libclient/shmrenderer.cpp b/src/libclient/shmrenderer.cpp index 0a2f9b892..3a0ca6424 100644 --- a/src/libclient/shmrenderer.cpp +++ b/src/libclient/shmrenderer.cpp @@ -90,10 +90,7 @@ public: , fpsC(0) , fps(0) , timer(new QTimer(this)) -#ifdef DEBUG_FPS - , frameCount(0) , lastFrameDebug(std::chrono::system_clock::now()) -#endif { timer->setInterval(33); connect(timer, &QTimer::timeout, [this]() { Q_EMIT parent_->frameUpdated(); }); @@ -110,7 +107,6 @@ public: } // Constants - constexpr static const int FPS_RATE_SEC = 1; constexpr static const int FRAME_CHECK_RATE_HZ = 120; // Lock the memory while the copy is being made @@ -172,9 +168,10 @@ public: auto currentTime = std::chrono::system_clock::now(); const std::chrono::duration<double> seconds = currentTime - lastFrameDebug; if (seconds.count() >= FPS_RATE_SEC) { - fps = (int) (fpsC / seconds.count()); + fps = static_cast<int>(fpsC / seconds.count()); fpsC = 0; lastFrameDebug = currentTime; + parent_->setFPS(fps); #ifdef DEBUG_FPS qDebug() << this << ": FPS " << fps; #endif diff --git a/src/libclient/smartinfohub.cpp b/src/libclient/smartinfohub.cpp deleted file mode 100644 index dd9d11ba9..000000000 --- a/src/libclient/smartinfohub.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * - * Author: Olivier Grégoire <olivier.gregoire@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 "smartinfohub.h" -#include "private/smartInfoHub_p.h" - -#include <dbus/videomanager.h> -#include <dbus/callmanager.h> -#include <dbus/callmanager.h> - -SmartInfoHub::SmartInfoHub() -{ - d_ptr = new SmartInfoHubPrivate; - connect(&CallManager::instance(), - &CallManagerInterface::SmartInfo, - this, - &SmartInfoHub::slotSmartInfo, - Qt::QueuedConnection); -} - -SmartInfoHub::~SmartInfoHub() {} - -void -SmartInfoHub::start() -{ - CallManager::instance().startSmartInfo(d_ptr->m_refreshTimeInformationMS); -} - -void -SmartInfoHub::stop() -{ - CallManager::instance().stopSmartInfo(); -} - -SmartInfoHub& -SmartInfoHub::instance() -{ - // Singleton - static SmartInfoHub instance_; - return instance_; -} - -void -SmartInfoHub::setRefreshTime(uint32_t timeMS) -{ - d_ptr->m_refreshTimeInformationMS = timeMS; -} - -// Retrieve information from the map and implement all the variables -void -SmartInfoHub::slotSmartInfo(const MapStringString& map) -{ - for (int i = 0; i < map.size(); i++) - d_ptr->m_information[map.keys().at(i)] = map[map.keys().at(i)]; - - Q_EMIT changed(); -} -// Getter - -bool -SmartInfoHub::isConference() const -{ - return (d_ptr->m_information["type"] == "conference"); -} - -float -SmartInfoHub::localFps() const -{ - if (!d_ptr->m_information[LOCAL_FPS].isEmpty()) - return d_ptr->m_information[LOCAL_FPS].toFloat(); - - return 0.0; -} - -float -SmartInfoHub::remoteFps() const -{ - if (!d_ptr->m_information[REMOTE_FPS].isEmpty()) - return d_ptr->m_information[REMOTE_FPS].toFloat(); - - return 0.0; -} - -int -SmartInfoHub::remoteWidth() const -{ - if (!d_ptr->m_information[REMOTE_WIDTH].isEmpty()) - return d_ptr->m_information[REMOTE_WIDTH].toInt(); - else - return 0; -} - -int -SmartInfoHub::remoteHeight() const -{ - if (!d_ptr->m_information[REMOTE_HEIGHT].isEmpty()) - return d_ptr->m_information[REMOTE_HEIGHT].toInt(); - else - return 0; -} - -int -SmartInfoHub::localWidth() const -{ - if (!d_ptr->m_information[LOCAL_WIDTH].isEmpty()) - return d_ptr->m_information[LOCAL_WIDTH].toInt(); - else - return 0; -} - -int -SmartInfoHub::localHeight() const -{ - if (!d_ptr->m_information[LOCAL_HEIGHT].isEmpty()) - return d_ptr->m_information[LOCAL_HEIGHT].toInt(); - else - return 0; -} - -QString -SmartInfoHub::callID() const -{ - if (!d_ptr->m_information[CALL_ID].isEmpty()) - return d_ptr->m_information[CALL_ID]; - else - return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; -} - -QString -SmartInfoHub::localVideoCodec() const -{ - if (!d_ptr->m_information[LOCAL_VIDEO_CODEC].isEmpty()) - return d_ptr->m_information[LOCAL_VIDEO_CODEC]; - else - return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; -} - -QString -SmartInfoHub::localAudioCodec() const -{ - if (!d_ptr->m_information[LOCAL_AUDIO_CODEC].isEmpty()) - return d_ptr->m_information[LOCAL_AUDIO_CODEC]; - else - return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; -} - -QString -SmartInfoHub::remoteVideoCodec() const -{ - if (!d_ptr->m_information[REMOTE_VIDEO_CODEC].isEmpty()) - return d_ptr->m_information[REMOTE_VIDEO_CODEC]; - else - return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; -} - -QString -SmartInfoHub::remoteAudioCodec() const -{ - if (!d_ptr->m_information[REMOTE_AUDIO_CODEC].isEmpty()) - return d_ptr->m_information[REMOTE_AUDIO_CODEC]; - else - return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; -} diff --git a/src/libclient/smartinfohub.h b/src/libclient/smartinfohub.h deleted file mode 100644 index 42b84e028..000000000 --- a/src/libclient/smartinfohub.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * - * Author: Olivier Grégoire <olivier.gregoire@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/>. * - ***************************************************************************/ - -#pragma once - -#include <QObject> -#include "typedefs.h" - -class SmartInfoHubPrivate; - -class SmartInfoHub final : public QObject -{ - Q_OBJECT -public: - // Singleton - static SmartInfoHub& instance(); - - void start(); - void stop(); - - void setRefreshTime(uint32_t timeMS); - - // Getter - float localFps() const; - float remoteFps() const; - int remoteWidth() const; - int remoteHeight() const; - int localWidth() const; - int localHeight() const; - QString callID() const; - QString localVideoCodec() const; - QString localAudioCodec() const; - QString remoteVideoCodec() const; - QString remoteAudioCodec() const; - bool isConference() const; - -Q_SIGNALS: - /// Emitted when informations have changed - void changed(); - -private Q_SLOTS: - void slotSmartInfo(const MapStringString& info); - -private: - // use to initialise the connection between the Qsignal and the lambda function - SmartInfoHub(); - virtual ~SmartInfoHub(); - - SmartInfoHubPrivate* d_ptr; -}; -- GitLab