diff --git a/linphone-app/src/components/core/CoreManagerGUI.cpp b/linphone-app/src/gui/core/CoreManagerGUI.cpp
similarity index 100%
rename from linphone-app/src/components/core/CoreManagerGUI.cpp
rename to linphone-app/src/gui/core/CoreManagerGUI.cpp
diff --git a/linphone-app/src/components/core/CoreManagerGUI.hpp b/linphone-app/src/gui/core/CoreManagerGUI.hpp
similarity index 100%
rename from linphone-app/src/components/core/CoreManagerGUI.hpp
rename to linphone-app/src/gui/core/CoreManagerGUI.hpp
diff --git a/linphone-app/src/linphone/core/Core.cpp b/linphone-app/src/linphone/core/Core.cpp
new file mode 100644
index 000000000..a8bdab338
--- /dev/null
+++ b/linphone-app/src/linphone/core/Core.cpp
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "config.h"
+
+#include "app/paths/Paths.hpp"
+#include "components/calls/CallsListModel.hpp"
+#include "components/chat/ChatModel.hpp"
+#include "components/chat-room/ChatRoomModel.hpp"
+#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"
+#include "components/settings/AccountSettingsModel.hpp"
+#include "components/settings/SettingsModel.hpp"
+#include "components/sip-addresses/SipAddressesModel.hpp"
+#include "components/timeline/TimelineListModel.hpp"
+
+#include "utils/Utils.hpp"
+#include "utils/Constants.hpp"
+
+#if defined(Q_OS_MACOS)
+#include "event-count-notifier/EventCountNotifierMacOs.hpp"
+#else
+#include "event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
+#endif // if defined(Q_OS_MACOS)
+
+#include "CoreHandlers.hpp"
+#include "CoreManager.hpp"
+#include
+
+#include
+#include "components/linphoneObject/LinphoneThread.hpp"
+
+// =============================================================================
+
+using namespace std;
+
+// -----------------------------------------------------------------------------
+
+CoreManager *CoreManager::mInstance=nullptr;
+CoreManagerGUI *CoreManager::mInstanceGUI=nullptr;
+QSharedPointer CoreManager::gLinphoneThread = nullptr;
+
+
+void Core::connectTo(CoreListener * listener){
+ //connect(listener, &CoreListener::accountRegistrationStateChanged, this, &Core::onAccountRegistrationStateChanged);
+ connect(listener, &CoreListener::authenticationRequested, this, &Core::onAuthenticationRequested);
+ connect(listener, &CoreListener::callEncryptionChanged, this, &Core::onCallEncryptionChanged);
+ connect(listener, &CoreListener::callLogUpdated, this, &Core::onCallLogUpdated);
+ connect(listener, &CoreListener::callStateChanged, this, &Core::onCallStateChanged);
+ connect(listener, &CoreListener::callStatsUpdated, this, &Core::onCallStatsUpdated);
+ connect(listener, &CoreListener::callCreated, this, &Core::onCallCreated);
+ connect(listener, &CoreListener::chatRoomStateChanged, this, &Core::onChatRoomStateChanged);
+ connect(listener, &CoreListener::configuringStatus, this, &Core::onConfiguringStatus);
+ connect(listener, &CoreListener::dtmfReceived, this, &Core::onDtmfReceived);
+ connect(listener, &CoreListener::globalStateChanged, this, &Core::onGlobalStateChanged);
+ connect(listener, &CoreListener::isComposingReceived, this, &Core::onIsComposingReceived);
+ connect(listener, &CoreListener::logCollectionUploadStateChanged, this, &Core::onLogCollectionUploadStateChanged);
+ connect(listener, &CoreListener::logCollectionUploadProgressIndication, this, &Core::onLogCollectionUploadProgressIndication);
+ connect(listener, &CoreListener::messageReceived, this, &Core::onMessageReceived);
+ connect(listener, &CoreListener::messagesReceived, this, &Core::onMessagesReceived);
+ connect(listener, &CoreListener::notifyPresenceReceivedForUriOrTel, this, &Core::onNotifyPresenceReceivedForUriOrTel);
+ connect(listener, &CoreListener::notifyPresenceReceived, this, &Core::onNotifyPresenceReceived);
+ connect(listener, &CoreListener::qrcodeFound, this, &Core::onQrcodeFound);
+ connect(listener, &CoreListener::transferStateChanged, this, &Core::onTransferStateChanged);
+ connect(listener, &CoreListener::versionUpdateCheckResultReceived, this, &Core::onVersionUpdateCheckResultReceived);
+ connect(listener, &CoreListener::ecCalibrationResult, this, &Core::onEcCalibrationResult);
+ connect(listener, &CoreListener::conferenceInfoReceived, this, &Core::onConferenceInfoReceived);
+}
+
+Core::Core(QObject *parent, const QString &configPath) :
+ QObject(parent), mHandlers(make_shared(this)) {
+ mCore = nullptr;
+ mLastRemoteProvisioningState = linphone::ConfiguringState::Skipped;
+ CoreHandlers *coreHandlers = mHandlers.get();
+ QObject::connect(coreHandlers, &CoreHandlers::coreStarting, this, &CoreManager::startIterate, Qt::QueuedConnection);
+ QObject::connect(coreHandlers, &CoreHandlers::setLastRemoteProvisioningState, this, &CoreManager::setLastRemoteProvisioningState);
+ QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, &CoreManager::initCoreManager, Qt::QueuedConnection);
+ QObject::connect(coreHandlers, &CoreHandlers::coreStopped, this, &CoreManager::stopIterate, Qt::QueuedConnection);
+ QObject::connect(coreHandlers, &CoreHandlers::logsUploadStateChanged, this, &CoreManager::handleLogsUploadStateChanged);
+ QObject::connect(coreHandlers, &CoreHandlers::callLogUpdated, this, &CoreManager::callLogsCountChanged);
+
+ QTimer::singleShot(10, [this, configPath](){// Delay the creation in order to have the CoreManager instance set before
+ createLinphoneCore(configPath);
+ });
+}
+
+CoreManager::~CoreManager(){
+ mCore->removeListener(mHandlers);
+ mHandlers = nullptr;// Ordering Call destructor just to be sure (removeListener should be enough)
+ mCore = nullptr;
+}
+
+// -----------------------------------------------------------------------------
+
+void CoreManager::initCoreManager(){
+ qInfo() << "Init CoreManager";
+ mAccountSettingsModel = new AccountSettingsModel(this);
+ mSettingsModel = new SettingsModel(this);
+ mCallsListModel = new CallsListModel(this);
+ mChatModel = new ChatModel(this);
+ mContactsListModel = new ContactsListModel(this);
+ mContactsImporterListModel = new ContactsImporterListModel(this);
+ mLdapListModel = new LdapListModel(this);
+ mSipAddressesModel = new SipAddressesModel(this);
+ mEventCountNotifier = new EventCountNotifier(this);
+ mTimelineListModel = new TimelineListModel(this);
+ mEventCountNotifier->updateUnreadMessageCount();
+ QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged);
+ migrate();
+ mStarted = true;
+
+ qInfo() << QStringLiteral("CoreManager initialized");
+ emit coreManagerInitialized();
+}
+
+AbstractEventCountNotifier * CoreManager::getEventCountNotifier(){
+ return mEventCountNotifier;
+}
+
+CoreManager *CoreManager::getInstance (){
+ return mInstance;
+}
+
+CoreManagerGUI *CoreManager::getInstanceGUI (){
+ return mInstanceGUI;
+}
+
+
+HistoryModel* CoreManager::getHistoryModel(){
+ if(!mHistoryModel){
+ mHistoryModel = new HistoryModel(this);
+ emit historyModelCreated(mHistoryModel);
+ }
+ return mHistoryModel;
+}
+
+RecorderManager* CoreManager::getRecorderManager(){
+ if(!mRecorderManager){
+ mRecorderManager = new RecorderManager(this);
+ emit recorderManagerCreated(mRecorderManager);
+ }
+ return mRecorderManager;
+}
+// -----------------------------------------------------------------------------
+
+void CoreManager::init (QObject *parent, const QString &configPath) {
+ if (mInstance)
+ return;
+ 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 () {
+ if (mInstance) {
+ mInstance->stopIterate();
+ auto core = mInstance->mCore;
+ mInstance->lockVideoRender();// Stop do iterations. We have to protect GUI.
+ 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.";
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+VcardModel *CoreManager::createDetachedVcardModel () const {
+ VcardModel *vcardModel = new VcardModel(linphone::Factory::get()->createVcard(), false);
+ qInfo() << QStringLiteral("Create detached vcard:") << vcardModel;
+ return vcardModel;
+}
+
+void CoreManager::forceRefreshRegisters () {
+ Q_CHECK_PTR(mCore);
+
+ qInfo() << QStringLiteral("Refresh registers.");
+ mCore->refreshRegisters();
+}
+void CoreManager::updateUnreadMessageCount(){
+ mEventCountNotifier->updateUnreadMessageCount();
+}
+
+void CoreManager::stateChanged(Qt::ApplicationState pState){
+ if(mCbsTimer){
+ if(pState == Qt::ApplicationActive)
+ mCbsTimer->setInterval( Constants::CbsCallInterval);
+ else
+ mCbsTimer->setInterval( Constants::CbsCallInterval * 2);// Reduce a little processes
+ }
+}
+// -----------------------------------------------------------------------------
+
+void CoreManager::sendLogs () const {
+ Q_CHECK_PTR(mCore);
+
+ qInfo() << QStringLiteral("Send logs to: `%1` from `%2`.")
+ .arg(Utils::coreStringToAppString(mCore->getLogCollectionUploadServerUrl()))
+ .arg(Utils::coreStringToAppString(mCore->getLogCollectionPath()));
+ mCore->uploadLogCollection();
+}
+
+void CoreManager::cleanLogs () const {
+ Q_CHECK_PTR(mCore);
+
+ mCore->resetLogCollection();
+}
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+
+#define SET_DATABASE_PATH(DATABASE, PATH) \
+ do { \
+ qInfo() << QStringLiteral("Set `%1` path: `%2`") \
+ .arg( # DATABASE) \
+ .arg(Utils::coreStringToAppString(PATH)); \
+ mCore->set ## DATABASE ## DatabasePath(PATH); \
+ } while (0);
+
+void CoreManager::setDatabasesPaths () {
+ SET_DATABASE_PATH(Friends, Paths::getFriendsListFilePath());
+ linphone_core_set_call_logs_database_path(mCore->cPtr(), Paths::getCallHistoryFilePath().c_str());// Setting the message database let SDK to migrate data
+ if(QFile::exists(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()))){
+ linphone_core_set_chat_database_path(mCore->cPtr(), Paths::getMessageHistoryFilePath().c_str());// Setting the message database let SDK to migrate data
+ QFile::remove(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()));
+ }
+}
+
+#undef SET_DATABASE_PATH
+
+// -----------------------------------------------------------------------------
+
+void CoreManager::setOtherPaths () {
+ if (mCore->getZrtpSecretsFile().empty() || !Paths::filePathExists(mCore->getZrtpSecretsFile(), true))
+ mCore->setZrtpSecretsFile(Paths::getZrtpSecretsFilePath());// Use application path if Linphone default is not available
+ qInfo() << "Using ZrtpSecrets path : " << QString::fromStdString(mCore->getZrtpSecretsFile());
+ if (mCore->getUserCertificatesPath().empty() || !Paths::filePathExists(mCore->getUserCertificatesPath(), true))
+ mCore->setUserCertificatesPath(Paths::getUserCertificatesDirPath());// Use application path if Linphone default is not available
+ qInfo() << "Using UserCertificate path : " << QString::fromStdString(mCore->getUserCertificatesPath());
+ if (mCore->getRootCa().empty() || !Paths::filePathExists(mCore->getRootCa()))
+ mCore->setRootCa(Paths::getRootCaFilePath());// Use application path if Linphone default is not available
+ qInfo() << "Using RootCa path : " << QString::fromStdString(mCore->getRootCa());
+}
+
+void CoreManager::setResourcesPaths () {
+ shared_ptr factory = linphone::Factory::get();
+ factory->setMspluginsDir(Paths::getPackageMsPluginsDirPath());
+ factory->setTopResourcesDir(Paths::getPackageTopDirPath());
+ factory->setSoundResourcesDir(Paths::getPackageSoundsResourcesDirPath());
+ factory->setDataResourcesDir(Paths::getPackageDataDirPath());
+ factory->setDataDir(Paths::getAppLocalDirPath());
+ factory->setDownloadDir(Paths::getDownloadDirPath());
+ factory->setConfigDir(Paths::getConfigDirPath(true));
+}
+
+// -----------------------------------------------------------------------------
+
+void CoreManager::createLinphoneCore (const QString &configPath) {
+ qInfo() << QStringLiteral("Launch async core creation.");
+
+ // Migration of configuration and database files from GTK version of Linphone.
+ Paths::migrate();
+ setResourcesPaths();
+ mCore = linphone::Factory::get()->createCore(
+ Paths::getConfigFilePath(configPath),
+ Paths::getFactoryConfigFilePath(),
+ nullptr
+ );
+ // Enable LIME on your core to use encryption.
+ mCore->enableLimeX3Dh(mCore->limeX3DhAvailable());
+ // Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room
+
+ mCore->addListener(mHandlers);
+ mCore->setVideoDisplayFilter("MSQOGL");
+ mCore->usePreviewWindow(true);
+ mCore->enableVideoPreview(false);
+ // Force capture/display.
+ // Useful if the app was built without video support.
+ // (The capture/display attributes are reset by the core in this case.)
+ shared_ptr config = mCore->getConfig();
+ if (mCore->videoSupported()) {
+ config->setInt("video", "capture", 1);
+ config->setInt("video", "display", 1);
+ }
+ QString userAgent = Utils::computeUserAgent(config);
+ mCore->setUserAgent(Utils::appStringToCoreString(userAgent), mCore->getVersion());
+ mCore->start();
+ setDatabasesPaths();
+ setOtherPaths();
+ mCore->enableFriendListSubscription(true);
+ mCore->enableRecordAware(true);
+ if(mCore->getAccountCreatorUrl() == "")
+ mCore->setAccountCreatorUrl(Constants::DefaultFlexiAPIURL);
+}
+
+void CoreManager::updateUserAgent(){
+ mCore->setUserAgent(Utils::appStringToCoreString(Utils::computeUserAgent(mCore->getConfig())), mCore->getVersion());
+ forceRefreshRegisters(); // After setting a new device name, REGISTER need to take account it.
+}
+
+void CoreManager::handleChatRoomCreated(const QSharedPointer &chatRoomModel){
+ emit chatRoomModelCreated(chatRoomModel);
+}
+
+void CoreManager::migrate () {
+ shared_ptr config = mCore->getConfig();
+ auto oldLimeServerUrl = mCore->getLimeX3DhServerUrl();// core url is deprecated : If core url exists, it must be copied to all linphone accounts.
+ int rcVersion = config->getInt(SettingsModel::UiSection, Constants::RcVersionName, 0);
+ if (oldLimeServerUrl.empty() && rcVersion == Constants::RcVersionCurrent)
+ return;
+ if (rcVersion > Constants::RcVersionCurrent) {
+ qWarning() << QStringLiteral("RC file version (%1) is more recent than app rc file version (%2)!!!")
+ .arg(rcVersion).arg(Constants::RcVersionCurrent);
+ return;
+ }
+
+ qInfo() << QStringLiteral("Migrate from old rc file (%1 to %2).")
+ .arg(rcVersion).arg(Constants::RcVersionCurrent);
+
+ bool setLimeServerUrl = false;
+ for(const auto &account : getAccountList()){
+ auto params = account->getParams();
+ if( params->getDomain() == Constants::LinphoneDomain) {
+ auto newParams = params->clone();
+ QString accountIdentity = (newParams->getIdentityAddress() ? newParams->getIdentityAddress()->asString().c_str() : "no-identity");
+ if( rcVersion < 1) {
+ newParams->setContactParameters(Constants::DefaultContactParameters);
+ newParams->setExpires(Constants::DefaultExpires);
+ qInfo() << "Migrating" << accountIdentity << "for version 1. contact parameters =" << Constants::DefaultContactParameters << ", expires =" << Constants::DefaultExpires;
+ }
+ if( rcVersion < 2) {
+ bool exists = newParams->getConferenceFactoryUri() != "";
+ setLimeServerUrl = true;
+ if(!exists )
+ newParams->setConferenceFactoryUri(Constants::DefaultConferenceURI);
+ qInfo() << "Migrating" << accountIdentity << "for version 2. Conference factory URI" << (exists ? std::string("unchanged") : std::string("= ") +Constants::DefaultConferenceURI).c_str();
+ // note: using std::string.c_str() to avoid having double quotes in qInfo()
+ }
+ if( rcVersion < 3){
+ newParams->enableCpimInBasicChatRoom(true);
+ qInfo() << "Migrating" << accountIdentity << "for version 3. Enable Cpim in basic chat rooms";
+ }
+ if( rcVersion < 4){
+ newParams->enableRtpBundle(true);
+ qInfo() << "Migrating" << accountIdentity << "for version 4. Enable RTP bundle mode";
+ }
+ if( rcVersion < 5) {
+ bool exists = !!newParams->getAudioVideoConferenceFactoryAddress();
+ setLimeServerUrl = true;
+ if( !exists)
+ newParams->setAudioVideoConferenceFactoryAddress(Utils::interpretUrl(Constants::DefaultVideoConferenceURI));
+ qInfo() << "Migrating" << accountIdentity << "for version 5. Video conference factory URI" << (exists ? std::string("unchanged") : std::string("= ") +Constants::DefaultVideoConferenceURI).c_str();
+ // note: using std::string.c_str() to avoid having double quotes in qInfo()
+ }
+
+ if(!oldLimeServerUrl.empty())
+ newParams->setLimeServerUrl(oldLimeServerUrl);
+ else if( setLimeServerUrl)
+ newParams->setLimeServerUrl(Constants::DefaultLimeServerURL);
+
+ account->setParams(newParams);
+ }
+ }
+ if( !oldLimeServerUrl.empty()) {
+ mCore->setLimeX3DhServerUrl("");
+ mCore->enableLimeX3Dh(true);
+ }else if(setLimeServerUrl) {
+ mCore->enableLimeX3Dh(true);
+ }
+
+ config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
+}
+
+// -----------------------------------------------------------------------------
+
+QString CoreManager::getVersion () const {
+ return Utils::coreStringToAppString(mCore->getVersion());
+}
+
+// -----------------------------------------------------------------------------
+
+int CoreManager::getEventCount () const {
+ return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
+}
+int CoreManager::getCallLogsCount() const{
+ return mCore->getCallLogs().size();
+}
+int CoreManager::getMissedCallCount(const QString &peerAddress, const QString &localAddress)const{
+ return mEventCountNotifier ? mEventCountNotifier->getMissedCallCount(peerAddress, localAddress) : 0;
+}
+int CoreManager::getMissedCallCountFromLocal( const QString &localAddress)const{
+ return mEventCountNotifier ? mEventCountNotifier->getMissedCallCountFromLocal(localAddress) : 0;
+}
+
+std::list> CoreManager::getAccountList()const{
+ std::list> accounts;
+ for(auto account : mCore->getAccountList())
+ if( account->getCustomParam("hidden") != "1")
+ accounts.push_back(account);
+ return accounts;
+}
+// -----------------------------------------------------------------------------
+
+void CoreManager::startIterate(){
+ mCbsTimer = new QTimer();
+ mCbsTimer->setInterval(Constants::CbsCallInterval);
+ QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate, Qt::DirectConnection);
+ qInfo() << QStringLiteral("Start iterate");
+ emit gLinphoneThread->startT(mCbsTimer);
+ //gLinphoneThread->test(mCbsTimer);
+ //mCbsTimer->start();
+}
+
+void CoreManager::stopIterate(){
+ qInfo() << QStringLiteral("Stop iterate");
+ emit gLinphoneThread->stopT(mCbsTimer);
+ //mCbsTimer->stop();
+ mCbsTimer->deleteLater();// allow the timer to continue its stuff
+ mCbsTimer = nullptr;
+}
+
+void CoreManager::iterate () {
+ lockVideoRender();
+ if(mCore)
+ mCore->iterate();
+ unlockVideoRender();
+}
+
+// -----------------------------------------------------------------------------
+
+void CoreManager::handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const string &info) {
+ switch (state) {
+ case linphone::Core::LogCollectionUploadState::InProgress:
+ break;
+
+ case linphone::Core::LogCollectionUploadState::Delivered:
+ case linphone::Core::LogCollectionUploadState::NotDelivered:
+ emit logsUploaded(Utils::coreStringToAppString(info));
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+QString CoreManager::getDownloadUrl () {
+ return Constants::DownloadUrl;
+}
+
+void CoreManager::setLastRemoteProvisioningState(const linphone::ConfiguringState& state){
+ mLastRemoteProvisioningState = state;
+}
+
+bool CoreManager::isLastRemoteProvisioningGood(){
+ return mLastRemoteProvisioningState != linphone::ConfiguringState::Failed;
+}
+
+QString CoreManager::getUserAgent()const {
+ if(mCore)
+ return Utils::coreStringToAppString(mCore->getUserAgent());
+ else
+ return EXECUTABLE_NAME " Desktop";// Just in case
+}
diff --git a/linphone-app/src/linphone/core/Core.hpp b/linphone-app/src/linphone/core/Core.hpp
new file mode 100644
index 000000000..3dba05ebd
--- /dev/null
+++ b/linphone-app/src/linphone/core/Core.hpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#ifndef CORE_H_
+#define CORE_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+// =============================================================================
+
+class QTimer;
+
+class AbstractEventCountNotifier;
+class AccountSettingsModel;
+class CallsListModel;
+class ChatModel;
+class ChatRoomModel;
+class ContactsListModel;
+class ContactsImporterListModel;
+class CoreHandlers;
+class CoreManagerGUI;
+class EventCountNotifier;
+class HistoryModel;
+class LdapListModel;
+class RecorderManager;
+class SettingsModel;
+class SipAddressesModel;
+class VcardModel;
+class TimelineListModel;
+
+class LinphoneThread;
+
+
+class CoreManager : public QObject {
+ Q_OBJECT
+public:
+
+ std::shared_ptr getCore () {
+ return mCore;
+ }
+
+
+ QString getVersion () const;
+ int getEventCount () const;
+ static QString getDownloadUrl ();
+
+ // ---------------------------------------------------------------------------
+ // Initialization.
+ // ---------------------------------------------------------------------------
+
+ static void init (QObject *parent, const QString &configPath);
+ static void uninit ();
+
+ // ---------------------------------------------------------------------------
+
+ // Must be used in a qml scene.
+ // Warning: The ownership of `VcardModel` is `QQmlEngine::JavaScriptOwnership` by default.
+ Q_INVOKABLE VcardModel *createDetachedVcardModel () const;
+
+ Q_INVOKABLE void forceRefreshRegisters ();
+ void updateUnreadMessageCount();
+ void stateChanged(Qt::ApplicationState pState);
+
+ Q_INVOKABLE void sendLogs () const;
+ Q_INVOKABLE void cleanLogs () const;
+
+ int getCallLogsCount() const;
+ int getMissedCallCount(const QString &peerAddress, const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines)
+ int getMissedCallCountFromLocal(const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines)
+
+ std::list> getAccountList()const;
+
+ static bool isInstanciated(){return mInstance!=nullptr;}
+
+ Q_INVOKABLE bool isLastRemoteProvisioningGood();
+ Q_INVOKABLE QString getUserAgent()const;
+ void updateUserAgent();
+
+public slots:
+ void initCoreManager();
+ void startIterate();
+ void stopIterate();
+ void setLastRemoteProvisioningState(const linphone::ConfiguringState& state);
+ void createLinphoneCore (const QString &configPath);// In order to delay creation
+ void handleChatRoomCreated(const QSharedPointer &chatRoomModel);
+
+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();
+
+private:
+ CoreManager (QObject *parent, const QString &configPath);
+ ~CoreManager ();
+
+ void setDatabasesPaths ();
+ void setOtherPaths ();
+ void setResourcesPaths ();
+
+ void migrate ();
+
+
+
+ void iterate ();
+
+ void handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info);
+
+ void connectTo(CoreListener * listener);
+ std::shared_ptr mCore;
+ std::shared_ptr mListener;
+
+ bool mStarted = false;
+};
+
+#endif // CORE_MANAGER_H_
diff --git a/linphone-app/src/linphone/core/CoreHandlers.cpp b/linphone-app/src/linphone/core/CoreHandlers.cpp
new file mode 100644
index 000000000..bca08f971
--- /dev/null
+++ b/linphone-app/src/linphone/core/CoreHandlers.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "app/App.hpp"
+#include "components/call/CallModel.hpp"
+#include "components/chat-events/ChatMessageModel.hpp"
+#include "components/contact/ContactModel.hpp"
+#include "components/notifier/Notifier.hpp"
+#include "components/settings/AccountSettingsModel.hpp"
+#include "components/settings/SettingsModel.hpp"
+#include "components/timeline/TimelineListModel.hpp"
+#include "utils/Utils.hpp"
+
+#include "CoreHandlers.hpp"
+#include "CoreManager.hpp"
+
+// =============================================================================
+
+using namespace std;
+
+// -----------------------------------------------------------------------------
+
+CoreHandlers::CoreHandlers (CoreManager *coreManager) {
+ Q_UNUSED(coreManager)
+}
+
+CoreHandlers::~CoreHandlers () {
+}
+
+// -----------------------------------------------------------------------------
+void CoreHandlers::onAccountRegistrationStateChanged (
+ const shared_ptr &,
+ const shared_ptr &account,
+ linphone::RegistrationState state,
+ const string &
+ ) {
+ emit registrationStateChanged(account, state);
+}
+
+void CoreHandlers::onAuthenticationRequested (
+ const shared_ptr & core,
+ const shared_ptr &authInfo,
+ linphone::AuthMethod method
+ ) {
+ Q_UNUSED(method)
+ if( authInfo ) {
+ auto accounts = CoreManager::getInstance()->getAccountList();
+ auto itAccount = accounts.begin() ;
+ std::string username = authInfo->getUsername();
+ std::string domain = authInfo->getDomain();
+ while(itAccount != accounts.end()) {
+ auto contact = (*itAccount)->getParams()->getIdentityAddress();
+ if( contact && contact->getUsername() == username && contact->getDomain() == domain) {
+ emit authenticationRequested(authInfo);// Send authentification request only if an account still exists
+ return;
+ }else
+ ++itAccount;
+ }
+ }
+}
+
+void CoreHandlers::onCallEncryptionChanged (
+ const shared_ptr &,
+ const shared_ptr &call,
+ bool,
+ const string &
+ ) {
+ emit callEncryptionChanged(call);
+}
+
+void CoreHandlers::onCallLogUpdated(const std::shared_ptr & core, const std::shared_ptr & callLog){
+ emit callLogUpdated(callLog);
+}
+
+void CoreHandlers::onCallStateChanged (
+ const shared_ptr &,
+ const shared_ptr &call,
+ linphone::Call::State state,
+ const string &
+ ) {
+ emit callStateChanged(call, state);
+
+ SettingsModel *settingsModel = CoreManager::getInstance()->getSettingsModel();
+ if (
+ call->getState() == linphone::Call::State::IncomingReceived && (
+ !settingsModel->getAutoAnswerStatus() ||
+ settingsModel->getAutoAnswerDelay() > 0
+ )
+ )
+ App::getInstance()->getNotifier()->notifyReceivedCall(call);
+}
+
+void CoreHandlers::onCallStatsUpdated (
+ const shared_ptr &,
+ const shared_ptr &call,
+ const shared_ptr &stats
+ ) {
+ call->getData("call-model").updateStats(stats);
+}
+
+void CoreHandlers::onCallCreated(const shared_ptr &,
+ const shared_ptr &call) {
+ emit callCreated(call);
+}
+
+void CoreHandlers::onChatRoomRead(const std::shared_ptr & core, const std::shared_ptr & chatRoom){
+ emit chatRoomRead(chatRoom);
+}
+
+void CoreHandlers::onChatRoomStateChanged(
+ const std::shared_ptr & core,
+ const std::shared_ptr & chatRoom,
+ linphone::ChatRoom::State state
+ ) {
+ if (core->getGlobalState() == linphone::GlobalState::On)
+ emit chatRoomStateChanged(chatRoom, state);
+}
+
+void CoreHandlers::onConfiguringStatus(
+ const std::shared_ptr & core,
+ linphone::ConfiguringState status,
+ const std::string & message){
+ Q_UNUSED(core)
+ emit setLastRemoteProvisioningState(status);
+ if(status == linphone::ConfiguringState::Failed){
+ qWarning() << "Remote provisioning has failed and was removed : "<< QString::fromStdString(message);
+ core->setProvisioningUri("");
+ }
+}
+
+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 &core,
+ linphone::GlobalState gstate,
+ const string & message
+ ) {
+ Q_UNUSED(core)
+ Q_UNUSED(message)
+ switch(gstate){
+ case linphone::GlobalState::On :
+ qInfo() << "Core is running " << QString::fromStdString(message);
+ emit coreStarted();
+ break;
+ case linphone::GlobalState::Off :
+ qInfo() << "Core is stopped " << QString::fromStdString(message);
+ emit coreStopped();
+ break;
+ case linphone::GlobalState::Startup : // Usefull to start core iterations
+ qInfo() << "Core is starting " << QString::fromStdString(message);
+ emit coreStarting();
+ break;
+ default:{}
+ }
+}
+
+void CoreHandlers::onIsComposingReceived (
+ const shared_ptr &,
+ const shared_ptr &room
+ ) {
+ emit isComposingChanged(room);
+}
+
+void CoreHandlers::onLogCollectionUploadStateChanged (
+ const shared_ptr &,
+ linphone::Core::LogCollectionUploadState state,
+ const string &info
+ ) {
+ emit logsUploadStateChanged(state, info);
+}
+
+void CoreHandlers::onLogCollectionUploadProgressIndication (
+ const shared_ptr &,
+ size_t,
+ size_t
+ ) {
+ // TODO;
+}
+
+void CoreHandlers::onMessageReceived (
+ const shared_ptr &core,
+ const shared_ptr &chatRoom,
+ const shared_ptr &message
+ ) {
+ onMessagesReceived(core, chatRoom, std::list>{message});
+}
+
+void CoreHandlers::onMessagesReceived (
+ const shared_ptr &core,
+ const shared_ptr &chatRoom,
+ const std::list> &messages
+ ) {
+ std::list> messagesToSignal;
+ std::list> messagesToNotify;
+ CoreManager *coreManager = CoreManager::getInstance();
+ SettingsModel *settingsModel = coreManager->getSettingsModel();
+ const App *app = App::getInstance();
+ QStringList notNotifyReasons;
+ QSettings appSettings;
+
+ appSettings.beginGroup("chatrooms");
+ for(auto message : messages){
+ if(message){
+ auto chatRoom = message->getChatRoom();
+ auto dbMessage = chatRoom->findMessage(message->getMessageId());
+ auto appdata = ChatMessageModel::AppDataManager(QString::fromStdString(dbMessage->getAppdata()));
+ appdata.mData["receivedTime"] = QString::number(QDateTime::currentMSecsSinceEpoch()/1000);
+ dbMessage->setAppdata(Utils::appStringToCoreString(appdata.toString()));
+ }
+ if( !message || message->isOutgoing() )
+ continue;
+
+ messagesToSignal.push_back(message);
+
+ // 1. Do not notify if chat is not activated.
+ if (chatRoom->getCurrentParams()->getEncryptionBackend() == linphone::ChatRoomEncryptionBackend::None && !settingsModel->getStandardChatEnabled()
+ || chatRoom->getCurrentParams()->getEncryptionBackend() != linphone::ChatRoomEncryptionBackend::None && !settingsModel->getSecureChatEnabled())
+ continue;
+
+ // 2. Do not notify if the chatroom's notification has been deactivated.
+ appSettings.beginGroup(ChatRoomModel::getChatRoomId(chatRoom));
+ if(!appSettings.value("notifications", true).toBool()){
+ appSettings.endGroup();
+ continue;
+ }else{
+ appSettings.endGroup();
+ }
+
+ // 3. Notify with Notification popup.
+ if (coreManager->getSettingsModel()->getChatNotificationsEnabled()
+ && (!app->hasFocus() || !Utils::isMe(chatRoom->getLocalAddress()))
+ && !message->isRead())// On aggregation, the list can contains already displayed messages.
+ messagesToNotify.push_back(message);
+ else{
+ notNotifyReasons.push_back(
+ "NotifEnabled=" + QString::number(coreManager->getSettingsModel()->getChatNotificationsEnabled())
+ +" focus=" +QString::number(app->hasFocus())
+ +" isMe=" +QString::number(Utils::isMe(chatRoom->getLocalAddress()))
+ +" isRead=" +QString::number(message->isRead())
+ );
+ }
+ }
+ if( messagesToSignal.size() > 0)
+ emit messagesReceived(messagesToSignal);
+ if( messagesToNotify.size() > 0)
+ app->getNotifier()->notifyReceivedMessages(messagesToNotify);
+ else if( notNotifyReasons.size() > 0)
+ qInfo() << "Notification received but was not selected to popup. Reasons : \n" << notNotifyReasons.join("\n");
+ // 3. Notify with sound.
+ if( messagesToNotify.size() > 0) {
+ if (!coreManager->getSettingsModel()->getChatNotificationsEnabled() || !settingsModel->getChatNotificationSoundEnabled())
+ return;
+
+ if ( !app->hasFocus() || !CoreManager::getInstance()->getTimelineListModel()->getChatRoomModel(chatRoom, false) )
+ core->playLocal(Utils::appStringToCoreString(settingsModel->getChatNotificationSoundPath()));
+ }
+}
+
+void CoreHandlers::onNotifyPresenceReceivedForUriOrTel (
+ const shared_ptr &,
+ const shared_ptr &,
+ const string &uriOrTel,
+ const shared_ptr &presenceModel
+ ) {
+ emit presenceReceived(Utils::coreStringToAppString(uriOrTel), presenceModel);
+}
+
+void CoreHandlers::onNotifyPresenceReceived (
+ const shared_ptr &,
+ const shared_ptr &linphoneFriend
+ ) {
+ // Ignore friend without vcard because the `contact-model` data doesn't exist.
+ if (linphoneFriend->getVcard() && linphoneFriend->dataExists("contact-model"))
+ linphoneFriend->getData("contact-model").refreshPresence();
+ emit presenceStatusReceived(linphoneFriend);
+}
+
+void CoreHandlers::onQrcodeFound(const std::shared_ptr & core, const std::string & result){
+ emit foundQRCode(result);
+}
+
+void CoreHandlers::onTransferStateChanged (
+ const shared_ptr &,
+ const shared_ptr &call,
+ linphone::Call::State state
+ ) {
+ switch (state) {
+ case linphone::Call::State::EarlyUpdatedByRemote:
+ case linphone::Call::State::EarlyUpdating:
+ case linphone::Call::State::Idle:
+ case linphone::Call::State::IncomingEarlyMedia:
+ case linphone::Call::State::IncomingReceived:
+ case linphone::Call::State::OutgoingEarlyMedia:
+ case linphone::Call::State::OutgoingRinging:
+ 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:
+ case linphone::Call::State::StreamsRunning:
+ case linphone::Call::State::UpdatedByRemote:
+ case linphone::Call::State::Updating:
+ break; // Nothing.
+
+ // 1. Init.
+ case linphone::Call::State::OutgoingInit:
+ qInfo() << QStringLiteral("Call transfer init.");
+ break;
+
+ // 2. In progress.
+ case linphone::Call::State::OutgoingProgress:
+ qInfo() << QStringLiteral("Call transfer in progress.");
+ break;
+
+ // 3. Done.
+ case linphone::Call::State::Connected:
+ qInfo() << QStringLiteral("Call transfer succeeded.");
+ emit callTransferSucceeded(call);
+ break;
+
+ // 4. Error.
+ case linphone::Call::State::End:
+ case linphone::Call::State::Error:
+ qWarning() << QStringLiteral("Call transfer failed.");
+ emit callTransferFailed(call);
+ break;
+ }
+}
+
+void CoreHandlers::onVersionUpdateCheckResultReceived (
+ const shared_ptr &,
+ linphone::VersionUpdateCheckResult result,
+ const string &version,
+ const string &url
+ ) {
+ if (result == linphone::VersionUpdateCheckResult::NewVersionAvailable)
+ App::getInstance()->getNotifier()->notifyNewVersionAvailable(
+ Utils::coreStringToAppString(version),
+ Utils::coreStringToAppString(url)
+ );
+}
+void CoreHandlers::onEcCalibrationResult(
+ const std::shared_ptr &,
+ linphone::EcCalibratorStatus status,
+ int delayMs
+ ) {
+ emit ecCalibrationResult(status, delayMs);
+}
+
+//------------------------------ CONFERENCE INFO
+void CoreHandlers::onConferenceInfoReceived(const std::shared_ptr & core, const std::shared_ptr & conferenceInfo) {
+ qDebug() << "onConferenceInfoReceived: " << conferenceInfo->getUri()->asString().c_str();
+ emit conferenceInfoReceived(conferenceInfo);
+}
diff --git a/linphone-app/src/linphone/core/CoreHandlers.hpp b/linphone-app/src/linphone/core/CoreHandlers.hpp
new file mode 100644
index 000000000..8331a6f4f
--- /dev/null
+++ b/linphone-app/src/linphone/core/CoreHandlers.hpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#ifndef CORE_HANDLERS_H_
+#define CORE_HANDLERS_H_
+
+#include
+#include
+
+// =============================================================================
+
+class CoreManager;
+class QMutex;
+
+class CoreHandlers :
+ public QObject,
+ public linphone::CoreListener {
+ Q_OBJECT
+
+public:
+ CoreHandlers (CoreManager *coreManager);
+ ~CoreHandlers ();
+
+signals:
+ void authenticationRequested (const std::shared_ptr &authInfo);
+ void callEncryptionChanged (const std::shared_ptr &call);
+ void callLogUpdated(const std::shared_ptr &call);
+ void callStateChanged (const std::shared_ptr &call, linphone::Call::State state);
+ void callTransferFailed (const std::shared_ptr &call);
+ void callTransferSucceeded (const std::shared_ptr &call);
+ void callCreated(const std::shared_ptr & call);
+ void chatRoomRead(const std::shared_ptr &chatRoom);
+ void chatRoomStateChanged(const std::shared_ptr &chatRoom,linphone::ChatRoom::State state);
+ void coreStarting();
+ void coreStarted ();
+ void coreStopped ();
+ void isComposingChanged (const std::shared_ptr &chatRoom);
+ void logsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info);
+ void messagesReceived (const std::list> &messages);
+ void presenceReceived (const QString &sipAddress, const std::shared_ptr &presenceModel);
+ void presenceStatusReceived(std::shared_ptr contact);
+ void registrationStateChanged (const std::shared_ptr &account, linphone::RegistrationState state);
+ void ecCalibrationResult(linphone::EcCalibratorStatus status, int delayMs);
+ void setLastRemoteProvisioningState(const linphone::ConfiguringState &state);
+ void conferenceInfoReceived(const std::shared_ptr & conferenceInfo);
+ void foundQRCode(const std::string & result);
+
+private:
+ // ---------------------------------------------------------------------------
+ // Linphone callbacks.
+ // ---------------------------------------------------------------------------
+ void onAccountRegistrationStateChanged(
+ const std::shared_ptr & core,
+ const std::shared_ptr & account,
+ linphone::RegistrationState state,
+ const std::string & message) override;
+
+ void onAuthenticationRequested (
+ const std::shared_ptr &core,
+ const std::shared_ptr &authInfo,
+ linphone::AuthMethod method
+ ) override;
+
+ void onCallEncryptionChanged (
+ const std::shared_ptr &core,
+ const std::shared_ptr &call,
+ bool on,
+ const std::string &authenticationToken
+ ) override;
+
+ void onCallLogUpdated(const std::shared_ptr & core, const std::shared_ptr & callLog) override;
+
+ void onCallStateChanged (
+ const std::shared_ptr &core,
+ const std::shared_ptr &call,
+ linphone::Call::State state,
+ const std::string &message
+ ) override;
+
+ void onCallStatsUpdated (
+ const std::shared_ptr &core,
+ const std::shared_ptr &call,
+ const std::shared_ptr &stats
+ ) override;
+
+ void onCallCreated(
+ const std::shared_ptr & lc,
+ const std::shared_ptr & call
+ ) override;
+
+ void onChatRoomRead(const std::shared_ptr & core, const std::shared_ptr & chatRoom) override;
+
+ void onChatRoomStateChanged(
+ const std::shared_ptr & core,
+ const std::shared_ptr & chatRoom,
+ linphone::ChatRoom::State state
+ ) override;
+
+ void onConfiguringStatus(
+ const std::shared_ptr & core,
+ linphone::ConfiguringState status,
+ const std::string & message) override;
+
+ void onDtmfReceived(
+ const std::shared_ptr & lc,
+ const std::shared_ptr & call,
+ int dtmf)override;
+
+ void onGlobalStateChanged (
+ const std::shared_ptr &core,
+ linphone::GlobalState gstate,
+ const std::string &message
+ ) override;
+
+ void onIsComposingReceived (
+ const std::shared_ptr &core,
+ const std::shared_ptr &room
+ ) override;
+
+ void onLogCollectionUploadStateChanged (
+ const std::shared_ptr &core,
+ linphone::Core::LogCollectionUploadState state,
+ const std::string &info
+ ) override;
+
+ void onLogCollectionUploadProgressIndication (
+ const std::shared_ptr &lc,
+ size_t offset,
+ size_t total
+ ) override;
+
+ void onMessageReceived (
+ const std::shared_ptr &core,
+ const std::shared_ptr &room,
+ const std::shared_ptr &message
+ ) override;
+
+ void onMessagesReceived (
+ const std::shared_ptr &core,
+ const std::shared_ptr &room,
+ const std::list> &messages
+ ) override;
+
+ void onNotifyPresenceReceivedForUriOrTel (
+ const std::shared_ptr &core,
+ const std::shared_ptr &linphoneFriend,
+ const std::string &uriOrTel,
+ const std::shared_ptr &presenceModel
+ ) override;
+
+ void onNotifyPresenceReceived (
+ const std::shared_ptr &core,
+ const std::shared_ptr &linphoneFriend
+ ) override;
+
+ void onQrcodeFound(const std::shared_ptr & core, const std::string & result) override;
+
+ void onTransferStateChanged (
+ const std::shared_ptr &core,
+ const std::shared_ptr &call,
+ linphone::Call::State state
+ ) override;
+
+ void onVersionUpdateCheckResultReceived (
+ const std::shared_ptr & core,
+ linphone::VersionUpdateCheckResult result,
+ const std::string &version,
+ const std::string &url
+ ) override;
+
+ void onEcCalibrationResult(
+ const std::shared_ptr & core,
+ linphone::EcCalibratorStatus status,
+ int delayMs
+ ) override;
+
+ // Conference Info
+ virtual void onConferenceInfoReceived(const std::shared_ptr & core, const std::shared_ptr & conferenceInfo) override;
+};
+
+#endif // CORE_HANDLERS_H_
diff --git a/linphone-app/src/linphone/core/CoreListener.cpp b/linphone-app/src/linphone/core/CoreListener.cpp
new file mode 100644
index 000000000..06c3e547b
--- /dev/null
+++ b/linphone-app/src/linphone/core/CoreListener.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+
+#include "app/App.hpp"
+#include "components/call/CallModel.hpp"
+#include "components/contact/ContactModel.hpp"
+#include "components/notifier/Notifier.hpp"
+#include "components/settings/AccountSettingsModel.hpp"
+#include "components/settings/SettingsModel.hpp"
+#include "components/timeline/TimelineListModel.hpp"
+#include "utils/Utils.hpp"
+
+#include "CoreListener.hpp"
+
+// =============================================================================
+
+using namespace std;
+
+// -----------------------------------------------------------------------------
+
+CoreListener::CoreListener(QObject * parent): QObject(parent){
+}
+CoreListener::~CoreListener(){
+ qDebug() << "Destroying CoreListener " << this;
+}
+
+// -----------------------------------------------------------------------------
+void CoreListener::onAccountRegistrationStateChanged(const std::shared_ptr & core, const std::shared_ptr & account, linphone::RegistrationState state, const std::string & message){
+ emit accountRegistrationStateChanged(account, state, message);
+}
+void CoreListener::onAuthenticationRequested(const std::shared_ptr &core, const std::shared_ptr &authInfo, linphone::AuthMethod method){
+ emit authenticationRequested(authInfo, method);
+}
+void CoreListener::onCallEncryptionChanged(const std::shared_ptr &core, const std::shared_ptr &call, bool on, const std::string &authenticationToken){
+ emit callEncryptionChanged(call, on, authenticationToken);
+}
+void CoreListener::onCallLogUpdated(const std::shared_ptr & core, const std::shared_ptr & callLog){
+ emit onCallLogUpdated(callLog);
+}
+void CoreListener::onCallStateChanged (const std::shared_ptr &core, const std::shared_ptr &call, linphone::Call::State state, const std::string &message){
+ emit onCallStateChanged(call, state, message);
+}
+void CoreListener::onCallStatsUpdated (const std::shared_ptr &core, const std::shared_ptr &call, const std::shared_ptr &stats){
+ emit onCallStatsUpdated(call, stats);
+}
+void CoreListener::onCallCreated(const std::shared_ptr & lc, const std::shared_ptr & call){
+ emit onCallCreated(call);
+}
+void CoreListener::onChatRoomStateChanged(const std::shared_ptr & core, const std::shared_ptr & chatRoom, linphone::ChatRoom::State state){
+ emit onChatRoomStateChanged(chatRoom, state);
+}
+void CoreListener::onConfiguringStatus(const std::shared_ptr & core, linphone::ConfiguringState status, const std::string & message){
+ emit onConfiguringStatus(status, message);
+}
+void CoreListener::onDtmfReceived(const std::shared_ptr & lc, const std::shared_ptr & call, int dtmf){
+ emit onDtmfReceived(call dtmf);
+}
+void CoreListener::onGlobalStateChanged (const std::shared_ptr &core, linphone::GlobalState gstate, const std::string &message){
+ emit onGlobalStateChanged(gstate, message);
+}
+void CoreListener::onIsComposingReceived (const std::shared_ptr &core, const std::shared_ptr &room){
+ emit onIsComposingReceived(room);
+}
+void CoreListener::onLogCollectionUploadStateChanged (const std::shared_ptr &core, linphone::Core::LogCollectionUploadState state, const std::string &info){
+ emit onLogCollectionUploadStateChanged(state, info);
+}
+void CoreListener::onLogCollectionUploadProgressIndication (const std::shared_ptr &lc, size_t offset, size_t total){
+ emit onLogCollectionUploadProgressIndication(offset, total);
+}
+void CoreListener::onMessageReceived (const std::shared_ptr &core, const std::shared_ptr &room, const std::shared_ptr &message){
+ emit onMessageReceived(room, message);
+}
+void CoreListener::onMessagesReceived (const std::shared_ptr &core, const std::shared_ptr &room, const std::list> &messages){
+ emit onMessagesReceived(room, messages);
+}
+void CoreListener::onNotifyPresenceReceivedForUriOrTel (const std::shared_ptr &core, const std::shared_ptr &linphoneFriend, const std::string &uriOrTel, const std::shared_ptr &presenceModel){
+ emit onNotifyPresenceReceivedForUriOrTel(linphoneFriend, uriOrTel, presenceModel);
+}
+void CoreListener::onNotifyPresenceReceived (const std::shared_ptr &core, const std::shared_ptr &linphoneFriend){
+ emit onNotifyPresenceReceived(linphoneFriend);
+}
+void CoreListener::onQrcodeFound(const std::shared_ptr & core, const std::string & result){
+ emit onQrcodeFound(result);
+}
+void CoreListener::onTransferStateChanged (const std::shared_ptr &core, const std::shared_ptr &call, linphone::Call::State state){
+ emit onTransferStateChanged(call, state);
+}
+void CoreListener::onVersionUpdateCheckResultReceived (const std::shared_ptr & core, linphone::VersionUpdateCheckResult result, const std::string &version, const std::string &url){
+ emit onVersionUpdateCheckResultReceived(result, version, url);
+}
+void CoreListener::onEcCalibrationResult(const std::shared_ptr & core, linphone::EcCalibratorStatus status, int delayMs){
+ emit onEcCalibrationResult(delayMs);
+}
+void CoreListener::onConferenceInfoReceived(const std::shared_ptr & core, const std::shared_ptr & conferenceInfo){
+ emit onConferenceInfoReceived(conferenceInfo);
+}
diff --git a/linphone-app/src/linphone/core/CoreListener.hpp b/linphone-app/src/linphone/core/CoreListener.hpp
new file mode 100644
index 000000000..fafc57c99
--- /dev/null
+++ b/linphone-app/src/linphone/core/CoreListener.hpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2010-2020 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * 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 .
+ */
+
+#ifndef CORE_LISTENER_H_
+#define CORE_LISTENER_H_
+
+#include
+#include
+
+#include
+#include
+
+class CoreListener : public QObject, public linphone::CoreListener {
+ Q_OBJECT
+
+public:
+ CoreListener (QObject * parent = nullptr);
+ ~CoreListener ();
+
+signals:
+ void accountRegistrationStateChanged(const std::shared_ptr & core, const std::shared_ptr & account, linphone::RegistrationState state, const std::string & message) override;
+ void authenticationRequested(const std::shared_ptr &core, const std::shared_ptr &authInfo, linphone::AuthMethod method) override;
+ void callEncryptionChanged(const std::shared_ptr &core, const std::shared_ptr &call, bool on, const std::string &authenticationToken) override;
+ void callLogUpdated(const std::shared_ptr & core, const std::shared_ptr & callLog) override;
+ void callStateChanged (const std::shared_ptr &core, const std::shared_ptr &call, linphone::Call::State state, const std::string &message) override;
+ void callStatsUpdated (const std::shared_ptr &core, const std::shared_ptr &call, const std::shared_ptr &stats) override;
+ void callCreated(const std::shared_ptr & lc, const std::shared_ptr & call) override;
+ void chatRoomStateChanged(const std::shared_ptr & core, const std::shared_ptr & chatRoom, linphone::ChatRoom::State state) override;
+ void configuringStatus(const std::shared_ptr & core, linphone::ConfiguringState status, const std::string & message) override;
+ void dtmfReceived(const std::shared_ptr & lc, const std::shared_ptr & call, int dtmf)override;
+ void globalStateChanged (const std::shared_ptr &core, linphone::GlobalState gstate, const std::string &message) override;
+ void isComposingReceived (const std::shared_ptr &core, const std::shared_ptr &room) override;
+ void logCollectionUploadStateChanged (const std::shared_ptr &core, linphone::Core::LogCollectionUploadState state, const std::string &info) override;
+ void logCollectionUploadProgressIndication (const std::shared_ptr &lc, size_t offset, size_t total) override;
+ void messageReceived (const std::shared_ptr &core, const std::shared_ptr &room, const std::shared_ptr &message) override;
+ void messagesReceived (const std::shared_ptr &core, const std::shared_ptr &room, const std::list> &messages) override;
+ void notifyPresenceReceivedForUriOrTel (const std::shared_ptr &core, const std::shared_ptr &linphoneFriend, const std::string &uriOrTel, const std::shared_ptr &presenceModel) override;
+ void notifyPresenceReceived (const std::shared_ptr &core, const std::shared_ptr &linphoneFriend) override;
+ void qrcodeFound(const std::shared_ptr & core, const std::string & result) override;
+ void transferStateChanged (const std::shared_ptr &core, const std::shared_ptr &call, linphone::Call::State state) override;
+ void versionUpdateCheckResultReceived (const std::shared_ptr & core, linphone::VersionUpdateCheckResult result, const std::string &version, const std::string &url) override;
+ void ecCalibrationResult(const std::shared_ptr & core, linphone::EcCalibratorStatus status, int delayMs) override;
+ // Conference Info
+ void conferenceInfoReceived(const std::shared_ptr & core, const std::shared_ptr & conferenceInfo) override;
+
+private:
+ // ---------------------------------------------------------------------------
+ // Linphone callbacks.
+ // ---------------------------------------------------------------------------
+ void onAccountRegistrationStateChanged(const std::shared_ptr & core, const std::shared_ptr & account, linphone::RegistrationState state, const std::string & message) override;
+ void onAuthenticationRequested(const std::shared_ptr &core, const std::shared_ptr &authInfo, linphone::AuthMethod method) override;
+ void onCallEncryptionChanged(const std::shared_ptr &core, const std::shared_ptr &call, bool on, const std::string &authenticationToken) override;
+ void onCallLogUpdated(const std::shared_ptr & core, const std::shared_ptr & callLog) override;
+ void onCallStateChanged (const std::shared_ptr &core, const std::shared_ptr &call, linphone::Call::State state, const std::string &message) override;
+ void onCallStatsUpdated (const std::shared_ptr &core, const std::shared_ptr &call, const std::shared_ptr &stats) override;
+ void onCallCreated(const std::shared_ptr