Add moveToThread on Gui objects constructor.

Fix VariantObject connections.
Rename call creator API.
Update SDK.
This commit is contained in:
Julien Wadel 2023-11-23 13:49:14 +01:00
parent cd82964b23
commit 9ec84bb168
13 changed files with 50 additions and 27 deletions

View file

@ -24,10 +24,10 @@
DEFINE_ABSTRACT_OBJECT(AccountGui) DEFINE_ABSTRACT_OBJECT(AccountGui)
AccountGui::AccountGui(QSharedPointer<AccountCore> core) { AccountGui::AccountGui(QSharedPointer<AccountCore> core) {
mustBeInMainThread(getClassName());
qDebug() << "[AccountGui] new" << this; qDebug() << "[AccountGui] new" << this;
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
mCore = core; mCore = core;
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
} }
AccountGui::~AccountGui() { AccountGui::~AccountGui() {

View file

@ -54,18 +54,19 @@ void AccountList::setSelf(QSharedPointer<AccountList> me) {
&QObject::deleteLater); &QObject::deleteLater);
mModelConnection->makeConnect(this, &AccountList::lUpdate, [this]() { mModelConnection->makeConnect(this, &AccountList::lUpdate, [this]() {
mModelConnection->invokeToModel([this]() { mModelConnection->invokeToModel([this]() {
QList<QSharedPointer<AccountCore>> accounts; QList<QSharedPointer<AccountCore>> *accounts = new QList<QSharedPointer<AccountCore>>();
// Model thread. // Model thread.
mustBeInLinphoneThread(getClassName()); mustBeInLinphoneThread(getClassName());
auto linphoneAccounts = CoreModel::getInstance()->getCore()->getAccountList(); auto linphoneAccounts = CoreModel::getInstance()->getCore()->getAccountList();
for (auto it : linphoneAccounts) { for (auto it : linphoneAccounts) {
auto model = AccountCore::create(it); auto model = AccountCore::create(it);
accounts.push_back(model); accounts->push_back(model);
} }
mModelConnection->invokeToCore([this, accounts]() { mModelConnection->invokeToCore([this, accounts]() {
mustBeInMainThread(getClassName()); mustBeInMainThread(getClassName());
clearData(); resetData();
add(accounts); add(*accounts);
delete accounts;
}); });
}); });
}); });

View file

@ -24,10 +24,10 @@
DEFINE_ABSTRACT_OBJECT(CallGui) DEFINE_ABSTRACT_OBJECT(CallGui)
CallGui::CallGui(QSharedPointer<CallCore> core) { CallGui::CallGui(QSharedPointer<CallCore> core) {
mustBeInMainThread(getClassName());
qDebug() << "[CallGui] new" << this; qDebug() << "[CallGui] new" << this;
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
mCore = core; mCore = core;
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
} }
CallGui::~CallGui() { CallGui::~CallGui() {

View file

@ -37,8 +37,15 @@ VariantObject::VariantObject(QVariant defaultValue, QObject *parent) {
new SafeConnection(mCoreObject.objectCast<QObject>(), mModelObject.objectCast<QObject>()), new SafeConnection(mCoreObject.objectCast<QObject>(), mModelObject.objectCast<QObject>()),
&QObject::deleteLater); &QObject::deleteLater);
mConnection->makeConnect(mCoreObject.get(), &SafeObject::setValue, &SafeObject::onSetValue); mConnection->makeConnect(mCoreObject.get(), &SafeObject::setValue, [this](QVariant value) {
mConnection->makeConnect(mModelObject.get(), &SafeObject::setValue, &SafeObject::onSetValue); mConnection->invokeToModel([this, value]() { mModelObject->onSetValue(value); });
});
mConnection->makeConnect(mModelObject.get(), &SafeObject::setValue, [this](QVariant value) {
mConnection->invokeToCore([this, value]() { mCoreObject->onSetValue(value); });
});
mConnection->makeConnect(mModelObject.get(), &SafeObject::valueChanged, [this](QVariant value) {
mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); });
});
connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged); connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged);
} }

View file

@ -68,9 +68,9 @@ QString ToolModel::getDisplayName(QString address) {
return displayName.isEmpty() ? address : displayName; return displayName.isEmpty() ? address : displayName;
} }
QSharedPointer<CallCore> ToolModel::startAudioCall(const QString &sipAddress, QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress,
const QString &prepareTransfertAddress, const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers) { const QHash<QString, QString> &headers) {
bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall() bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall()
std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore(); std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore();

View file

@ -39,9 +39,9 @@ public:
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address); static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
static QString getDisplayName(QString address); static QString getDisplayName(QString address);
static QSharedPointer<CallCore> startAudioCall(const QString &sipAddress, static QSharedPointer<CallCore> createCall(const QString &sipAddress,
const QString &prepareTransfertAddress = "", const QString &prepareTransfertAddress = "",
const QHash<QString, QString> &headers = {}); const QHash<QString, QString> &headers = {});
private: private:
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT

View file

@ -41,7 +41,9 @@ public:
inline QString log() const { inline QString log() const {
return QStringLiteral("[%1]: %2").arg(getClassName()).arg("%1"); return QStringLiteral("[%1]: %2").arg(getClassName()).arg("%1");
} }
inline static bool isInLinphoneThread() {
return Thread::isInLinphoneThread();
}
inline static bool mustBeInLinphoneThread(const QString &context) { // For convenience : Alias to Thread inline static bool mustBeInLinphoneThread(const QString &context) { // For convenience : Alias to Thread
return Thread::mustBeInLinphoneThread(context); return Thread::mustBeInLinphoneThread(context);
} }

View file

