From 3399c9e445e1e1c4f932b36624c0aeaa98bff68c Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Sun, 11 Sep 2022 22:20:28 +0200 Subject: [PATCH] Multithreading prototype. --- linphone-app/CMakeLists.txt | 4 ++ linphone-app/src/app/App.cpp | 10 ++-- linphone-app/src/components/Components.hpp | 1 + linphone-app/src/components/core/Core.cpp | 32 +++++++++++ linphone-app/src/components/core/Core.hpp | 22 ++++++++ .../src/components/core/CoreManager.cpp | 30 +++++++++-- .../src/components/core/CoreManager.hpp | 21 +++++--- .../src/components/core/CoreManagerGUI.cpp | 29 ++++++++++ .../src/components/core/CoreManagerGUI.hpp | 36 +++++++++++++ .../linphoneObject/LinphoneObject.h | 31 +++++++++++ .../linphoneObject/LinphoneThread.hpp | 54 +++++++++++++++++++ 11 files changed, 255 insertions(+), 15 deletions(-) create mode 100644 linphone-app/src/components/core/Core.cpp create mode 100644 linphone-app/src/components/core/Core.hpp create mode 100644 linphone-app/src/components/core/CoreManagerGUI.cpp create mode 100644 linphone-app/src/components/core/CoreManagerGUI.hpp create mode 100644 linphone-app/src/components/linphoneObject/LinphoneObject.h create mode 100644 linphone-app/src/components/linphoneObject/LinphoneThread.hpp diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index f00f19a18..97ef7f674 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -241,6 +241,7 @@ set(SOURCES src/components/content/ContentProxyModel.cpp src/components/core/CoreHandlers.cpp src/components/core/CoreManager.cpp + src/components/core/CoreManagerGUI.cpp src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp src/components/file/FileDownloader.cpp src/components/file/FileExtractor.cpp @@ -252,6 +253,7 @@ set(SOURCES src/components/ldap/LdapModel.cpp src/components/ldap/LdapListModel.cpp src/components/ldap/LdapProxyModel.cpp + #src/components/linphoneObject/LinphoneThread.cpp src/components/notifier/Notifier.cpp src/components/other/clipboard/Clipboard.cpp src/components/other/colors/ColorModel.cpp @@ -381,6 +383,7 @@ set(HEADERS src/components/content/ContentProxyModel.hpp src/components/core/CoreHandlers.hpp src/components/core/CoreManager.hpp + src/components/core/CoreManagerGUI.hpp src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp src/components/file/FileDownloader.hpp src/components/file/FileExtractor.hpp @@ -392,6 +395,7 @@ set(HEADERS src/components/ldap/LdapModel.hpp src/components/ldap/LdapListModel.hpp src/components/ldap/LdapProxyModel.hpp + src/components/linphoneObject/LinphoneThread.hpp src/components/notifier/Notifier.hpp src/components/other/clipboard/Clipboard.hpp src/components/other/colors/ColorModel.hpp diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index b89685a5a..78da9667d 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -61,6 +61,10 @@ #include "components/participant/ParticipantListModel.hpp" #include "components/participant/ParticipantProxyModel.hpp" +#include +#include + +Q_DECLARE_METATYPE(linphone::ConfiguringState) // ============================================================================= using namespace std; @@ -200,8 +204,7 @@ bool App::setFetchConfig (QCommandLineParser *parser) { App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) { - - connect(this, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(stateChanged(Qt::ApplicationState))); + connect(this, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(stateChanged(Qt::ApplicationState))); setWindowIcon(QIcon(Constants::WindowIconPath)); @@ -658,6 +661,7 @@ void App::registerTypes () { qRegisterMetaType>(); qRegisterMetaType>(); //qRegisterMetaType>(); + qRegisterMetaType(); LinphoneEnums::registerMetaTypes(); registerType("AssistantModel"); @@ -741,7 +745,7 @@ void App::registerSharedTypes () { qInfo() << QStringLiteral("Registering shared types..."); registerSharedSingletonType("App"); - registerSharedSingletonType("CoreManager"); + registerSharedSingletonType("CoreManager"); registerSharedSingletonType("SettingsModel"); registerSharedSingletonType("AccountSettingsModel"); registerSharedSingletonType("SipAddressesModel"); diff --git a/linphone-app/src/components/Components.hpp b/linphone-app/src/components/Components.hpp index 68810b554..ea87709a9 100644 --- a/linphone-app/src/components/Components.hpp +++ b/linphone-app/src/components/Components.hpp @@ -52,6 +52,7 @@ #include "content/ContentProxyModel.hpp" #include "core/CoreHandlers.hpp" #include "core/CoreManager.hpp" +#include "core/CoreManagerGUI.hpp" #include "file/FileDownloader.hpp" #include "file/FileExtractor.hpp" #include "file/TemporaryFile.hpp" diff --git a/linphone-app/src/components/core/Core.cpp b/linphone-app/src/components/core/Core.cpp new file mode 100644 index 000000000..0e4b73400 --- /dev/null +++ b/linphone-app/src/components/core/Core.cpp @@ -0,0 +1,32 @@ +#include "Core.hpp" + +#include +#include + +#include "utils/Constants.hpp" + +Core::Core(QObject * parent) : LinphoneObject>(parent){ + +} + +void Core::startIterate(){ + mCbsTimer = new QTimer((QThread*)this); + mCbsTimer->setInterval(Constants::CbsCallInterval); + QObject::connect(mCbsTimer, &QTimer::timeout, this, &Core::iterate); + qInfo() << QStringLiteral("Start iterate"); + + mCbsTimer->start(); + start(); +} + +void Core::stopIterate(){ + qInfo() << QStringLiteral("Stop iterate"); + mCbsTimer->stop(); + mCbsTimer->deleteLater();// allow the timer to continue its stuff + mCbsTimer = nullptr; +} + +void Core::iterate () + if(mLinphoneObject) + mLinphoneObject->iterate(); +} diff --git a/linphone-app/src/components/core/Core.hpp b/linphone-app/src/components/core/Core.hpp new file mode 100644 index 000000000..6af2194c6 --- /dev/null +++ b/linphone-app/src/components/core/Core.hpp @@ -0,0 +1,22 @@ +#ifndef CORE_H +#define CORE_H + +#include +#include "components/linphoneObject/LinphoneObject.h" + +#include + +class QTimer; + +class Core : public LinphoneObject>{ +public: + Core(QObject * parent = nullptr); + + void startIterate(); + void stopIterate(); + void iterate (); +private: + QTimer * mCbsTimer; +}; + +#endif // CORE_H diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 01bfa2f6c..a9098b672 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -34,6 +34,7 @@ #include "components/contact/VcardModel.hpp" #include "components/contacts/ContactsListModel.hpp" #include "components/contacts/ContactsImporterListModel.hpp" +#include "components/core/CoreManagerGUI.hpp" #include "components/history/HistoryModel.hpp" #include "components/ldap/LdapListModel.hpp" #include "components/recorder/RecorderManager.hpp" @@ -56,6 +57,7 @@ #include #include +#include "components/linphoneObject/LinphoneThread.hpp" // ============================================================================= @@ -64,6 +66,8 @@ using namespace std; // ----------------------------------------------------------------------------- CoreManager *CoreManager::mInstance=nullptr; +CoreManagerGUI *CoreManager::mInstanceGUI=nullptr; +QSharedPointer CoreManager::gLinphoneThread = nullptr; CoreManager::CoreManager (QObject *parent, const QString &configPath) : QObject(parent), mHandlers(make_shared(this)) { @@ -123,6 +127,10 @@ CoreManager *CoreManager::getInstance (){ return mInstance; } +CoreManagerGUI *CoreManager::getInstanceGUI (){ + return mInstanceGUI; +} + HistoryModel* CoreManager::getHistoryModel(){ if(!mHistoryModel){ @@ -144,7 +152,12 @@ RecorderManager* CoreManager::getRecorderManager(){ void CoreManager::init (QObject *parent, const QString &configPath) { if (mInstance) return; - mInstance = new CoreManager(parent, configPath); + gLinphoneThread = QSharedPointer::create(parent); + gLinphoneThread->start(); + //this->moveToThread(mLinphoneThread.get()); + mInstance = new CoreManager(nullptr, configPath); + gLinphoneThread->objectToThread(mInstance); + mInstanceGUI = new CoreManagerGUI(parent); } void CoreManager::uninit () { @@ -155,6 +168,10 @@ void CoreManager::uninit () { mInstance->unlockVideoRender(); delete mInstance; // This will also remove stored Linphone objects. mInstance = nullptr; + gLinphoneThread->exit(); + gLinphoneThread = nullptr; + mInstanceGUI->deleteLater(); + mInstanceGUI = nullptr; core->stop(); if( core->getGlobalState() != linphone::GlobalState::Off) qWarning() << "Core is not off after stopping it. It may result to have multiple core instance."; @@ -412,16 +429,19 @@ std::list> CoreManager::getAccountList()const // ----------------------------------------------------------------------------- void CoreManager::startIterate(){ - mCbsTimer = new QTimer(this); + mCbsTimer = new QTimer(); mCbsTimer->setInterval(Constants::CbsCallInterval); - QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate); + QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate, Qt::DirectConnection); qInfo() << QStringLiteral("Start iterate"); - mCbsTimer->start(); + emit gLinphoneThread->startT(mCbsTimer); + //gLinphoneThread->test(mCbsTimer); + //mCbsTimer->start(); } void CoreManager::stopIterate(){ qInfo() << QStringLiteral("Stop iterate"); - mCbsTimer->stop(); + emit gLinphoneThread->stopT(mCbsTimer); + //mCbsTimer->stop(); mCbsTimer->deleteLater();// allow the timer to continue its stuff mCbsTimer = nullptr; } diff --git a/linphone-app/src/components/core/CoreManager.hpp b/linphone-app/src/components/core/CoreManager.hpp index 637cac4f9..dca85ed08 100644 --- a/linphone-app/src/components/core/CoreManager.hpp +++ b/linphone-app/src/components/core/CoreManager.hpp @@ -26,6 +26,7 @@ #include #include #include +#include // ============================================================================= @@ -39,6 +40,7 @@ class ChatRoomModel; class ContactsListModel; class ContactsImporterListModel; class CoreHandlers; +class CoreManagerGUI; class EventCountNotifier; class HistoryModel; class LdapListModel; @@ -48,16 +50,17 @@ class SipAddressesModel; class VcardModel; class TimelineListModel; +class LinphoneThread; + class CoreManager : public QObject { - Q_OBJECT; + Q_OBJECT Q_PROPERTY(QString version READ getVersion CONSTANT) Q_PROPERTY(QString downloadUrl READ getDownloadUrl CONSTANT) Q_PROPERTY(int eventCount READ getEventCount NOTIFY eventCountChanged) Q_PROPERTY(int callLogsCount READ getCallLogsCount NOTIFY callLogsCountChanged) Q_PROPERTY(bool initialized READ isInitialized NOTIFY coreManagerInitialized) - public: bool started () const { return mStarted; @@ -135,6 +138,11 @@ public: } static CoreManager *getInstance (); + static CoreManagerGUI *getInstanceGUI(); + + QString getVersion () const; + int getEventCount () const; + static QString getDownloadUrl (); // --------------------------------------------------------------------------- // Initialization. @@ -200,16 +208,12 @@ private: void migrate (); - QString getVersion () const; - - int getEventCount () const; + void iterate (); void handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info); - static QString getDownloadUrl (); - std::shared_ptr mCore; std::shared_ptr mHandlers; // It is used for handling linphone. Keep it to shared_ptr. @@ -237,6 +241,9 @@ private: QMutex mMutexVideoRender; static CoreManager *mInstance; + static CoreManagerGUI *mInstanceGUI; + + static QSharedPointer gLinphoneThread; }; #endif // CORE_MANAGER_H_ diff --git a/linphone-app/src/components/core/CoreManagerGUI.cpp b/linphone-app/src/components/core/CoreManagerGUI.cpp new file mode 100644 index 000000000..446abe8be --- /dev/null +++ b/linphone-app/src/components/core/CoreManagerGUI.cpp @@ -0,0 +1,29 @@ +#include "CoreManagerGUI.hpp" + +#include "components/Components.hpp" + +CoreManagerGUI::CoreManagerGUI(QObject * parent) : QObject(parent){ + auto core = CoreManager::getInstance(); + + connect(core, &CoreManager::coreManagerInitialized, this, &CoreManagerGUI::coreManagerInitialized); + connect(core, &CoreManager::chatRoomModelCreated, this, &CoreManagerGUI::chatRoomModelCreated); + connect(core, &CoreManager::historyModelCreated, this, &CoreManagerGUI::historyModelCreated); + connect(core, &CoreManager::recorderManagerCreated, this, &CoreManagerGUI::recorderManagerCreated); + + connect(core, &CoreManager::eventCountChanged, this, &CoreManagerGUI::eventCountChanged); + connect(core, &CoreManager::callLogsCountChanged, this, &CoreManagerGUI::callLogsCountChanged); +} + +QString CoreManagerGUI::getDownloadUrl (){ + return CoreManager::getDownloadUrl(); +} + +QString CoreManagerGUI::getVersion () const{ + return CoreManager::getInstance()->getVersion(); +} +int CoreManagerGUI::getEventCount () const{ + return CoreManager::getInstance()->getEventCount(); +} +int CoreManagerGUI::getCallLogsCount() const{ + return CoreManager::getInstance()->getCallLogsCount(); +} diff --git a/linphone-app/src/components/core/CoreManagerGUI.hpp b/linphone-app/src/components/core/CoreManagerGUI.hpp new file mode 100644 index 000000000..b0b2359ca --- /dev/null +++ b/linphone-app/src/components/core/CoreManagerGUI.hpp @@ -0,0 +1,36 @@ +#ifndef COREMANAGERGUI_H +#define COREMANAGERGUI_H + +#include + +class ChatRoomModel; +class HistoryModel; +class RecorderManager; + +class CoreManagerGUI : public QObject{ + Q_OBJECT + Q_PROPERTY(QString version READ getVersion CONSTANT) + Q_PROPERTY(QString downloadUrl READ getDownloadUrl CONSTANT) + Q_PROPERTY(int eventCount READ getEventCount NOTIFY eventCountChanged) + Q_PROPERTY(int callLogsCount READ getCallLogsCount NOTIFY callLogsCountChanged) +public: + CoreManagerGUI(QObject * parent = nullptr); + + QString getVersion () const; + int getEventCount () const; + int getCallLogsCount() const; + static QString getDownloadUrl (); +signals: + void coreManagerInitialized (); + + void chatRoomModelCreated (const QSharedPointer &chatRoomModel); + void historyModelCreated (HistoryModel *historyModel); + void recorderManagerCreated(RecorderManager *recorderModel); + + void logsUploaded (const QString &url); + void eventCountChanged (); + void callLogsCountChanged(); + +}; + +#endif // COREMANAGERGUI_H diff --git a/linphone-app/src/components/linphoneObject/LinphoneObject.h b/linphone-app/src/components/linphoneObject/LinphoneObject.h new file mode 100644 index 000000000..73a76ed74 --- /dev/null +++ b/linphone-app/src/components/linphoneObject/LinphoneObject.h @@ -0,0 +1,31 @@ +#ifndef LINPHONEOBJECT_H +#define LINPHONEOBJECT_H + +#include +#include +#include + + +template +class LinphoneObject : public QObject{ +public: + LinphoneObject(QObject * parent = nullptr) : QObject(parent){} + + bool isValid() const{ + bool ok = true; + if(!gLinphoneThread) + gLinphoneThread = QThread::currentThread(); + else if(gLinphoneThread != QThread::currentThread()){ + ok = false; + qCritical() << "Current Linphone Object is being used in the wrong thread" << this; + } + return ok; + } +private: + T mLinphoneObject; + + static QThread * gLinphoneThread; +}; +template +QThread *LinphoneObject::gLinphoneThread = nullptr; +#endif // LINPHONEOBJECT_H diff --git a/linphone-app/src/components/linphoneObject/LinphoneThread.hpp b/linphone-app/src/components/linphoneObject/LinphoneThread.hpp new file mode 100644 index 000000000..37baa8c90 --- /dev/null +++ b/linphone-app/src/components/linphoneObject/LinphoneThread.hpp @@ -0,0 +1,54 @@ +#ifndef LINPHONETHREAD_HPP +#define LINPHONETHREAD_HPP + +#include +#include + + +class LinphoneThread : public QObject{ + Q_OBJECT +public: + + class LThread : public QThread{ + public: + LThread(QObject * parent) : QThread(parent){} + virtual void run(){ + exec(); + } + }; + LThread * mThread; + LinphoneThread(QObject * parent = nullptr) : QObject(nullptr){ + mThread = new LThread(parent); + this->moveToThread(mThread); + connect(this, &LinphoneThread::startT, this, &LinphoneThread::startAsync, Qt::QueuedConnection); + connect(this, &LinphoneThread::stopT, this, &LinphoneThread::stopAsync, Qt::QueuedConnection); + } + void start(){ + mThread->start(); + } + void exit(){ + mThread->exit(); + } + + void objectToThread(QObject * object){ + object->moveToThread(mThread); + } +signals: + void startT(QTimer * timer); + void stopT(QTimer * timer); +public slots: + void startAsync(QTimer * timer){ + timer->moveToThread(mThread); + timer->start(); + } + void stopAsync(QTimer * timer){ + timer->stop(); + } + /* + template + void create(T t){ + t->moveToThread(this); + }*/ +}; + +#endif // LINPHONETHREAD_HPP