diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index 6ad57872f..805a6f0b0 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -397,7 +397,7 @@ void App::initContentApp () { QObject::connect( CoreManager::getInstance(), - &CoreManager::coreStarted, CoreManager::getInstance(), + &CoreManager::managerInitialized, CoreManager::getInstance(), [this, mustBeIconified]() mutable { if(CoreManager::getInstance()->started()) openAppAfterInit(mustBeIconified); @@ -894,7 +894,7 @@ void App::openAppAfterInit (bool mustBeIconified) { coreManager->getCallsListModel()->launchAudioCall(sipAddress); }else{ QObject * context = new QObject(); - QObject::connect(CoreManager::getInstance(), &CoreManager::coreStarted,context, + QObject::connect(CoreManager::getInstance(), &CoreManager::managerInitialized,context, [sipAddress,coreManager, context]() mutable { if(context){ delete context; diff --git a/linphone-app/src/components/core/CoreHandlers.cpp b/linphone-app/src/components/core/CoreHandlers.cpp index 5ecb295c7..2718c1f01 100644 --- a/linphone-app/src/components/core/CoreHandlers.cpp +++ b/linphone-app/src/components/core/CoreHandlers.cpp @@ -50,36 +50,13 @@ void scheduleFunctionInApp (function func) { // ----------------------------------------------------------------------------- CoreHandlers::CoreHandlers (CoreManager *coreManager) { - mCoreStartedLock = new QMutex(); - QObject::connect(coreManager, &CoreManager::coreCreated, this, &CoreHandlers::handleCoreCreated); + Q_UNUSED(coreManager) } CoreHandlers::~CoreHandlers () { - delete mCoreStartedLock; - mCoreStartedLock = nullptr; } // ----------------------------------------------------------------------------- - -void CoreHandlers::handleCoreCreated () { - mCoreStartedLock->lock(); - - Q_ASSERT(mCoreCreated == false); - mCoreCreated = true; - notifyCoreStarted(); - mCoreStartedLock->unlock(); -} - -void CoreHandlers::notifyCoreStarted () { - if (mCoreCreated && mCoreStarted) - scheduleFunctionInApp([this] { - qInfo() << QStringLiteral("Core started."); - emit coreStarted(); - }); -} - -// ----------------------------------------------------------------------------- - void CoreHandlers::onAuthenticationRequested ( const shared_ptr & core, const shared_ptr &authInfo, @@ -136,22 +113,23 @@ void CoreHandlers::onDtmfReceived( const std::shared_ptr & lc, const std::shared_ptr & call, int dtmf) { + Q_UNUSED(lc) + Q_UNUSED(call) CoreManager::getInstance()->getCore()->playDtmf((char)dtmf, CallModel::DtmfSoundDelay); } void CoreHandlers::onGlobalStateChanged ( - const shared_ptr &, + const shared_ptr &core, linphone::GlobalState gstate, - const string & + const string & message ) { - if (gstate == linphone::GlobalState::On) { - mCoreStartedLock->lock(); - - Q_ASSERT(mCoreStarted == false); - mCoreStarted = true; - notifyCoreStarted(); - - mCoreStartedLock->unlock(); - } + Q_UNUSED(core) + Q_UNUSED(message) + if( gstate == linphone::GlobalState::On) + emit coreStarted(); + else if( gstate == linphone::GlobalState::Off) + emit coreStopped(); + else if( gstate == linphone::GlobalState::Startup) + emit coreStarting(); } void CoreHandlers::onIsComposingReceived ( @@ -256,6 +234,7 @@ void CoreHandlers::onTransferStateChanged ( case linphone::Call::State::Paused: case linphone::Call::State::PausedByRemote: case linphone::Call::State::Pausing: + case linphone::Call::State::PushIncomingReceived: case linphone::Call::State::Referred: case linphone::Call::State::Released: case linphone::Call::State::Resuming: diff --git a/linphone-app/src/components/core/CoreHandlers.hpp b/linphone-app/src/components/core/CoreHandlers.hpp index b08c95913..259c1e1bf 100644 --- a/linphone-app/src/components/core/CoreHandlers.hpp +++ b/linphone-app/src/components/core/CoreHandlers.hpp @@ -45,7 +45,9 @@ signals: void callTransferFailed (const std::shared_ptr &call); void callTransferSucceeded (const std::shared_ptr &call); void callCreated(const std::shared_ptr & call); + void coreStarting(); void coreStarted (); + void coreStopped (); void isComposingChanged (const std::shared_ptr &chatRoom); void logsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info); void messageReceived (const std::shared_ptr &message); @@ -54,8 +56,6 @@ signals: void ecCalibrationResult(linphone::EcCalibratorStatus status, int delayMs); private: - void handleCoreCreated (); - void notifyCoreStarted (); // --------------------------------------------------------------------------- // Linphone callbacks. @@ -165,11 +165,6 @@ private: ) override; // --------------------------------------------------------------------------- - - bool mCoreCreated = false; - bool mCoreStarted = false; - - QMutex *mCoreStartedLock = nullptr; }; #endif // CORE_HANDLERS_H_ diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 5ccda1a7b..a39d54dc1 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -72,43 +72,39 @@ CoreManager *CoreManager::mInstance; CoreManager::CoreManager (QObject *parent, const QString &configPath) : QObject(parent), mHandlers(make_shared(this)) { - QTimer * delayedCreationTimer = new QTimer(); - delayedCreationTimer->setSingleShot(true); - QObject::connect(delayedCreationTimer, &QTimer::timeout, this , [configPath, this, delayedCreationTimer]{ - delayedCreationTimer->deleteLater(); - createLinphoneCore(configPath); - qInfo() << QStringLiteral("Core created. Enable iterate."); - mInstance->mCbsTimer->start(); - std::shared_ptr h = mInstance->getHandlers();// Protect handler as we will enter its function where it can be deleted (like while restarting) - emit mInstance->coreCreated(); - }); - + mCore = nullptr; CoreHandlers *coreHandlers = mHandlers.get(); - - QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, [] { - // Do not change this order. :) (Or pray.) - mInstance->mCallsListModel = new CallsListModel(mInstance); - mInstance->mContactsListModel = new ContactsListModel(mInstance); - mInstance->mAccountSettingsModel = new AccountSettingsModel(mInstance); - mInstance->mSettingsModel = new SettingsModel(mInstance); - mInstance->mSipAddressesModel = new SipAddressesModel(mInstance); - EventCountNotifier *eventCountNotifier = new EventCountNotifier(mInstance); - eventCountNotifier->updateUnreadMessageCount(); - QObject::connect(eventCountNotifier, &EventCountNotifier::eventCountChanged, - mInstance, &CoreManager::eventCountChanged - ); - mInstance->mEventCountNotifier = eventCountNotifier; - mInstance->migrate(); - mInstance->mStarted = true; - emit mInstance->coreStarted(); - }); - + QObject::connect(coreHandlers, &CoreHandlers::coreStarting, this, &CoreManager::startIterate, Qt::QueuedConnection); + QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, &CoreManager::initManager, Qt::QueuedConnection); + QObject::connect(coreHandlers, &CoreHandlers::coreStopped, this, &CoreManager::stopIterate, Qt::QueuedConnection); QObject::connect(coreHandlers, &CoreHandlers::logsUploadStateChanged, this, &CoreManager::handleLogsUploadStateChanged); - delayedCreationTimer->start(CbsCallInterval); + + createLinphoneCore(configPath); +} + +CoreManager::~CoreManager(){ + mCore->removeListener(mHandlers); + mHandlers = nullptr;// Call destructor + mCore = nullptr;// Call destructor } // ----------------------------------------------------------------------------- +void CoreManager::initManager(){ + mCallsListModel = new CallsListModel(this); + mContactsListModel = new ContactsListModel(this); + mAccountSettingsModel = new AccountSettingsModel(this); + mSettingsModel = new SettingsModel(this); + mSipAddressesModel = new SipAddressesModel(this); + mEventCountNotifier = new EventCountNotifier(this); + mEventCountNotifier->updateUnreadMessageCount(); + QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged); + migrate(); + mStarted = true; + qInfo() << QStringLiteral("Core created. Enable iterate."); + emit managerInitialized(); +} + shared_ptr CoreManager::getChatModel (const QString &peerAddress, const QString &localAddress) { if (peerAddress.isEmpty() || localAddress.isEmpty()) return nullptr; @@ -161,13 +157,7 @@ HistoryModel* CoreManager::getHistoryModel(){ void CoreManager::init (QObject *parent, const QString &configPath) { if (mInstance) return; - mInstance = new CoreManager(parent, configPath); - - QTimer *timer = mInstance->mCbsTimer = new QTimer(mInstance); - timer->setInterval(CbsCallInterval); - - QObject::connect(timer, &QTimer::timeout, mInstance, &CoreManager::iterate); } void CoreManager::uninit () { @@ -176,8 +166,11 @@ void CoreManager::uninit () { mInstance = nullptr; qInfo() << "Linphone Core is destroyed"; }); - mInstance->mCbsTimer->stop(); - mInstance->deleteLater();// Ensure to take time to delete the instance + QObject::connect(mInstance->getHandlers().get(), &CoreHandlers::coreStopped, mInstance, &QObject::deleteLater); + + mInstance->lockVideoRender();// Stop do iterations. We have to protect GUI. + mInstance->mCore->stop(); + mInstance->unlockVideoRender(); QTest::qWaitFor([&]() {return mInstance == nullptr;},10000); if( mInstance){ qWarning() << "Linphone Core couldn't destroy in time. It may lead to have multiple session of Linphone Core"; @@ -338,12 +331,27 @@ int CoreManager::getMissedCallCount(const QString &peerAddress, const QString &l int CoreManager::getMissedCallCountFromLocal( const QString &localAddress)const{ return mEventCountNotifier ? mEventCountNotifier->getMissedCallCountFromLocal(localAddress) : 0; } + // ----------------------------------------------------------------------------- +void CoreManager::startIterate(){ + mCbsTimer = new QTimer(this); + mCbsTimer->setInterval(CbsCallInterval); + QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate); + mCbsTimer->start(); +} + +void CoreManager::stopIterate(){ + mCbsTimer->stop(); + mCbsTimer->deleteLater();// allow the timer to continue its stuff + mCbsTimer = nullptr; +} + void CoreManager::iterate () { - mInstance->lockVideoRender(); - mCore->iterate(); - mInstance->unlockVideoRender(); + lockVideoRender(); + if(mCore) + mCore->iterate(); + unlockVideoRender(); } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/core/CoreManager.hpp b/linphone-app/src/components/core/CoreManager.hpp index 8f65d3c89..d6e040c9d 100644 --- a/linphone-app/src/components/core/CoreManager.hpp +++ b/linphone-app/src/components/core/CoreManager.hpp @@ -137,9 +137,13 @@ public: static bool isInstanciated(){return mInstance!=nullptr;} +public slots: + void initManager(); + void startIterate(); + void stopIterate(); + signals: - void coreCreated (); - void coreStarted (); + void managerInitialized (); void chatModelCreated (const std::shared_ptr &chatModel); void historyModelCreated (HistoryModel *historyModel); @@ -150,6 +154,7 @@ signals: private: CoreManager (QObject *parent, const QString &configPath); + ~CoreManager (); void setDatabasesPaths (); void setOtherPaths (); diff --git a/linphone-app/ui/views/App/Main/MainWindow.qml b/linphone-app/ui/views/App/Main/MainWindow.qml index cba397da8..de88c2123 100644 --- a/linphone-app/ui/views/App/Main/MainWindow.qml +++ b/linphone-app/ui/views/App/Main/MainWindow.qml @@ -51,7 +51,7 @@ ApplicationWindow { Connections { target: CoreManager - onCoreStarted: mainLoader.active = true + onManagerInitialized: mainLoader.active = true } Shortcut {