/* * CoreHandlers.cpp * Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Created on: February 2, 2017 * Author: Ronan Abhamon */ #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 "utils/Utils.hpp" #include "CoreHandlers.hpp" #include "CoreManager.hpp" // ============================================================================= using namespace std; // Schedule a function in app context. void scheduleFunctionInApp (function func) { App *app = App::getInstance(); if (QThread::currentThread() != app->thread()) QTimer::singleShot(0, app, func); else func(); } // ----------------------------------------------------------------------------- CoreHandlers::CoreHandlers (CoreManager *coreManager) { mCoreStartedLock = new QMutex(); QObject::connect(coreManager, &CoreManager::coreCreated, this, &CoreHandlers::handleCoreCreated); } CoreHandlers::~CoreHandlers () { delete mCoreStartedLock; } // ----------------------------------------------------------------------------- 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 &, const shared_ptr &authInfo, linphone::AuthMethod ) { emit authenticationRequested(authInfo); } void CoreHandlers::onCallEncryptionChanged ( const shared_ptr &, const shared_ptr &call, bool, const string & ) { emit callEncryptionChanged(call); } 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::onGlobalStateChanged ( const shared_ptr &, linphone::GlobalState gstate, const string & ) { if (gstate == linphone::GlobalState::On) { mCoreStartedLock->lock(); Q_ASSERT(mCoreStarted == false); mCoreStarted = true; notifyCoreStarted(); mCoreStartedLock->unlock(); } } 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 ) { const string contentType = message->getContentType(); if (contentType == "text/plain" || contentType == "application/vnd.gsma.rcs-ft-http+xml") { emit messageReceived(message); // 1. Do not notify if chat is not activated. CoreManager *coreManager = CoreManager::getInstance(); SettingsModel *settingsModel = coreManager->getSettingsModel(); if (!settingsModel->getChatEnabled()) return; // 2. Notify with Notification popup. const App *app = App::getInstance(); if (!app->hasFocus() || !chatRoom->getLocalAddress()->weakEqual(coreManager->getAccountSettingsModel()->getUsedSipAddress())) app->getNotifier()->notifyReceivedMessage(message); // 3. Notify with sound. if (!settingsModel->getChatNotificationSoundEnabled()) return; if ( !app->hasFocus() || !CoreManager::getInstance()->chatModelExists( Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()), Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()) ) ) 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->getData("contact-model").refreshPresence(); } void CoreHandlers::onRegistrationStateChanged ( const shared_ptr &, const shared_ptr &proxyConfig, linphone::RegistrationState state, const string & ) { emit registrationStateChanged(proxyConfig, state); } 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::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) ); }