QmlName for Gui objects.

Debug message format.
Preview updates on Call state.
This commit is contained in:
Julien Wadel 2024-04-03 15:51:17 +02:00
parent fd09a79957
commit 19840b30f3
17 changed files with 133 additions and 81 deletions

View file

@ -31,8 +31,10 @@
#include "core/call/CallGui.hpp"
#include "core/participant/ParticipantDeviceCore.hpp"
#include "core/participant/ParticipantDeviceGui.hpp"
#include "tool/Utils.hpp"
DEFINE_ABSTRACT_OBJECT(CameraGui)
DEFINE_GUI_OBJECT(CameraGui)
// =============================================================================
CameraGui::CameraGui(QQuickItem *parent) : QQuickFramebufferObject(parent) {
@ -56,16 +58,17 @@ CameraGui::~CameraGui() {
QQuickFramebufferObject::Renderer *CameraGui::createRenderer() const {
auto renderer = createRenderer(false);
if (!renderer) {
qInfo() << log().arg("(%1) Setting Camera to Dummy, %2").arg(mQmlName).arg(getSourceLocation());
lInfo() << log().arg("(%1) Setting Camera to Dummy, %2").arg(mQmlName).arg(getSourceLocation());
QTimer::singleShot(1, this, &CameraGui::isNotReady);
renderer = new CameraDummy(); // Used to fill a renderer to avoid pushing a NULL.
QTimer::singleShot(1000, this, &CameraGui::requestNewRenderer);
if (getSourceLocation() != CorePreview) QTimer::singleShot(1000, this, &CameraGui::requestNewRenderer);
} else QTimer::singleShot(1, this, &CameraGui::isReady); // Hack because of constness of createRenderer()
return renderer;
}
QQuickFramebufferObject::Renderer *CameraGui::createRenderer(bool resetWindowId) const {
QQuickFramebufferObject::Renderer *renderer = NULL;
lDebug() << log().arg("CreateRenderer. Reset=") << resetWindowId;
// A renderer is mandatory, we cannot wait async.
switch (getSourceLocation()) {
case CorePreview: {
@ -76,7 +79,7 @@ QQuickFramebufferObject::Renderer *CameraGui::createRenderer(bool resetWindowId)
auto f = [qmlName = mQmlName, callGui = mCallGui, &renderer, resetWindowId]() {
auto call = callGui->getCore()->getModel()->getMonitor();
if (call) {
qInfo() << "[Camera] (" << qmlName << ") " << (resetWindowId ? "Resetting" : "Setting")
lInfo() << "[Camera] (" << qmlName << ") " << (resetWindowId ? "Resetting" : "Setting")
<< " Camera to CallModel";
if (resetWindowId) {
renderer = (QQuickFramebufferObject::Renderer *)call->getNativeVideoWindowId();
@ -87,15 +90,13 @@ QQuickFramebufferObject::Renderer *CameraGui::createRenderer(bool resetWindowId)
}
}
};
if (mIsDeleting) {
App::postModelBlock(f);
} else App::postModelSync(f);
App::postModelBlock(f);
} break;
case Device: {
auto f = [qmlName = mQmlName, participantDeviceGui = mParticipantDeviceGui, &renderer, resetWindowId]() {
auto device = participantDeviceGui->getCore()->getModel()->getMonitor();
if (device) {
qInfo() << "[Camera] (" << qmlName << ") " << (resetWindowId ? "Resetting" : "Setting")
lInfo() << "[Camera] (" << qmlName << ") " << (resetWindowId ? "Resetting" : "Setting")
<< " Camera to ParticipantDeviceModel";
if (resetWindowId) {
} else {
@ -104,9 +105,7 @@ QQuickFramebufferObject::Renderer *CameraGui::createRenderer(bool resetWindowId)
}
}
};
if (mIsDeleting) {
App::postModelBlock(f);
} else App::postModelSync(f);
App::postModelBlock(f);
} break;
default: {
}
@ -129,22 +128,12 @@ void CameraGui::checkVideoDefinition() { /*
}*/
}
QString CameraGui::getQmlName() const {
return mQmlName;
}
void CameraGui::setQmlName(const QString &name) {
if (name != mQmlName) {
mQmlName = name;
emit qmlNameChanged();
}
}
bool CameraGui::getIsReady() const {
return mIsReady;
}
void CameraGui::setIsReady(bool isReady) {
if (mIsReady != isReady) {
lDebug() << log().arg("Set IsReady") << isReady;
mIsReady = isReady;
emit isReadyChanged(mIsReady);
}
@ -175,8 +164,10 @@ CallGui *CameraGui::getCallGui() const {
void CameraGui::setCallGui(CallGui *callGui) {
if (mCallGui != callGui) {
if (mCallGui) disconnect(mCallGui->getCore(), &CallCore::stateChanged, this, &CameraGui::callStateChanged);
mCallGui = callGui;
qDebug() << "Set Call " << mCallGui;
if (mCallGui) connect(mCallGui->getCore(), &CallCore::stateChanged, this, &CameraGui::callStateChanged);
lDebug() << log().arg("Set Call") << mCallGui;
emit callGuiChanged(mCallGui);
updateWindowIdLocation();
}
@ -189,7 +180,7 @@ ParticipantDeviceGui *CameraGui::getParticipantDeviceGui() const {
void CameraGui::setParticipantDeviceGui(ParticipantDeviceGui *deviceGui) {
if (mParticipantDeviceGui != deviceGui) {
mParticipantDeviceGui = deviceGui;
qDebug() << log().arg("Set Device %1").arg((quint64)mParticipantDeviceGui);
lDebug() << log().arg("Set Device") << mParticipantDeviceGui;
// setIsPreview(mParticipantDeviceGui->getCore()->isLocal());
emit participantDeviceGuiChanged(mParticipantDeviceGui);
updateWindowIdLocation();
@ -202,13 +193,9 @@ CameraGui::WindowIdLocation CameraGui::getSourceLocation() const {
void CameraGui::setWindowIdLocation(const WindowIdLocation &location) {
if (mWindowIdLocation != location) {
qDebug() << log()
.arg("( %1 ) Update Window Id location from %2 to %3")
.arg(mQmlName)
.arg(mWindowIdLocation)
.arg(location);
lDebug() << log().arg("Update Window Id location from %2 to %3").arg(mWindowIdLocation).arg(location);
if (mWindowIdLocation == CorePreview) PreviewManager::getInstance()->unsubscribe(this);
resetWindowId(); // Location change: Reset old window ID.
else resetWindowId(); // Location change: Reset old window ID.
mWindowIdLocation = location;
if (mWindowIdLocation == CorePreview) PreviewManager::getInstance()->subscribe(this);
update();
@ -227,3 +214,12 @@ void CameraGui::updateWindowIdLocation() {
setWindowIdLocation(WindowIdLocation::Device);
else setWindowIdLocation(WindowIdLocation::CorePreview);
}
void CameraGui::callStateChanged(LinphoneEnums::CallState state) {
if (getSourceLocation() == CorePreview && state == LinphoneEnums::CallState::Connected) {
if (!getIsReady()) {
lDebug() << log().arg("Request new renderer because of not being Ready on CallState as Connected");
emit requestNewRenderer();
}
}
}

View file

@ -42,7 +42,6 @@ class CameraGui : public QQuickFramebufferObject, public AbstractObject {
Q_PROPERTY(bool isReady READ getIsReady WRITE setIsReady NOTIFY isReadyChanged)
// Q_PROPERTY(SoundPlayer * linphonePlayer READ getLinphonePlayer WRITE setLinphonePlayer NOTIFY
// linphonePlayerChanged)
Q_PROPERTY(QString qmlName READ getQmlName WRITE setQmlName NOTIFY qmlNameChanged REQUIRED)
typedef enum { None = -1, CorePreview = 0, Call, Device, Player, Core } WindowIdLocation;
@ -66,8 +65,6 @@ public:
void setCallGui(CallGui *callGui);
ParticipantDeviceGui *getParticipantDeviceGui() const;
void setParticipantDeviceGui(ParticipantDeviceGui *participantDeviceGui);
QString getQmlName() const;
void setQmlName(const QString &name);
WindowIdLocation getSourceLocation() const;
void setWindowIdLocation(const WindowIdLocation &location);
@ -76,6 +73,8 @@ public:
void removeCallModel();
void removeLinphonePlayer();
void callStateChanged(LinphoneEnums::CallState state);
signals:
void requestNewRenderer();
void isReadyChanged(bool isReady);
@ -85,7 +84,6 @@ signals:
void participantDeviceGuiChanged(ParticipantDeviceGui *participantDeviceGui);
void videoDefinitionChanged();
// void linphonePlayerChanged(SoundPlayer * linphonePlayer);
void qmlNameChanged();
private:
bool mIsPreview = false;
@ -96,13 +94,13 @@ private:
QTimer mLastVideoDefinitionChecker;
CallGui *mCallGui = nullptr;
ParticipantDeviceGui *mParticipantDeviceGui = nullptr;
QString mQmlName;
WindowIdLocation mWindowIdLocation = None;
mutable bool mIsWindowIdSet = false;
bool mIsDeleting = false;
DECLARE_ABSTRACT_OBJECT
DECLARE_GUI_OBJECT
};
#endif

View file

@ -25,6 +25,9 @@
#include "../App.hpp"
#include "PreviewManager.hpp"
#include "tool/Utils.hpp"
DEFINE_ABSTRACT_OBJECT(PreviewManager)
// =============================================================================
PreviewManager *PreviewManager::gInstance = nullptr;
@ -59,8 +62,11 @@ QQuickFramebufferObject::Renderer *PreviewManager::subscribe(const CameraGui *ca
connect(candidate, &QObject::destroyed, this, qOverload<QObject *>(&PreviewManager::unsubscribe));
mCandidates.append({candidate, nullptr});
itCandidate = mCandidates.end() - 1;
lDebug() << log().arg("Subscribing New") << itCandidate->first->getQmlName();
} else {
lDebug() << log().arg("Resubscribing") << itCandidate->first->getQmlName();
}
App::postModelSync([&renderer, isFirst = (itCandidate == mCandidates.begin())]() {
App::postModelBlock([&renderer, isFirst = (itCandidate == mCandidates.begin())]() {
renderer =
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
if (isFirst) CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer);
@ -78,16 +84,20 @@ void PreviewManager::unsubscribe(const CameraGui *candidate) { // If nullptr, Us
return item.first == candidate;
});
if (itCandidate != mCandidates.end()) {
lDebug() << log().arg("Unsubscribing") << itCandidate->first->getQmlName();
disconnect(candidate, nullptr, this, nullptr);
if (mCandidates.size() == 1) {
mCandidates.erase(itCandidate);
deactivate();
} else if (mCandidates.begin() == itCandidate) {
mCandidates.erase(itCandidate);
qWarning() << "Update " << mCandidates.first().first->getQmlName();
App::postModelSync([renderer = mCandidates.first().second]() {
CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer);
});
lDebug() << log().arg("Update") << mCandidates.first().first->getQmlName();
auto renderer = mCandidates.first().second;
if (!renderer) QTimer::singleShot(1, mCandidates.first().first, &CameraGui::requestNewRenderer);
else
App::postModelBlock([renderer = mCandidates.first().second]() {
CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer);
});
} else {
mCandidates.erase(itCandidate);
}

View file

@ -22,6 +22,7 @@
#define PREVIEW_MANAGER_H_
#include "CameraGui.hpp"
#include "tool/AbstractObject.hpp"
#include <QMutex>
#include <QObject>
#include <QPair>
@ -34,7 +35,7 @@
// =============================================================================
class PreviewManager : public QObject {
class PreviewManager : public QObject, public AbstractObject {
Q_OBJECT
public:
PreviewManager(QObject *parent = nullptr);
@ -55,6 +56,7 @@ private:
QList<QPair<const CameraGui *, QQuickFramebufferObject::Renderer *>> mCandidates;
static PreviewManager *gInstance;
QQuickFramebufferObject::Renderer *mPreviewRenderer = nullptr;
DECLARE_ABSTRACT_OBJECT
};
#endif

View file

@ -102,7 +102,7 @@ ParticipantDeviceCore *ConferenceCore::getActiveSpeaker() const {
}
ParticipantDeviceGui *ConferenceCore::getActiveSpeakerGui() const {
return new ParticipantDeviceGui(mActiveSpeaker);
return mActiveSpeaker ? new ParticipantDeviceGui(mActiveSpeaker) : nullptr;
}
ParticipantGui *ConferenceCore::getMeGui() const {

View file

@ -23,9 +23,6 @@
DEFINE_ABSTRACT_OBJECT(ParticipantDeviceGui)
ParticipantDeviceGui::ParticipantDeviceGui(QObject *parent) : QObject(parent) {
mCore = ParticipantDeviceCore::create(nullptr);
}
ParticipantDeviceGui::ParticipantDeviceGui(QSharedPointer<ParticipantDeviceCore> core) {
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
mCore = core;

View file

@ -32,7 +32,6 @@ class ParticipantDeviceGui : public QObject, public AbstractObject {
public:
ParticipantDeviceGui(QSharedPointer<ParticipantDeviceCore> core);
ParticipantDeviceGui(QObject *parent = nullptr);
~ParticipantDeviceGui();
ParticipantDeviceCore *getCore() const;
QSharedPointer<ParticipantDeviceCore> mCore;

View file

@ -92,26 +92,28 @@ QSharedPointer<ParticipantDeviceCore> ParticipantDeviceList::findDeviceByUniqueA
void ParticipantDeviceList::setConferenceModel(const std::shared_ptr<ConferenceModel> &conferenceModel) {
mustBeInMainThread(log().arg(Q_FUNC_INFO));
mConferenceModel = conferenceModel;
qDebug() << log().arg("Set Conference %1").arg((quint64)mConferenceModel.get());
if (mConferenceModelConnection->mCore.lock()) { // Unsure to get myself
auto oldConnect = mConferenceModelConnection->mCore; // Setself rebuild safepointer
setSelf(mConferenceModelConnection->mCore.mQData); // reset connections
oldConnect.unlock();
}
beginResetModel();
mList.clear();
endResetModel();
if (mConferenceModel) {
qDebug() << "[ParticipantDeviceList] : request devices";
mConferenceModelConnection->invokeToModel([this]() {
qDebug() << "[ParticipantDeviceList] : build devices";
auto devices = buildDevices(mConferenceModel);
mConferenceModelConnection->invokeToCore([this, devices]() {
qDebug() << "[ParticipantDeviceList] : set devices";
setDevices(devices);
if (mConferenceModel != conferenceModel) {
mConferenceModel = conferenceModel;
qDebug() << log().arg("Set Conference %1").arg((quint64)mConferenceModel.get());
if (mConferenceModelConnection->mCore.lock()) { // Unsure to get myself
auto oldConnect = mConferenceModelConnection->mCore; // Setself rebuild safepointer
setSelf(mConferenceModelConnection->mCore.mQData); // reset connections
oldConnect.unlock();
}
beginResetModel();
mList.clear();
endResetModel();
if (mConferenceModel) {
qDebug() << "[ParticipantDeviceList] : request devices";
mConferenceModelConnection->invokeToModel([this]() {
qDebug() << "[ParticipantDeviceList] : build devices";
auto devices = buildDevices(mConferenceModel);
mConferenceModelConnection->invokeToCore([this, devices]() {
qDebug() << "[ParticipantDeviceList] : set devices";
setDevices(devices);
});
});
});
}
}
}

View file

@ -21,12 +21,14 @@
#include "ParticipantDeviceProxy.hpp"
#include "ParticipantDeviceList.hpp"
#include "core/App.hpp"
#include "tool/Utils.hpp"
#include <QQmlApplicationEngine>
// =============================================================================
DEFINE_ABSTRACT_OBJECT(ParticipantDeviceProxy)
DEFINE_GUI_OBJECT(ParticipantDeviceProxy)
ParticipantDeviceProxy::ParticipantDeviceProxy(QObject *parent) : SortFilterProxy(parent) {
mParticipants = ParticipantDeviceList::create();
@ -45,11 +47,17 @@ CallGui *ParticipantDeviceProxy::getCurrentCall() const {
}
void ParticipantDeviceProxy::setCurrentCall(CallGui *call) {
qDebug() << "[ParticipantDeviceProxy] set current call " << this << " => " << call;
lDebug() << log().arg("Set current call") << this << " => " << call;
if (mCurrentCall != call) {
CallCore *callCore = nullptr;
if (mCurrentCall) {
callCore = mCurrentCall->getCore();
if (call && callCore == call->getCore()) {
mCurrentCall = call;
lDebug() << log().arg("Same call core");
emit currentCallChanged();
return;
}
if (callCore) callCore->disconnect(mParticipants.get());
callCore = nullptr;
}
@ -58,12 +66,12 @@ void ParticipantDeviceProxy::setCurrentCall(CallGui *call) {
if (callCore) {
connect(callCore, &CallCore::conferenceChanged, mParticipants.get(), [this]() {
auto conference = mCurrentCall->getCore()->getConferenceCore();
qDebug() << "[ParticipantDeviceProxy] set conference " << this << " => " << conference;
lDebug() << log().arg("Set conference") << this << " => " << conference;
mParticipants->setConferenceModel(conference ? conference->getModel() : nullptr);
// mParticipants->lSetConferenceModel(conference ? conference->getModel() : nullptr);
});
auto conference = callCore->getConferenceCore();
qDebug() << "[ParticipantDeviceProxy] set conference " << this << " => " << conference;
lDebug() << log().arg("Set conference") << this << " => " << conference;
mParticipants->setConferenceModel(conference ? conference->getModel() : nullptr);
// mParticipants->lSetConferenceModel(conference ? conference->getModel() : nullptr);
}

View file

@ -35,6 +35,7 @@ class ParticipantDeviceProxy : public SortFilterProxy, public AbstractObject {
Q_PROPERTY(ParticipantDeviceGui *me READ getMe WRITE setMe NOTIFY meChanged)
public:
DECLARE_GUI_OBJECT
ParticipantDeviceProxy(QObject *parent = Q_NULLPTR);
~ParticipantDeviceProxy();

View file

@ -149,7 +149,7 @@ signals:
void nextVideoFrameDecoded(const std::shared_ptr<linphone::Call> &call);
void cameraNotWorking(const std::shared_ptr<linphone::Call> &call, const std::string &cameraName);
void videoDisplayErrorOccurred(const std::shared_ptr<linphone::Call> &call, int errorCode);
virtual void audioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
void audioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
const std::shared_ptr<linphone::AudioDevice> &audioDevice);
void remoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording);
};

View file

@ -34,11 +34,35 @@
return gClassName; \
}
#define DECLARE_GUI_OBJECT \
Q_SIGNALS: \
void qmlNameChanged(); \
\
public: \
Q_PROPERTY(QString qmlName READ getQmlName WRITE setQmlName NOTIFY qmlNameChanged) \
QString getQmlName() const; \
void setQmlName(const QString &name); \
QString mQmlName; \
virtual inline QString log() const override { \
return AbstractObject::log().arg(QStringLiteral("%1 %2").arg(getQmlName()).arg("%1")); \
}
#define DEFINE_GUI_OBJECT(CLASS_NAME) \
QString CLASS_NAME::getQmlName() const { \
return mQmlName; \
} \
void CLASS_NAME::setQmlName(const QString &name) { \
if (mQmlName != name) { \
mQmlName = name; \
emit qmlNameChanged(); \
} \
}
class AbstractObject {
public:
virtual QString getClassName() const = 0;
// return "[ClassName]: %1"
inline QString log() const {
virtual inline QString log() const {
return QStringLiteral("[%1]: %2").arg(getClassName()).arg("%1");
}
inline static bool isInLinphoneThread() {

View file

@ -304,7 +304,7 @@ QString Utils::generateLinphoneSipAddress(const QString &uri) {
QString Utils::findAvatarByAddress(const QString &address) {
QString avatar;
App::postModelSync([address, avatar]() mutable {
App::postModelBlock([address, avatar]() mutable {
auto defaultFriendList = CoreModel::getInstance()->getCore()->getDefaultFriendList();
if (!defaultFriendList) return;
auto linphoneAddr = ToolModel::interpretUrl(address);

View file

@ -21,6 +21,7 @@
#ifndef UTILS_H_
#define UTILS_H_
#include <QDebug>
#include <QObject>
#include <QString>
@ -138,4 +139,10 @@ public:
}
};
#define lDebug() qDebug().noquote()
#define lInfo() qInfo().noquote()
#define lWarning() qWarning().noquote()
#define lCritical() qCritical().noquote()
#define lFatal() qFatal().noquote()
#endif // UTILS_H_

View file

@ -26,9 +26,9 @@ Window {
console.log("CALL", call)
// if conference, the main item is only
// displayed when state is connected
if (call && !conferenceInfo) middleItemStackView.replace(inCallItem)
//if (call && middleItemStackView.currentItem != inCallItem) middleItemStackView.replace(inCallItem)
}
Component.onCompleted: if (call && !conferenceInfo) middleItemStackView.replace(inCallItem)
//Component.onCompleted: if (call && !conferenceInfo && middleItemStackView.currentItem != inCallItem) middleItemStackView.replace(inCallItem)
property var callObj
function joinConference(withVideo) {
@ -63,7 +63,7 @@ Window {
onCallStateChanged: {
console.log("State:", callState)
if (callState === LinphoneEnums.CallState.Connected) {
if (conferenceInfo) {
if (conferenceInfo && middleItemStackView.currentItem != inCallItem) {
middleItemStackView.replace(inCallItem)
bottomButtonsLayout.visible = true
}
@ -678,7 +678,7 @@ Window {
Component {
id: inCallItem
Control.Control {
Item {
Layout.fillWidth: true
implicitWidth: 1059 * DefaultStyle.dp
// implicitHeight: parent.height
@ -693,10 +693,12 @@ Window {
color: DefaultStyle.grey_600
radius: 15 * DefaultStyle.dp
}*/
contentItem: CallLayout{
CallLayout{
anchors.fill: parent
call: mainWindow.call
callTerminatedByUser: mainWindow.callTerminatedByUser
}
Component.onCompleted: console.log("New inCallItem " + inCallItem)
}
}
GridLayout {

View file

@ -23,7 +23,7 @@ Item {
property int radius: 15 * DefaultStyle.dp
property var peerAddressObj: participantDevice && participantDevice.core
? UtilsCpp.getDisplayName(participantDevice.core.address)
: call && call.core
: !previewEnabled && call && call.core
? UtilsCpp.getDisplayName(call.core.peerAddress)
: null
property string peerAddress:peerAddressObj ? peerAddressObj.value : ""
@ -47,7 +47,7 @@ Item {
height: 100
width: height
account: mainItem.account
call: mainItem.call
call: !mainItem.previewEnabled ? mainItem.call : null
}
Text {
Layout.alignment: Qt.AlignHCenter

View file

@ -17,6 +17,8 @@ Item{
property ParticipantDeviceProxy participantDevices : ParticipantDeviceProxy {
id: allDevices
qmlName: "AS"
Component.onCompleted: console.log("Loaded : " +allDevices)
}
onCallChanged: {
waitingTime.seconds = 0
@ -102,7 +104,10 @@ Item{
}
Sticker {
id: preview
visible: allDevices.count <= 2
qmlName: 'P'
previewEnabled: true
visible: mainItem.call && allDevices.count <= 2
onVisibleChanged: console.log(visible + " : " +allDevices.count)
height: 180 * DefaultStyle.dp
width: 300 * DefaultStyle.dp
anchors.right: mainItem.right
@ -110,9 +115,10 @@ Item{
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.bottomMargin: 10 * DefaultStyle.dp
//participantDevice: allDevices.me
cameraEnabled: visible && mainItem.call && mainItem.call.core.cameraEnabled
previewEnabled: true
qmlName: 'P'
cameraEnabled: preview.visible && mainItem.call && mainItem.call.core.cameraEnabled
onCameraEnabledChanged: console.log("P : " +cameraEnabled + " / " +visible +" / " +mainItem.call)
call: mainItem.call
MovableMouseArea {
id: previewMouseArea