@ -50,13 +50,13 @@ VariantObject *Utils::getDisplayName(const QString &address) {
return data; return data;
} }
VariantObject *Utils::startAudioCall(const QString &sipAddress, VariantObject *Utils::createCall(const QString &sipAddress,
const QString &prepareTransfertAddress, const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers) { const QHash<QString, QString> &headers) {
VariantObject *data = new VariantObject(QVariant()); // Scope : GUI VariantObject *data = new VariantObject(QVariant()); // Scope : GUI
data->makeRequest([sipAddress, prepareTransfertAddress, headers]() { data->makeRequest([sipAddress, prepareTransfertAddress, headers]() {
auto call = ToolModel::startAudioCall(sipAddress, prepareTransfertAddress, headers); auto call = ToolModel::createCall(sipAddress, prepareTransfertAddress, headers);
if (call) { if (call) {
return QVariant::fromValue(new CallGui(call)); return QVariant::fromValue(new CallGui(call));
} else return QVariant(); } else return QVariant();

View file

@ -49,9 +49,9 @@ public:
} }
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address); Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
Q_INVOKABLE static VariantObject *startAudioCall(const QString &sipAddress, Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
const QString &prepareTransfertAddress = "", const QString &prepareTransfertAddress = "",
const QHash<QString, QString> &headers = {}); const QHash<QString, QString> &headers = {});
Q_INVOKABLE static VariantObject *haveAccount(); Q_INVOKABLE static VariantObject *haveAccount();
static inline QString coreStringToAppString(const std::string &str) { static inline QString coreStringToAppString(const std::string &str) {

View file

@ -33,12 +33,16 @@ void Thread::run() {
if (result <= 0) toExit = true; if (result <= 0) toExit = true;
} }
} }
bool Thread::isInLinphoneThread() {
return QThread::currentThread() == CoreModel::getInstance()->thread();
}
bool Thread::mustBeInLinphoneThread(const QString &context) { bool Thread::mustBeInLinphoneThread(const QString &context) {
bool isLinphoneThread = QThread::currentThread() == CoreModel::getInstance()->thread(); bool isLinphoneThread = isInLinphoneThread();
if (!isLinphoneThread) qCritical() << "[Thread] Not processing in Linphone thread from " << context; if (!isLinphoneThread) qCritical() << "[Thread] Not processing in Linphone thread from " << context;
return isLinphoneThread; return isLinphoneThread;
} }
bool Thread::mustBeInMainThread(const QString &context) { bool Thread::mustBeInMainThread(const QString &context) {
bool isMainThread = QThread::currentThread() == App::getInstance()->thread(); bool isMainThread = QThread::currentThread() == App::getInstance()->thread();
if (!isMainThread) qCritical() << "[Thread] Not processing in Main thread from " << context; if (!isMainThread) qCritical() << "[Thread] Not processing in Main thread from " << context;

View file

@ -26,6 +26,7 @@
class Thread : public QThread { class Thread : public QThread {
public: public:
Thread(QObject *parent = nullptr); Thread(QObject *parent = nullptr);
static bool isInLinphoneThread();
static bool mustBeInLinphoneThread(const QString &context); static bool mustBeInLinphoneThread(const QString &context);
static bool mustBeInMainThread(const QString &context); static bool mustBeInMainThread(const QString &context);

View file

@ -26,6 +26,10 @@ Window{
gc() gc()
} }
Component.onDestruction: gc() Component.onDestruction: gc()
Connections{
target: call && call.core || null
onLastErrorMessageChanged: if(mainItem.call) errorMessageText.text=mainItem.call.core.lastErrorMessage
}
ColumnLayout{ ColumnLayout{
anchors.fill: parent anchors.fill: parent
RowLayout { RowLayout {
@ -69,8 +73,11 @@ Window{
id: accountStatus id: accountStatus
Layout.preferredWidth: 50 Layout.preferredWidth: 50
Layout.preferredHeight: 50 Layout.preferredHeight: 50
property int accountCount: accountProxy.count
onAccountCountChanged: console.log("AccountCount:"+accountCount)
property var defaultAccount: accountProxy.defaultAccount property var defaultAccount: accountProxy.defaultAccount
property var state: accountProxy.count > 0 && defaultAccount? defaultAccount.registrationState : LoginPageCpp.registrationState onDefaultAccountChanged: console.log("DefaultAccount:"+defaultAccount)
property var state: accountProxy.count > 0 && defaultAccount? defaultAccount.core.registrationState : LoginPageCpp.registrationState
onStateChanged: console.log("State:"+state) onStateChanged: console.log("State:"+state)
color: state === LinphoneEnums.RegistrationState.Ok color: state === LinphoneEnums.RegistrationState.Ok
@ -94,7 +101,9 @@ Window{
Button{ Button{
text: 'Call' text: 'Call'
onClicked: { onClicked: {
mainItem.callVarObject = UtilsCpp.startAudioCall(usernameToCall.inputText + "@sip.linphone.org") var address = usernameToCall.text + "@sip.linphone.org"
console.log("Calling "+address)
mainItem.callVarObject = UtilsCpp.createCall(address)
proto.component1 = comp proto.component1 = comp
} }
} }
@ -123,7 +132,6 @@ Window{
} }
Text{ Text{
id: errorMessageText id: errorMessageText
text: mainItem.call ? mainItem.call.core.lastErrorMessage : ''
color: 'red' color: 'red'
} }
ItemPrototype{ ItemPrototype{

@ -1 +1 @@
Subproject commit aaeaad94a6e63f182f50318ed1a209c83b152d73 Subproject commit a9a7ff8bb52d7535033b0cb60e2113b9ee377664