diff --git a/src/app/avadapter.cpp b/src/app/avadapter.cpp index f3fe0ed579cc38da68b8f1d5626e0fb0b180f97d..9c68deb193f772b21bdb8212504851f5e1ddae84 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 f565ce59ac82a1669cd24efc03355f39bd33b138..2f115cf8a7b78789961ce2dde2720b8a916cbba0 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 d266673f5f5cf4eaddf71fa86fb2b8743b13e897..25c473c58b90eb4a5f7ebfe17247daeda7f4bc1d 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 0e18614b5f531c30a292fcdd9a8a8ec8ddfcbba3..88e375cb14d0839218f3be37b92b687adc61f484 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 7ab85e0cd67421da3cc520a4ec59139563e3224a..df70ac49c0d0645da1d0d1904f9bfc308ca7a67d 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 f80e128f9f274fbbb9b983e063751093f1642495..994eb68c4a0c7d5644375a033d232f847df0ea86 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 0000000000000000000000000000000000000000..53343495064f8f83b579058afa6fd604f5d607b5 --- /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 86f6b50d17288ce8efb738456baf6aff9ef142b7..87f8f2e79957115d92f92d2211e07c94c8469cef 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 8e607242aaf9e0cde3f228629e68c8ff4414b6c1..1b8e86c42ccb6c5f0890aab2cfc938c65fec1d3d 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 5917cfa9ebcc70e4823e86efb0d5d2ed31bc18c3..93e0b2434646bf048705b3a1fe233d824018e65c 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 8f558284d5d9c27f0067af982a9419e6234f2d7f..fd4cdc7d7c205bc965b2129ce9bfb8bb3efcb422 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 2676c9c4ce2d8adbf5aaef4db4f21b425b3b383f..99780f5fa59ae00cf2b8f725d62e09315f8f0cef 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 d0ab442e237854d1fe7bced91858750147e497d5..1e0a782f7648ed8e960115102483665c164364b8 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 4b152bf3d943b7264b4b21bad1334035b5aeefa6..e635617e56542f9584af447227c0894779d4ec2d 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 2f1e934d818d73c4b8acc6f8e2a1bc39365d7dfd..67ade3482b61a6ee1a6bb652643c87fc83c24db7 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 5f1e4b11747383a508ba443a044ecb20da77a829..e5fe8c8a2ca88f3f0ceaf84d698f44870703c858 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 a6a292e5f7b5e2bde2bfdbb7a97ed6ece7ac4c52..47df29f2a9cfe5289addaf189db6fa1bf4a48cea 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 83b90c5b1cbb216e6fb7f1f06d7e8488ce896203..8dd19065eceb35ba6f47960a479cc83f91b3910a 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 cf20d60d181df227307a3cdcb739896faad85e9b..7389dc59691468b05ab3dc1cc9d94d0f306f16fb 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 22f6fea4a7275d5a4a3f68cee8ea4aad3dcb2847..e79ceb51fa4aca995ef2c370997968bfa3a8bfc6 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 df7419768058750f58d99189d5229a126ba04229..f850e2f770b1cad43ac8fbd72f8d2421ef33af99 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 0a2f9b8922c961186b6481a5f4669aa071c8f12b..3a0ca642403cd6b54e8deddd1a3a437b427f99eb 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 dd9d11ba9a6bc697a4f43023436725cac24396af..0000000000000000000000000000000000000000 --- 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 42b84e0281220bc0c70f6c52f68d97bc1fc5f52d..0000000000000000000000000000000000000000 --- 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; -};