Fix crash on logger (instance lost).
Add Call model. Start audio call from Utils. Simplify VariantObject to use only setValue(). Add notifications.
This commit is contained in:
parent
62a9d34e09
commit
7ff6989614
34 changed files with 1883 additions and 380 deletions
|
|
@ -35,6 +35,9 @@ if(NOT WIN32)
|
||||||
add_compile_options(-Werror=deprecated-declarations)
|
add_compile_options(-Werror=deprecated-declarations)
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG -DQT_NO_DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG" )
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)#useful for config.h
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)#useful for config.h
|
||||||
include(application_info.cmake)
|
include(application_info.cmake)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,18 @@
|
||||||
#include "App.hpp"
|
#include "App.hpp"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QFileSelector>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include <QLibraryInfo>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <QQmlFileSelector>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "core/account/Account.hpp"
|
#include "core/account/Account.hpp"
|
||||||
#include "core/account/AccountProxy.hpp"
|
#include "core/account/AccountProxy.hpp"
|
||||||
#include "core/logger/QtLogger.hpp"
|
#include "core/logger/QtLogger.hpp"
|
||||||
#include "core/login/LoginPage.hpp"
|
#include "core/login/LoginPage.hpp"
|
||||||
|
#include "core/notifier/Notifier.hpp"
|
||||||
#include "core/phone-number/PhoneNumber.hpp"
|
#include "core/phone-number/PhoneNumber.hpp"
|
||||||
#include "core/phone-number/PhoneNumberProxy.hpp"
|
#include "core/phone-number/PhoneNumberProxy.hpp"
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
|
|
@ -50,6 +55,9 @@ App *App::getInstance() {
|
||||||
return dynamic_cast<App *>(QApplication::instance());
|
return dynamic_cast<App *>(QApplication::instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Notifier *App::getNotifier() const {
|
||||||
|
return mNotifier;
|
||||||
|
}
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
// Initializations
|
// Initializations
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
@ -76,11 +84,22 @@ void App::init() {
|
||||||
|
|
||||||
// QML
|
// QML
|
||||||
mEngine = new QQmlApplicationEngine(this);
|
mEngine = new QQmlApplicationEngine(this);
|
||||||
|
// Provide `+custom` folders for custom components and `5.9` for old components.
|
||||||
|
QStringList selectors("custom");
|
||||||
|
const QVersionNumber &version = QLibraryInfo::version();
|
||||||
|
if (version.majorVersion() == 5 && version.minorVersion() == 9) selectors.push_back("5.9");
|
||||||
|
auto selector = new QQmlFileSelector(mEngine, mEngine);
|
||||||
|
selector->setExtraSelectors(selectors);
|
||||||
|
qInfo() << QStringLiteral("[App] Activated selectors:") << selector->selector()->allSelectors();
|
||||||
|
|
||||||
mEngine->addImportPath(":/");
|
mEngine->addImportPath(":/");
|
||||||
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
||||||
initCppInterfaces();
|
initCppInterfaces();
|
||||||
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
||||||
|
|
||||||
|
// Enable notifications.
|
||||||
|
mNotifier = new Notifier(mEngine);
|
||||||
|
|
||||||
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
||||||
|
|
@ -110,6 +129,7 @@ void App::initCppInterfaces() {
|
||||||
qmlRegisterUncreatableType<PhoneNumber>(Constants::MainQmlUri, 1, 0, "PhoneNumber", QLatin1String("Uncreatable"));
|
qmlRegisterUncreatableType<PhoneNumber>(Constants::MainQmlUri, 1, 0, "PhoneNumber", QLatin1String("Uncreatable"));
|
||||||
qmlRegisterType<AccountProxy>(Constants::MainQmlUri, 1, 0, "AccountProxy");
|
qmlRegisterType<AccountProxy>(Constants::MainQmlUri, 1, 0, "AccountProxy");
|
||||||
qmlRegisterUncreatableType<Account>(Constants::MainQmlUri, 1, 0, "Account", QLatin1String("Uncreatable"));
|
qmlRegisterUncreatableType<Account>(Constants::MainQmlUri, 1, 0, "Account", QLatin1String("Uncreatable"));
|
||||||
|
qmlRegisterUncreatableType<Call>(Constants::MainQmlUri, 1, 0, "Call", QLatin1String("Uncreatable"));
|
||||||
|
|
||||||
LinphoneEnums::registerMetaTypes();
|
LinphoneEnums::registerMetaTypes();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,13 @@
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
class Notifier;
|
||||||
|
|
||||||
class App : public SingleApplication {
|
class App : public SingleApplication {
|
||||||
public:
|
public:
|
||||||
App(int &argc, char *argv[]);
|
App(int &argc, char *argv[]);
|
||||||
static App *getInstance();
|
static App *getInstance();
|
||||||
|
Notifier *getNotifier() const;
|
||||||
|
|
||||||
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
// App::postModelAsync(<lambda>) => run lambda in model thread and continue.
|
||||||
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
// App::postModelSync(<lambda>) => run lambda in current thread and block connection.
|
||||||
|
|
@ -43,6 +45,14 @@ public:
|
||||||
QMetaObject::invokeMethod(CoreModel::getInstance().get(), callable);
|
QMetaObject::invokeMethod(CoreModel::getInstance().get(), callable);
|
||||||
}
|
}
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
|
static auto postCoreAsync(Func &&callable, Args &&...args) {
|
||||||
|
QMetaObject::invokeMethod(App::getInstance(), callable, args...);
|
||||||
|
}
|
||||||
|
template <typename Func>
|
||||||
|
static auto postCoreAsync(Func &&callable) {
|
||||||
|
QMetaObject::invokeMethod(App::getInstance(), callable);
|
||||||
|
}
|
||||||
|
template <typename Func, typename... Args>
|
||||||
static auto postModelSync(Func &&callable, Args &&...args) {
|
static auto postModelSync(Func &&callable, Args &&...args) {
|
||||||
if (QThread::currentThread() != CoreModel::getInstance()->thread()) {
|
if (QThread::currentThread() != CoreModel::getInstance()->thread()) {
|
||||||
bool end = false;
|
bool end = false;
|
||||||
|
|
@ -70,4 +80,5 @@ private:
|
||||||
|
|
||||||
QCommandLineParser *mParser = nullptr;
|
QCommandLineParser *mParser = nullptr;
|
||||||
Thread *mLinphoneThread = nullptr;
|
Thread *mLinphoneThread = nullptr;
|
||||||
|
Notifier *mNotifier = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/account/AccountList.cpp
|
core/account/AccountList.cpp
|
||||||
core/account/AccountProxy.cpp
|
core/account/AccountProxy.cpp
|
||||||
core/App.cpp
|
core/App.cpp
|
||||||
|
core/call/Call.cpp
|
||||||
core/logger/QtLogger.cpp
|
core/logger/QtLogger.cpp
|
||||||
core/login/LoginPage.cpp
|
core/login/LoginPage.cpp
|
||||||
|
core/notifier/Notifier.cpp
|
||||||
core/path/Paths.cpp
|
core/path/Paths.cpp
|
||||||
core/phone-number/PhoneNumber.cpp
|
core/phone-number/PhoneNumber.cpp
|
||||||
core/phone-number/PhoneNumberList.cpp
|
core/phone-number/PhoneNumberList.cpp
|
||||||
|
|
|
||||||
81
Linphone/core/call/Call.cpp
Normal file
81
Linphone/core/call/Call.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Call.hpp"
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(Call)
|
||||||
|
|
||||||
|
Call::Call(const std::shared_ptr<linphone::Call> &call) : QObject(nullptr) {
|
||||||
|
// Should be call from model Thread
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
mCallModel = Utils::makeQObject_ptr<CallModel>(call);
|
||||||
|
connect(mCallModel.get(), &CallModel::stateChanged, this, &Call::onStateChanged);
|
||||||
|
connect(this, &Call::lAccept, mCallModel.get(), &CallModel::accept);
|
||||||
|
connect(this, &Call::lDecline, mCallModel.get(), &CallModel::decline);
|
||||||
|
connect(this, &Call::lTerminate, mCallModel.get(), &CallModel::terminate);
|
||||||
|
mCallModel->setSelf(mCallModel);
|
||||||
|
mState = LinphoneEnums::fromLinphone(call->getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
Call::~Call() {
|
||||||
|
mustBeInMainThread("~" + getClassName());
|
||||||
|
emit mCallModel->removeListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::CallStatus Call::getStatus() const {
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call::setStatus(LinphoneEnums::CallStatus status) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mStatus != status) {
|
||||||
|
mStatus = status;
|
||||||
|
emit statusChanged(mStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::CallState Call::getState() const {
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call::setState(LinphoneEnums::CallState state, const QString &message) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mState != state) {
|
||||||
|
mState = state;
|
||||||
|
if (state == LinphoneEnums::CallState::Error) setLastErrorMessage(message);
|
||||||
|
emit stateChanged(mState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call::onStateChanged(linphone::Call::State state, const std::string &message) {
|
||||||
|
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Call::getLastErrorMessage() const {
|
||||||
|
return mLastErrorMessage;
|
||||||
|
}
|
||||||
|
void Call::setLastErrorMessage(const QString &message) {
|
||||||
|
if (mLastErrorMessage != message) {
|
||||||
|
mLastErrorMessage = message;
|
||||||
|
emit lastErrorMessageChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
91
Linphone/core/call/Call.hpp
Normal file
91
Linphone/core/call/Call.hpp
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALL_H_
|
||||||
|
#define CALL_H_
|
||||||
|
|
||||||
|
#include "model/call/CallModel.hpp"
|
||||||
|
#include "tool/LinphoneEnums.hpp"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
class Call : public QObject, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(LinphoneEnums::CallStatus status READ getStatus NOTIFY statusChanged)
|
||||||
|
Q_PROPERTY(LinphoneEnums::CallState state READ getState NOTIFY stateChanged)
|
||||||
|
Q_PROPERTY(QString lastErrorMessage READ getLastErrorMessage NOTIFY lastErrorMessageChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Should be call from model Thread. Will be automatically in App thread after initialization
|
||||||
|
Call(const std::shared_ptr<linphone::Call> &call);
|
||||||
|
~Call();
|
||||||
|
|
||||||
|
LinphoneEnums::CallStatus getStatus() const;
|
||||||
|
void setStatus(LinphoneEnums::CallStatus status);
|
||||||
|
|
||||||
|
LinphoneEnums::CallState getState() const;
|
||||||
|
void setState(LinphoneEnums::CallState state, const QString &message);
|
||||||
|
void onStateChanged(linphone::Call::State state, const std::string &message);
|
||||||
|
|
||||||
|
QString getLastErrorMessage() const;
|
||||||
|
void setLastErrorMessage(const QString &message);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void statusChanged(LinphoneEnums::CallStatus status);
|
||||||
|
void stateChanged(LinphoneEnums::CallState state);
|
||||||
|
void lastErrorMessageChanged();
|
||||||
|
|
||||||
|
// Linphone commands
|
||||||
|
void lAccept(bool withVideo); // Accept an incoming call
|
||||||
|
void lDecline(); // Decline an incoming call
|
||||||
|
void lTerminate(); // Hangup a call
|
||||||
|
/* TODO
|
||||||
|
Q_INVOKABLE void acceptWithVideo();
|
||||||
|
|
||||||
|
Q_INVOKABLE void askForTransfer();
|
||||||
|
Q_INVOKABLE void askForAttendedTransfer();
|
||||||
|
Q_INVOKABLE bool transferTo(const QString &sipAddress);
|
||||||
|
Q_INVOKABLE bool transferToAnother(const QString &peerAddress);
|
||||||
|
|
||||||
|
Q_INVOKABLE bool getRemoteVideoEnabled() const;
|
||||||
|
Q_INVOKABLE void acceptVideoRequest();
|
||||||
|
Q_INVOKABLE void rejectVideoRequest();
|
||||||
|
|
||||||
|
Q_INVOKABLE void takeSnapshot();
|
||||||
|
Q_INVOKABLE void startRecording();
|
||||||
|
Q_INVOKABLE void stopRecording();
|
||||||
|
|
||||||
|
Q_INVOKABLE void sendDtmf(const QString &dtmf);
|
||||||
|
Q_INVOKABLE void verifyAuthenticationToken(bool verify);
|
||||||
|
Q_INVOKABLE void updateStreams();
|
||||||
|
Q_INVOKABLE void toggleSpeakerMute();
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CallModel> mCallModel;
|
||||||
|
LinphoneEnums::CallStatus mStatus;
|
||||||
|
LinphoneEnums::CallState mState;
|
||||||
|
QString mLastErrorMessage;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(Call *)
|
||||||
|
#endif
|
||||||
420
Linphone/core/notifier/Notifier.cpp
Normal file
420
Linphone/core/notifier/Notifier.cpp
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QQmlComponent>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QQuickView>
|
||||||
|
#include <QQuickWindow>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "Notifier.hpp"
|
||||||
|
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "core/call/Call.hpp"
|
||||||
|
#include "tool/LinphoneEnums.hpp"
|
||||||
|
#include "tool/providers/ImageProvider.hpp"
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(Notifier)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr char NotificationsPath[] = "qrc:/Linphone/view/Item/Notification/";
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Notifications QML properties/methods.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
constexpr char NotificationShowMethodName[] = "open";
|
||||||
|
|
||||||
|
constexpr char NotificationPropertyData[] = "notificationData";
|
||||||
|
|
||||||
|
constexpr char NotificationPropertyX[] = "popupX";
|
||||||
|
constexpr char NotificationPropertyY[] = "popupY";
|
||||||
|
|
||||||
|
constexpr char NotificationPropertyWindow[] = "__internalWindow";
|
||||||
|
|
||||||
|
constexpr char NotificationPropertyTimer[] = "__timer";
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Arbitrary hardcoded values.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
constexpr int NotificationSpacing = 10;
|
||||||
|
constexpr int MaxNotificationsNumber = 5;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void setProperty(QObject &object, const char *property, const T &value) {
|
||||||
|
if (!object.setProperty(property, QVariant(value))) {
|
||||||
|
qWarning() << QStringLiteral("Unable to set property: `%1`.").arg(property);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Available notifications.
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
const QHash<int, Notifier::Notification> Notifier::Notifications = {
|
||||||
|
//{Notifier::ReceivedMessage, {Notifier::ReceivedMessage, "NotificationReceivedMessage.qml", 10}},
|
||||||
|
//{Notifier::ReceivedFileMessage, {Notifier::ReceivedFileMessage, "NotificationReceivedFileMessage.qml", 10}},
|
||||||
|
{Notifier::ReceivedCall, {Notifier::ReceivedCall, "NotificationReceivedCall.qml", 30}},
|
||||||
|
//{Notifier::NewVersionAvailable, {Notifier::NewVersionAvailable, "NotificationNewVersionAvailable.qml", 30}},
|
||||||
|
//{Notifier::SnapshotWasTaken, {Notifier::SnapshotWasTaken, "NotificationSnapshotWasTaken.qml", 10}},
|
||||||
|
//{Notifier::RecordingCompleted, {Notifier::RecordingCompleted, "NotificationRecordingCompleted.qml", 10}}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Notifier::Notifier(QObject *parent) : QObject(parent) {
|
||||||
|
mustBeInMainThread(getClassName());
|
||||||
|
const int nComponents = Notifications.size();
|
||||||
|
mComponents = new QQmlComponent *[nComponents];
|
||||||
|
|
||||||
|
QQmlEngine *engine = App::getInstance()->mEngine;
|
||||||
|
for (const auto &key : Notifications.keys()) {
|
||||||
|
QQmlComponent *component =
|
||||||
|
new QQmlComponent(engine, QUrl(NotificationsPath + Notifier::Notifications[key].filename));
|
||||||
|
if (Q_UNLIKELY(component->isError())) {
|
||||||
|
qWarning() << QStringLiteral("Errors found in `Notification` component %1:").arg(key)
|
||||||
|
<< component->errors();
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
mComponents[key] = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMutex = new QMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
Notifier::~Notifier() {
|
||||||
|
mustBeInMainThread("~" + getClassName());
|
||||||
|
delete mMutex;
|
||||||
|
|
||||||
|
const int nComponents = Notifications.size();
|
||||||
|
for (int i = 0; i < nComponents; ++i)
|
||||||
|
mComponents[i]->deleteLater();
|
||||||
|
delete[] mComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
QObject *Notifier::createNotification(Notifier::NotificationType type, QVariantMap data) {
|
||||||
|
QQuickItem *wrapperItem = nullptr;
|
||||||
|
mMutex->lock();
|
||||||
|
Q_ASSERT(mInstancesNumber <= MaxNotificationsNumber);
|
||||||
|
if (mInstancesNumber == MaxNotificationsNumber) { // Check existing instances.
|
||||||
|
qWarning() << QStringLiteral("Unable to create another notification.");
|
||||||
|
mMutex->unlock();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
QList<QScreen *> allScreens = QGuiApplication::screens();
|
||||||
|
if (allScreens.size() > 0) { // Ensure to have a screen to avoid errors
|
||||||
|
QQuickItem *previousWrapper = nullptr;
|
||||||
|
++mInstancesNumber;
|
||||||
|
bool showAsTool = false;
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
for (auto w : QGuiApplication::topLevelWindows()) {
|
||||||
|
if ((w->windowState() & Qt::WindowFullScreen) == Qt::WindowFullScreen) {
|
||||||
|
showAsTool = true;
|
||||||
|
w->raise(); // Used to get focus on Mac (On Mac, A Tool is hidden if the app has not focus and the only
|
||||||
|
// way to rid it is to use Widget Attributes(Qt::WA_MacAlwaysShowToolWindow) that is not
|
||||||
|
// available)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < allScreens.size(); ++i) {
|
||||||
|
|
||||||
|
// Use QQuickView to create a visual root object that is
|
||||||
|
// independant from current application Window
|
||||||
|
QScreen *screen = allScreens[i];
|
||||||
|
// auto engine = App::getInstance()->mEngine;
|
||||||
|
auto engine = new QQmlApplicationEngine();
|
||||||
|
engine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
||||||
|
engine->addImportPath(":/");
|
||||||
|
// if(showAsTool) window->setProperty("showAsTool",true);
|
||||||
|
engine->setInitialProperties(data);
|
||||||
|
// engine->rootContext()->setContextProperty("applicationDirPath",QGuiApplication::applicationDirPath());
|
||||||
|
// engine->setInitialProperties({{"screenIndex", i}});
|
||||||
|
//, {"x", screen->geometry().x()}, {"y", screen->geometry().y()}});
|
||||||
|
const QUrl url(QString(NotificationsPath) + Notifier::Notifications[type].filename);
|
||||||
|
QObject::connect(
|
||||||
|
engine, &QQmlApplicationEngine::objectCreated, this,
|
||||||
|
[this, url, screen, engine](QObject *obj, const QUrl &objUrl) {
|
||||||
|
if (!obj && url == objUrl) {
|
||||||
|
qCritical() << "[App] Notifier.qml couldn't be load.";
|
||||||
|
engine->deleteLater();
|
||||||
|
exit(-1);
|
||||||
|
} else {
|
||||||
|
qWarning() << engine->rootObjects()[0];
|
||||||
|
auto window = qobject_cast<QQuickWindow *>(obj);
|
||||||
|
if (window) {
|
||||||
|
int *screenHeightOffset = &mScreenHeightOffset[screen->name()]; // Access optimization
|
||||||
|
QRect availableGeometry = screen->availableGeometry();
|
||||||
|
int heightOffset =
|
||||||
|
availableGeometry.y() +
|
||||||
|
(availableGeometry.height() -
|
||||||
|
window->height()); //*screen->devicePixelRatio(); when using manual scaler
|
||||||
|
|
||||||
|
window->setX(availableGeometry.x() +
|
||||||
|
(availableGeometry.width() -
|
||||||
|
window->property("width")
|
||||||
|
.toInt())); //*screen->devicePixelRatio()); when using manual scaler
|
||||||
|
window->setY(heightOffset - (*screenHeightOffset % heightOffset));
|
||||||
|
qWarning() << window->geometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
engine->load(url);
|
||||||
|
}
|
||||||
|
qInfo() << QStringLiteral("Create notifications:") << wrapperItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMutex->unlock();
|
||||||
|
return wrapperItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Notifier::showNotification(QObject *notification, int timeout) {
|
||||||
|
// Display notification.
|
||||||
|
QMetaObject::invokeMethod(notification, NotificationShowMethodName, Qt::DirectConnection);
|
||||||
|
|
||||||
|
QTimer *timer = new QTimer(notification);
|
||||||
|
timer->setInterval(timeout);
|
||||||
|
timer->setSingleShot(true);
|
||||||
|
notification->setProperty(NotificationPropertyTimer, QVariant::fromValue(timer));
|
||||||
|
|
||||||
|
// Destroy it after timeout.
|
||||||
|
QObject::connect(timer, &QTimer::timeout, this,
|
||||||
|
[this, notification]() { deleteNotificationOnTimeout(QVariant::fromValue(notification)); });
|
||||||
|
|
||||||
|
// Called explicitly (by a click on notification for example)
|
||||||
|
QObject::connect(notification, SIGNAL(deleteNotification(QVariant)), this, SLOT(deleteNotification(QVariant)));
|
||||||
|
|
||||||
|
timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
void Notifier::deleteNotificationOnTimeout(QVariant notification) {
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
for (auto w : QGuiApplication::topLevelWindows()) {
|
||||||
|
if ((w->windowState() & Qt::WindowFullScreen) == Qt::WindowFullScreen) {
|
||||||
|
w->requestActivate(); // Used to get focus on fullscreens on Mac in order to avoid screen switching.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
deleteNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notifier::deleteNotification(QVariant notification) {
|
||||||
|
mMutex->lock();
|
||||||
|
|
||||||
|
QObject *instance = notification.value<QObject *>();
|
||||||
|
|
||||||
|
// Notification marked destroyed.
|
||||||
|
if (instance->property("__valid").isValid()) {
|
||||||
|
mMutex->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << QStringLiteral("Delete notification:") << instance;
|
||||||
|
|
||||||
|
instance->setProperty("__valid", true);
|
||||||
|
instance->property(NotificationPropertyTimer).value<QTimer *>()->stop();
|
||||||
|
|
||||||
|
mInstancesNumber--;
|
||||||
|
Q_ASSERT(mInstancesNumber >= 0);
|
||||||
|
|
||||||
|
if (mInstancesNumber == 0) mScreenHeightOffset.clear();
|
||||||
|
|
||||||
|
mMutex->unlock();
|
||||||
|
|
||||||
|
instance->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
#define CREATE_NOTIFICATION(TYPE, DATA) \
|
||||||
|
QObject *notification = createNotification(TYPE, DATA); \
|
||||||
|
if (!notification) return; \
|
||||||
|
const int timeout = Notifications[TYPE].getTimeout() * 1000; \
|
||||||
|
showNotification(notification, timeout);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Notification functions.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Notifier::notifyReceivedCall(const shared_ptr<linphone::Call> &call) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
auto model = new Call(call);
|
||||||
|
model->moveToThread(this->thread());
|
||||||
|
App::postCoreAsync([this, model]() {
|
||||||
|
mustBeInMainThread(getClassName());
|
||||||
|
QVariantMap map;
|
||||||
|
map["call"].setValue(model);
|
||||||
|
CREATE_NOTIFICATION(Notifier::ReceivedCall, map)
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
model, &Call::statusChanged, notification, [this, notification](LinphoneEnums::CallStatus status) {
|
||||||
|
qInfo() << log().arg("Delete notification on call status : %1").arg(LinphoneEnums::toString(status));
|
||||||
|
deleteNotification(QVariant::fromValue(notification));
|
||||||
|
});
|
||||||
|
QObject::connect(model, &Call::destroyed, notification,
|
||||||
|
[this, notification]() { deleteNotification(QVariant::fromValue(notification)); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void Notifier::notifyReceivedMessages(const list<shared_ptr<linphone::ChatMessage>> &messages) {
|
||||||
|
QVariantMap map;
|
||||||
|
QString txt;
|
||||||
|
if (messages.size() > 0) {
|
||||||
|
shared_ptr<linphone::ChatMessage> message = messages.front();
|
||||||
|
|
||||||
|
if (messages.size() == 1) {
|
||||||
|
auto fileContent = message->getFileTransferInformation();
|
||||||
|
if (!fileContent) {
|
||||||
|
foreach (auto content, message->getContents()) {
|
||||||
|
if (content->isText()) txt += content->getUtf8Text().c_str();
|
||||||
|
}
|
||||||
|
} else if (fileContent->isVoiceRecording())
|
||||||
|
//: 'Voice message received!' : message to warn the user in a notofication for voice messages.
|
||||||
|
txt = tr("newVoiceMessage");
|
||||||
|
else txt = tr("newFileMessage");
|
||||||
|
if (txt.isEmpty() && message->hasConferenceInvitationContent())
|
||||||
|
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
||||||
|
txt = tr("newConferenceInvitation");
|
||||||
|
} else
|
||||||
|
//: 'New messages received!' Notification that warn the user of new messages.
|
||||||
|
txt = tr("newChatRoomMessages");
|
||||||
|
map["message"] = txt;
|
||||||
|
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
|
||||||
|
map["timelineModel"].setValue(
|
||||||
|
CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true).get());
|
||||||
|
if (messages.size() == 1) { // Display only sender on mono message.
|
||||||
|
map["peerAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly());
|
||||||
|
map["fullPeerAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asString());
|
||||||
|
}
|
||||||
|
map["localAddress"] = Utils::coreStringToAppString(message->getToAddress()->asStringUriOnly());
|
||||||
|
map["fullLocalAddress"] = Utils::coreStringToAppString(message->getToAddress()->asString());
|
||||||
|
map["window"].setValue(App::getInstance()->getMainWindow());
|
||||||
|
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notifier::notifyReceivedReactions(
|
||||||
|
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const linphone::ChatMessageReaction>>>
|
||||||
|
&reactions) {
|
||||||
|
QVariantMap map;
|
||||||
|
QString txt;
|
||||||
|
|
||||||
|
if (reactions.size() > 0) {
|
||||||
|
ChatMessageModel *redirection = nullptr;
|
||||||
|
QPair<shared_ptr<linphone::ChatMessage>, std::shared_ptr<const linphone::ChatMessageReaction>> reaction =
|
||||||
|
reactions.front();
|
||||||
|
shared_ptr<linphone::ChatMessage> message = reaction.first;
|
||||||
|
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
|
||||||
|
auto timelineModel = CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true);
|
||||||
|
map["messageId"] = Utils::coreStringToAppString(message->getMessageId());
|
||||||
|
if (reactions.size() == 1) {
|
||||||
|
QString messageTxt;
|
||||||
|
auto fileContent = message->getFileTransferInformation();
|
||||||
|
if (!fileContent) {
|
||||||
|
foreach (auto content, message->getContents()) {
|
||||||
|
if (content->isText()) messageTxt += content->getUtf8Text().c_str();
|
||||||
|
}
|
||||||
|
} else if (fileContent->isVoiceRecording())
|
||||||
|
//: 'Voice message' : Voice message type that has been reacted.
|
||||||
|
messageTxt += tr("voiceMessageReact");
|
||||||
|
else {
|
||||||
|
QFileInfo file(Utils::coreStringToAppString(fileContent->getFilePath()));
|
||||||
|
messageTxt += file.fileName();
|
||||||
|
}
|
||||||
|
if (messageTxt.isEmpty() && message->hasConferenceInvitationContent())
|
||||||
|
//: 'Conference invitation' : Conference invitation message type that has been reacted.
|
||||||
|
messageTxt += tr("conferenceInvitationReact");
|
||||||
|
//: ''Has reacted by %1 to: %2' : Reaction message. %1=Reaction(emoji), %2=type of message(Voice
|
||||||
|
//: Message/Conference invitation/ Message text)
|
||||||
|
txt = tr("reactionMessage").arg(Utils::coreStringToAppString(reaction.second->getBody())).arg(messageTxt);
|
||||||
|
|
||||||
|
} else
|
||||||
|
//: 'New reactions received!' : Notification that warn the user of new reactions.
|
||||||
|
txt = tr("newReactionsMessages");
|
||||||
|
map["message"] = txt;
|
||||||
|
|
||||||
|
map["timelineModel"].setValue(timelineModel.get());
|
||||||
|
if (reactions.size() == 1) { // Display only sender on mono message.
|
||||||
|
map["peerAddress"] = Utils::coreStringToAppString(reaction.second->getFromAddress()->asStringUriOnly());
|
||||||
|
map["fullPeerAddress"] = Utils::coreStringToAppString(reaction.second->getFromAddress()->asString());
|
||||||
|
}
|
||||||
|
map["localAddress"] = Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly());
|
||||||
|
map["fullLocalAddress"] = Utils::coreStringToAppString(chatRoom->getLocalAddress()->asString());
|
||||||
|
map["window"].setValue(App::getInstance()->getMainWindow());
|
||||||
|
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notifier::notifyReceivedFileMessage(const shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const shared_ptr<linphone::Content> &content) {
|
||||||
|
QVariantMap map;
|
||||||
|
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
|
||||||
|
map["timelineModel"].setValue(
|
||||||
|
CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true).get());
|
||||||
|
map["fileUri"] = Utils::coreStringToAppString(content->getFilePath());
|
||||||
|
if (Utils::getImage(map["fileUri"].toString()).isNull()) map["imageUri"] = "";
|
||||||
|
else map["imageUri"] = map["fileUri"];
|
||||||
|
map["fileSize"] = quint64(content->getSize() + content->getFileSize());
|
||||||
|
CREATE_NOTIFICATION(Notifier::ReceivedFileMessage, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Notifier::notifyNewVersionAvailable(const QString &version, const QString &url) {
|
||||||
|
QVariantMap map;
|
||||||
|
map["message"] = tr("newVersionAvailable").arg(version);
|
||||||
|
map["url"] = url;
|
||||||
|
CREATE_NOTIFICATION(Notifier::NewVersionAvailable, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notifier::notifySnapshotWasTaken(const QString &filePath) {
|
||||||
|
QVariantMap map;
|
||||||
|
map["filePath"] = filePath;
|
||||||
|
CREATE_NOTIFICATION(Notifier::SnapshotWasTaken, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notifier::notifyRecordingCompleted(const QString &filePath) {
|
||||||
|
QVariantMap map;
|
||||||
|
map["filePath"] = filePath;
|
||||||
|
CREATE_NOTIFICATION(Notifier::RecordingCompleted, map)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#undef SHOW_NOTIFICATION
|
||||||
|
#undef CREATE_NOTIFICATION
|
||||||
104
Linphone/core/notifier/Notifier.hpp
Normal file
104
Linphone/core/notifier/Notifier.hpp
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NOTIFIER_H_
|
||||||
|
#define NOTIFIER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "core/call/Call.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
#include <QHash>
|
||||||
|
#include <QObject>
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
class QMutex;
|
||||||
|
class QQmlComponent;
|
||||||
|
|
||||||
|
class Notifier : public QObject, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Notifier(QObject *parent = Q_NULLPTR);
|
||||||
|
~Notifier();
|
||||||
|
|
||||||
|
enum NotificationType {
|
||||||
|
ReceivedMessage,
|
||||||
|
ReceivedFileMessage,
|
||||||
|
ReceivedCall,
|
||||||
|
NewVersionAvailable,
|
||||||
|
SnapshotWasTaken,
|
||||||
|
RecordingCompleted
|
||||||
|
};
|
||||||
|
|
||||||
|
// void notifyReceivedCall(Call *call);
|
||||||
|
void notifyReceivedCall(const std::shared_ptr<linphone::Call> &call); // Call from Linphone
|
||||||
|
|
||||||
|
/*
|
||||||
|
void notifyReceivedMessages(const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
||||||
|
void notifyReceivedReactions(
|
||||||
|
const QList<QPair<std::shared_ptr<linphone::ChatMessage>, std::shared_ptr<const
|
||||||
|
linphone::ChatMessageReaction>>> &reactions); void notifyReceivedFileMessage(const
|
||||||
|
std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content);
|
||||||
|
|
||||||
|
void notifyNewVersionAvailable(const QString &version, const QString &url);
|
||||||
|
void notifySnapshotWasTaken(const QString &filePath);
|
||||||
|
void notifyRecordingCompleted(const QString &filePath);
|
||||||
|
*/
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void deleteNotificationOnTimeout(QVariant notification);
|
||||||
|
void deleteNotification(QVariant notification);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Notification {
|
||||||
|
Notification(const int &type = 0, const QString &filename = QString(""), int timeout = 0) {
|
||||||
|
this->type = type;
|
||||||
|
this->filename = filename;
|
||||||
|
this->timeout = timeout;
|
||||||
|
}
|
||||||
|
int getTimeout() const {
|
||||||
|
if (type == Notifier::ReceivedCall) {
|
||||||
|
// return CoreManager::getInstance()->getSettingsModel()->getIncomingCallTimeout();
|
||||||
|
return 30;
|
||||||
|
} else return timeout;
|
||||||
|
}
|
||||||
|
QString filename;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int timeout;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
QObject *createNotification(NotificationType type, QVariantMap data);
|
||||||
|
void showNotification(QObject *notification, int timeout);
|
||||||
|
|
||||||
|
QHash<QString, int> mScreenHeightOffset;
|
||||||
|
int mInstancesNumber = 0;
|
||||||
|
|
||||||
|
QMutex *mMutex = nullptr;
|
||||||
|
QQmlComponent **mComponents = nullptr;
|
||||||
|
|
||||||
|
static const QHash<int, Notification> Notifications;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NOTIFIER_H_
|
||||||
|
|
@ -3,10 +3,31 @@
|
||||||
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
|
|
||||||
|
#ifdef QT_QML_DEBUG
|
||||||
|
#include <QQmlDebuggingEnabler>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 10)
|
||||||
|
// From 5.15.2 to 5.15.10, sometimes, Accessibility freeze the application : Deactivate handlers.
|
||||||
|
#define ACCESSBILITY_WORKAROUND
|
||||||
|
#include <QAccessible>
|
||||||
|
#include <QAccessibleEvent>
|
||||||
|
void DummyUpdateHandler(QAccessibleEvent *event) {
|
||||||
|
}
|
||||||
|
void DummyRootObjectHandler(QObject *) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
// Useful to share camera on Fullscreen (other context) or multiscreens
|
||||||
|
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||||
|
// Disable QML cache. Avoid malformed cache.
|
||||||
|
qputenv("QML_DISABLE_DISK_CACHE", "true");
|
||||||
|
|
||||||
App app(argc, argv);
|
App app(argc, argv);
|
||||||
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
|
|
@ -19,6 +40,11 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ACCESSBILITY_WORKAROUND
|
||||||
|
QAccessible::installUpdateHandler(DummyUpdateHandler);
|
||||||
|
QAccessible::installRootObjectHandler(DummyRootObjectHandler);
|
||||||
|
#endif
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
while (result >= 0) {
|
while (result >= 0) {
|
||||||
result = app.exec();
|
result = app.exec();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
list(APPEND _LINPHONEAPP_SOURCES
|
list(APPEND _LINPHONEAPP_SOURCES
|
||||||
model/account/AccountModel.cpp
|
model/account/AccountModel.cpp
|
||||||
model/account/AccountManager.cpp
|
model/account/AccountManager.cpp
|
||||||
|
|
||||||
|
model/call/CallModel.cpp
|
||||||
|
|
||||||
model/core/CoreModel.cpp
|
model/core/CoreModel.cpp
|
||||||
model/core/CoreListener.cpp
|
|
||||||
|
|
||||||
model/listener/Listener.hpp
|
model/listener/Listener.hpp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ void AccountManager::onRegistrationStateChanged(const std::shared_ptr<linphone::
|
||||||
mAccountModel = nullptr;
|
mAccountModel = nullptr;
|
||||||
break;
|
break;
|
||||||
case linphone::RegistrationState::Ok:
|
case linphone::RegistrationState::Ok:
|
||||||
|
core->setDefaultAccount(account);
|
||||||
emit mAccountModel->removeListener();
|
emit mAccountModel->removeListener();
|
||||||
mAccountModel = nullptr;
|
mAccountModel = nullptr;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
144
Linphone/model/call/CallModel.cpp
Normal file
144
Linphone/model/call/CallModel.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CallModel.hpp"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "model/core/CoreModel.hpp"
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(CallModel)
|
||||||
|
|
||||||
|
CallModel::CallModel(const std::shared_ptr<linphone::Call> &call, QObject *parent)
|
||||||
|
: ::Listener<linphone::Call, linphone::CallListener>(call, parent) {
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
CallModel::~CallModel() {
|
||||||
|
mustBeInLinphoneThread("~" + getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::accept(bool withVideo) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
auto params = core->createCallParams(mMonitor);
|
||||||
|
params->enableVideo(withVideo);
|
||||||
|
// Answer with local call address.
|
||||||
|
auto localAddress = mMonitor->getCallLog()->getLocalAddress();
|
||||||
|
for (auto account : core->getAccountList()) {
|
||||||
|
if (account->getParams()->getIdentityAddress()->weakEqual(localAddress)) {
|
||||||
|
params->setAccount(account);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mMonitor->acceptWithParams(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::decline() {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
auto errorInfo = linphone::Factory::get()->createErrorInfo();
|
||||||
|
errorInfo->set("SIP", linphone::Reason::Declined, 603, "Decline", "");
|
||||||
|
mMonitor->terminateWithErrorInfo(errorInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::terminate() {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
mMonitor->terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onDtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf) {
|
||||||
|
emit dtmfReceived(call, dtmf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onGoclearAckSent(const std::shared_ptr<linphone::Call> &call) {
|
||||||
|
emit goclearAckSent(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onEncryptionChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
bool on,
|
||||||
|
const std::string &authenticationToken) {
|
||||||
|
emit encryptionChanged(call, on, authenticationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onSendMasterKeyChanged(const std::shared_ptr<linphone::Call> &call, const std::string &sendMasterKey) {
|
||||||
|
emit sendMasterKeyChanged(call, sendMasterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onReceiveMasterKeyChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::string &receiveMasterKey) {
|
||||||
|
emit receiveMasterKeyChanged(call, receiveMasterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onInfoMessageReceived(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::InfoMessage> &message) {
|
||||||
|
emit infoMessageReceived(call, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state,
|
||||||
|
const std::string &message) {
|
||||||
|
emit stateChanged(state, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats) {
|
||||||
|
emit statsUpdated(call, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onTransferStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||||
|
emit transferStateChanged(call, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onAckProcessing(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::Headers> &ack,
|
||||||
|
bool isReceived) {
|
||||||
|
emit ackProcessing(call, ack, isReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onTmmbrReceived(const std::shared_ptr<linphone::Call> &call, int streamIndex, int tmmbr) {
|
||||||
|
emit tmmbrReceived(call, streamIndex, tmmbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onSnapshotTaken(const std::shared_ptr<linphone::Call> &call, const std::string &filePath) {
|
||||||
|
emit snapshotTaken(call, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onNextVideoFrameDecoded(const std::shared_ptr<linphone::Call> &call) {
|
||||||
|
emit nextVideoFrameDecoded(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onCameraNotWorking(const std::shared_ptr<linphone::Call> &call, const std::string &cameraName) {
|
||||||
|
emit cameraNotWorking(call, cameraName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onVideoDisplayErrorOccurred(const std::shared_ptr<linphone::Call> &call, int errorCode) {
|
||||||
|
emit videoDisplayErrorOccurred(call, errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onAudioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::AudioDevice> &audioDevice) {
|
||||||
|
emit audioDeviceChanged(call, audioDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onRemoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording) {
|
||||||
|
emit remoteRecording(call, recording);
|
||||||
|
}
|
||||||
105
Linphone/model/call/CallModel.hpp
Normal file
105
Linphone/model/call/CallModel.hpp
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALL_MODEL_H_
|
||||||
|
#define CALL_MODEL_H_
|
||||||
|
|
||||||
|
#include "model/listener/Listener.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
class CallModel : public ::Listener<linphone::Call, linphone::CallListener>,
|
||||||
|
public linphone::CallListener,
|
||||||
|
public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CallModel(const std::shared_ptr<linphone::Call> &account, QObject *parent = nullptr);
|
||||||
|
~CallModel();
|
||||||
|
|
||||||
|
void accept(bool withVideo);
|
||||||
|
void decline();
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// LINPHONE
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
virtual void onDtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf) override;
|
||||||
|
virtual void onGoclearAckSent(const std::shared_ptr<linphone::Call> &call) override;
|
||||||
|
virtual void onEncryptionChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
bool on,
|
||||||
|
const std::string &authenticationToken) override;
|
||||||
|
virtual void onSendMasterKeyChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::string &sendMasterKey) override;
|
||||||
|
virtual void onReceiveMasterKeyChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::string &receiveMasterKey) override;
|
||||||
|
virtual void onInfoMessageReceived(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::InfoMessage> &message) override;
|
||||||
|
virtual void onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state,
|
||||||
|
const std::string &message) override;
|
||||||
|
virtual void onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats) override;
|
||||||
|
virtual void onTransferStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state) override;
|
||||||
|
virtual void onAckProcessing(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::Headers> &ack,
|
||||||
|
bool isReceived) override;
|
||||||
|
virtual void onTmmbrReceived(const std::shared_ptr<linphone::Call> &call, int streamIndex, int tmmbr) override;
|
||||||
|
virtual void onSnapshotTaken(const std::shared_ptr<linphone::Call> &call, const std::string &filePath) override;
|
||||||
|
virtual void onNextVideoFrameDecoded(const std::shared_ptr<linphone::Call> &call) override;
|
||||||
|
virtual void onCameraNotWorking(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::string &cameraName) override;
|
||||||
|
virtual void onVideoDisplayErrorOccurred(const std::shared_ptr<linphone::Call> &call, int errorCode) override;
|
||||||
|
virtual void onAudioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::AudioDevice> &audioDevice) override;
|
||||||
|
virtual void onRemoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void dtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf);
|
||||||
|
void goclearAckSent(const std::shared_ptr<linphone::Call> &call);
|
||||||
|
void
|
||||||
|
encryptionChanged(const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken);
|
||||||
|
void sendMasterKeyChanged(const std::shared_ptr<linphone::Call> &call, const std::string &sendMasterKey);
|
||||||
|
void receiveMasterKeyChanged(const std::shared_ptr<linphone::Call> &call, const std::string &receiveMasterKey);
|
||||||
|
void infoMessageReceived(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::InfoMessage> &message);
|
||||||
|
void stateChanged(linphone::Call::State state, const std::string &message);
|
||||||
|
void statsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats);
|
||||||
|
void transferStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||||
|
void ackProcessing(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::Headers> &ack,
|
||||||
|
bool isReceived);
|
||||||
|
void tmmbrReceived(const std::shared_ptr<linphone::Call> &call, int streamIndex, int tmmbr);
|
||||||
|
void snapshotTaken(const std::shared_ptr<linphone::Call> &call, const std::string &filePath);
|
||||||
|
void nextVideoFrameDecoded(const std::shared_ptr<linphone::Call> &call);
|
||||||
|
void cameraNotWorking(const std::shared_ptr<linphone::Call> &call, const std::string &cameraName);
|
||||||
|
void videoDisplayErrorOccurred(const std::shared_ptr<linphone::Call> &call, int errorCode);
|
||||||
|
virtual void audioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<linphone::AudioDevice> &audioDevice);
|
||||||
|
void remoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CoreListener.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CoreListener::CoreListener(QObject *parent) : QObject(parent) {
|
|
||||||
}
|
|
||||||
CoreListener::~CoreListener() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreListener::onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Account> &account,
|
|
||||||
linphone::RegistrationState state,
|
|
||||||
const std::string &message) {
|
|
||||||
emit accountRegistrationStateChanged(core, account, state, message);
|
|
||||||
}
|
|
||||||
void CoreListener::onAuthenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
|
||||||
linphone::AuthMethod method) {
|
|
||||||
emit authenticationRequested(core, authInfo, method);
|
|
||||||
}
|
|
||||||
void CoreListener::onCallEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
bool on,
|
|
||||||
const std::string &authenticationToken) {
|
|
||||||
emit callEncryptionChanged(core, call, on, authenticationToken);
|
|
||||||
}
|
|
||||||
void CoreListener::onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::CallLog> &callLog) {
|
|
||||||
emit callLogUpdated(core, callLog);
|
|
||||||
}
|
|
||||||
void CoreListener::onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state,
|
|
||||||
const std::string &message) {
|
|
||||||
emit callStateChanged(core, call, state, message);
|
|
||||||
}
|
|
||||||
void CoreListener::onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats) {
|
|
||||||
emit callStatsUpdated(core, call, stats);
|
|
||||||
}
|
|
||||||
void CoreListener::onCallCreated(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
const std::shared_ptr<linphone::Call> &call) {
|
|
||||||
emit callCreated(lc, call);
|
|
||||||
}
|
|
||||||
void CoreListener::onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
|
||||||
emit chatRoomRead(core, chatRoom);
|
|
||||||
}
|
|
||||||
void CoreListener::onChatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
linphone::ChatRoom::State state) {
|
|
||||||
emit chatRoomStateChanged(core, chatRoom, state);
|
|
||||||
}
|
|
||||||
void CoreListener::onConferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
|
|
||||||
emit conferenceInfoReceived(core, conferenceInfo);
|
|
||||||
}
|
|
||||||
void CoreListener::onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Config::ConfiguringState status,
|
|
||||||
const std::string &message) {
|
|
||||||
emit configuringStatus(core, status, message);
|
|
||||||
}
|
|
||||||
void CoreListener::onDtmfReceived(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
int dtmf) {
|
|
||||||
emit dtmfReceived(lc, call, dtmf);
|
|
||||||
}
|
|
||||||
void CoreListener::onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::EcCalibratorStatus status,
|
|
||||||
int delayMs) {
|
|
||||||
emit ecCalibrationResult(core, status, delayMs);
|
|
||||||
}
|
|
||||||
void CoreListener::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::GlobalState gstate,
|
|
||||||
const std::string &message) {
|
|
||||||
emit globalStateChanged(core, gstate, message);
|
|
||||||
}
|
|
||||||
void CoreListener::onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room) {
|
|
||||||
emit isComposingReceived(core, room);
|
|
||||||
}
|
|
||||||
void CoreListener::onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Core::LogCollectionUploadState state,
|
|
||||||
const std::string &info) {
|
|
||||||
emit logCollectionUploadStateChanged(core, state, info);
|
|
||||||
}
|
|
||||||
void CoreListener::onLogCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
size_t offset,
|
|
||||||
size_t total) {
|
|
||||||
emit logCollectionUploadProgressIndication(lc, offset, total);
|
|
||||||
}
|
|
||||||
void CoreListener::onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message) {
|
|
||||||
emit messageReceived(core, room, message);
|
|
||||||
}
|
|
||||||
void CoreListener::onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
|
||||||
emit messagesReceived(core, room, messages);
|
|
||||||
}
|
|
||||||
void CoreListener::onNewMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
|
|
||||||
emit newMessageReaction(core, chatRoom, message, reaction);
|
|
||||||
}
|
|
||||||
void CoreListener::onNotifyPresenceReceivedForUriOrTel(
|
|
||||||
const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
|
||||||
const std::string &uriOrTel,
|
|
||||||
const std::shared_ptr<const linphone::PresenceModel> &presenceModel) {
|
|
||||||
emit notifyPresenceReceivedForUriOrTel(core, linphoneFriend, uriOrTel, presenceModel);
|
|
||||||
}
|
|
||||||
void CoreListener::onNotifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend) {
|
|
||||||
emit notifyPresenceReceived(core, linphoneFriend);
|
|
||||||
}
|
|
||||||
void CoreListener::onQrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result) {
|
|
||||||
emit qrcodeFound(core, result);
|
|
||||||
}
|
|
||||||
void CoreListener::onReactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::Address> &address) {
|
|
||||||
emit reactionRemoved(core, chatRoom, message, address);
|
|
||||||
}
|
|
||||||
void CoreListener::onTransferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state) {
|
|
||||||
emit transferStateChanged(core, call, state);
|
|
||||||
}
|
|
||||||
void CoreListener::onVersionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::VersionUpdateCheckResult result,
|
|
||||||
const std::string &version,
|
|
||||||
const std::string &url) {
|
|
||||||
emit versionUpdateCheckResultReceived(core, result, version, url);
|
|
||||||
}
|
|
||||||
|
|
@ -1,187 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CORE_LISTENER_H_
|
|
||||||
#define CORE_LISTENER_H_
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <linphone++/linphone.hh>
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
class CoreListener : public QObject, public linphone::CoreListener {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CoreListener(QObject *parent = nullptr);
|
|
||||||
virtual ~CoreListener();
|
|
||||||
|
|
||||||
virtual void onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Account> &account,
|
|
||||||
linphone::RegistrationState state,
|
|
||||||
const std::string &message) override;
|
|
||||||
virtual void onAuthenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
|
||||||
linphone::AuthMethod method) override;
|
|
||||||
virtual void onCallEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
bool on,
|
|
||||||
const std::string &authenticationToken) override;
|
|
||||||
virtual void onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::CallLog> &callLog) override;
|
|
||||||
virtual void onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state,
|
|
||||||
const std::string &message) override;
|
|
||||||
virtual void onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats) override;
|
|
||||||
virtual void onCallCreated(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
const std::shared_ptr<linphone::Call> &call) override;
|
|
||||||
virtual void onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) override;
|
|
||||||
virtual void onChatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
linphone::ChatRoom::State state) override;
|
|
||||||
virtual void
|
|
||||||
onConferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) override;
|
|
||||||
virtual void onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Config::ConfiguringState status,
|
|
||||||
const std::string &message) override;
|
|
||||||
virtual void onDtmfReceived(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
int dtmf) override;
|
|
||||||
virtual void onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::EcCalibratorStatus status,
|
|
||||||
int delayMs) override;
|
|
||||||
virtual void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::GlobalState gstate,
|
|
||||||
const std::string &message) override;
|
|
||||||
virtual void onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room) override;
|
|
||||||
virtual void onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Core::LogCollectionUploadState state,
|
|
||||||
const std::string &info) override;
|
|
||||||
virtual void onLogCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc,
|
|
||||||
size_t offset,
|
|
||||||
size_t total) override;
|
|
||||||
virtual void onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message) override;
|
|
||||||
virtual void onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) override;
|
|
||||||
virtual void onNewMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) override;
|
|
||||||
virtual void
|
|
||||||
onNotifyPresenceReceivedForUriOrTel(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
|
||||||
const std::string &uriOrTel,
|
|
||||||
const std::shared_ptr<const linphone::PresenceModel> &presenceModel) override;
|
|
||||||
virtual void onNotifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend) override;
|
|
||||||
virtual void onQrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result) override;
|
|
||||||
virtual void onReactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::Address> &address) override;
|
|
||||||
virtual void onTransferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state) override;
|
|
||||||
virtual void onVersionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::VersionUpdateCheckResult result,
|
|
||||||
const std::string &version,
|
|
||||||
const std::string &url) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void accountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Account> &account,
|
|
||||||
linphone::RegistrationState state,
|
|
||||||
const std::string &message);
|
|
||||||
void authenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
|
||||||
linphone::AuthMethod method);
|
|
||||||
void callEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
bool on,
|
|
||||||
const std::string &authenticationToken);
|
|
||||||
void callLogUpdated(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::CallLog> &callLog);
|
|
||||||
void callStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state,
|
|
||||||
const std::string &message);
|
|
||||||
void callStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats);
|
|
||||||
void callCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call);
|
|
||||||
void chatRoomRead(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
|
||||||
void chatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
linphone::ChatRoom::State state);
|
|
||||||
void conferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo);
|
|
||||||
void configuringStatus(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Config::ConfiguringState status,
|
|
||||||
const std::string &message);
|
|
||||||
void dtmfReceived(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call, int dtmf);
|
|
||||||
void
|
|
||||||
ecCalibrationResult(const std::shared_ptr<linphone::Core> &core, linphone::EcCalibratorStatus status, int delayMs);
|
|
||||||
void globalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::GlobalState gstate,
|
|
||||||
const std::string &message);
|
|
||||||
void isComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room);
|
|
||||||
void logCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::Core::LogCollectionUploadState state,
|
|
||||||
const std::string &info);
|
|
||||||
void logCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc, size_t offset, size_t total);
|
|
||||||
void messageReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message);
|
|
||||||
void messagesReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
|
||||||
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
|
||||||
void newMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction);
|
|
||||||
void notifyPresenceReceivedForUriOrTel(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
|
||||||
const std::string &uriOrTel,
|
|
||||||
const std::shared_ptr<const linphone::PresenceModel> &presenceModel);
|
|
||||||
void notifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Friend> &linphoneFriend);
|
|
||||||
void qrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result);
|
|
||||||
void reactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
|
||||||
const std::shared_ptr<linphone::ChatMessage> &message,
|
|
||||||
const std::shared_ptr<const linphone::Address> &address);
|
|
||||||
void transferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
|
||||||
linphone::Call::State state);
|
|
||||||
void versionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
|
||||||
linphone::VersionUpdateCheckResult result,
|
|
||||||
const std::string &version,
|
|
||||||
const std::string &url);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -28,14 +28,17 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
|
#include "core/notifier/Notifier.hpp"
|
||||||
#include "core/path/Paths.hpp"
|
#include "core/path/Paths.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
DEFINE_ABSTRACT_OBJECT(CoreModel)
|
||||||
|
|
||||||
QSharedPointer<CoreModel> CoreModel::gCoreModel;
|
std::shared_ptr<CoreModel> CoreModel::gCoreModel;
|
||||||
|
|
||||||
CoreModel::CoreModel(const QString &configPath, QThread *parent) : QObject() {
|
CoreModel::CoreModel(const QString &configPath, QThread *parent)
|
||||||
|
: ::Listener<linphone::Core, linphone::CoreListener>(nullptr, parent) {
|
||||||
connect(parent, &QThread::finished, this, [this]() {
|
connect(parent, &QThread::finished, this, [this]() {
|
||||||
// Model thread
|
// Model thread
|
||||||
if (mCore && mCore->getGlobalState() == linphone::GlobalState::On) mCore->stop();
|
if (mCore && mCore->getGlobalState() == linphone::GlobalState::On) mCore->stop();
|
||||||
|
|
@ -50,8 +53,9 @@ CoreModel::CoreModel(const QString &configPath, QThread *parent) : QObject() {
|
||||||
CoreModel::~CoreModel() {
|
CoreModel::~CoreModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<CoreModel> CoreModel::create(const QString &configPath, QThread *parent) {
|
std::shared_ptr<CoreModel> CoreModel::create(const QString &configPath, QThread *parent) {
|
||||||
auto model = QSharedPointer<CoreModel>::create(configPath, parent);
|
auto model = std::make_shared<CoreModel>(configPath, parent);
|
||||||
|
model->setSelf(model);
|
||||||
gCoreModel = model;
|
gCoreModel = model;
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
@ -64,6 +68,7 @@ void CoreModel::start() {
|
||||||
mCore =
|
mCore =
|
||||||
linphone::Factory::get()->createCore(Utils::appStringToCoreString(Paths::getConfigFilePath(mConfigPath)),
|
linphone::Factory::get()->createCore(Utils::appStringToCoreString(Paths::getConfigFilePath(mConfigPath)),
|
||||||
Utils::appStringToCoreString(Paths::getFactoryConfigFilePath()), nullptr);
|
Utils::appStringToCoreString(Paths::getFactoryConfigFilePath()), nullptr);
|
||||||
|
setMonitor(mCore);
|
||||||
setPathsAfterCreation();
|
setPathsAfterCreation();
|
||||||
mCore->start();
|
mCore->start();
|
||||||
setPathAfterStart();
|
setPathAfterStart();
|
||||||
|
|
@ -71,7 +76,7 @@ void CoreModel::start() {
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
QSharedPointer<CoreModel> CoreModel::getInstance() {
|
std::shared_ptr<CoreModel> CoreModel::getInstance() {
|
||||||
return gCoreModel;
|
return gCoreModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,3 +136,138 @@ void CoreModel::setPathAfterStart() {
|
||||||
mCore->setRootCa(Utils::appStringToCoreString(Paths::getRootCaFilePath()));
|
mCore->setRootCa(Utils::appStringToCoreString(Paths::getRootCaFilePath()));
|
||||||
qInfo() << "[CoreModel] Using RootCa path : " << QString::fromStdString(mCore->getRootCa());
|
qInfo() << "[CoreModel] Using RootCa path : " << QString::fromStdString(mCore->getRootCa());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CoreModel::onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Account> &account,
|
||||||
|
linphone::RegistrationState state,
|
||||||
|
const std::string &message) {
|
||||||
|
emit accountRegistrationStateChanged(core, account, state, message);
|
||||||
|
}
|
||||||
|
void CoreModel::onAuthenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
||||||
|
linphone::AuthMethod method) {
|
||||||
|
emit authenticationRequested(core, authInfo, method);
|
||||||
|
}
|
||||||
|
void CoreModel::onCallEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
bool on,
|
||||||
|
const std::string &authenticationToken) {
|
||||||
|
emit callEncryptionChanged(core, call, on, authenticationToken);
|
||||||
|
}
|
||||||
|
void CoreModel::onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::CallLog> &callLog) {
|
||||||
|
emit callLogUpdated(core, callLog);
|
||||||
|
}
|
||||||
|
void CoreModel::onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state,
|
||||||
|
const std::string &message) {
|
||||||
|
if (state == linphone::Call::State::IncomingReceived) {
|
||||||
|
App::getInstance()->getNotifier()->notifyReceivedCall(call);
|
||||||
|
}
|
||||||
|
emit callStateChanged(core, call, state, message);
|
||||||
|
}
|
||||||
|
void CoreModel::onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats) {
|
||||||
|
emit callStatsUpdated(core, call, stats);
|
||||||
|
}
|
||||||
|
void CoreModel::onCallCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call) {
|
||||||
|
emit callCreated(lc, call);
|
||||||
|
}
|
||||||
|
void CoreModel::onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
||||||
|
emit chatRoomRead(core, chatRoom);
|
||||||
|
}
|
||||||
|
void CoreModel::onChatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
linphone::ChatRoom::State state) {
|
||||||
|
emit chatRoomStateChanged(core, chatRoom, state);
|
||||||
|
}
|
||||||
|
void CoreModel::onConferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
|
||||||
|
emit conferenceInfoReceived(core, conferenceInfo);
|
||||||
|
}
|
||||||
|
void CoreModel::onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Config::ConfiguringState status,
|
||||||
|
const std::string &message) {
|
||||||
|
emit configuringStatus(core, status, message);
|
||||||
|
}
|
||||||
|
void CoreModel::onDtmfReceived(const std::shared_ptr<linphone::Core> &lc,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
int dtmf) {
|
||||||
|
emit dtmfReceived(lc, call, dtmf);
|
||||||
|
}
|
||||||
|
void CoreModel::onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::EcCalibratorStatus status,
|
||||||
|
int delayMs) {
|
||||||
|
emit ecCalibrationResult(core, status, delayMs);
|
||||||
|
}
|
||||||
|
void CoreModel::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::GlobalState gstate,
|
||||||
|
const std::string &message) {
|
||||||
|
emit globalStateChanged(core, gstate, message);
|
||||||
|
}
|
||||||
|
void CoreModel::onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room) {
|
||||||
|
emit isComposingReceived(core, room);
|
||||||
|
}
|
||||||
|
void CoreModel::onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Core::LogCollectionUploadState state,
|
||||||
|
const std::string &info) {
|
||||||
|
emit logCollectionUploadStateChanged(core, state, info);
|
||||||
|
}
|
||||||
|
void CoreModel::onLogCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc,
|
||||||
|
size_t offset,
|
||||||
|
size_t total) {
|
||||||
|
emit logCollectionUploadProgressIndication(lc, offset, total);
|
||||||
|
}
|
||||||
|
void CoreModel::onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message) {
|
||||||
|
emit messageReceived(core, room, message);
|
||||||
|
}
|
||||||
|
void CoreModel::onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) {
|
||||||
|
emit messagesReceived(core, room, messages);
|
||||||
|
}
|
||||||
|
void CoreModel::onNewMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) {
|
||||||
|
emit newMessageReaction(core, chatRoom, message, reaction);
|
||||||
|
}
|
||||||
|
void CoreModel::onNotifyPresenceReceivedForUriOrTel(
|
||||||
|
const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
||||||
|
const std::string &uriOrTel,
|
||||||
|
const std::shared_ptr<const linphone::PresenceModel> &presenceModel) {
|
||||||
|
emit notifyPresenceReceivedForUriOrTel(core, linphoneFriend, uriOrTel, presenceModel);
|
||||||
|
}
|
||||||
|
void CoreModel::onNotifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend) {
|
||||||
|
emit notifyPresenceReceived(core, linphoneFriend);
|
||||||
|
}
|
||||||
|
void CoreModel::onQrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result) {
|
||||||
|
emit qrcodeFound(core, result);
|
||||||
|
}
|
||||||
|
void CoreModel::onReactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::Address> &address) {
|
||||||
|
emit reactionRemoved(core, chatRoom, message, address);
|
||||||
|
}
|
||||||
|
void CoreModel::onTransferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state) {
|
||||||
|
emit transferStateChanged(core, call, state);
|
||||||
|
}
|
||||||
|
void CoreModel::onVersionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::VersionUpdateCheckResult result,
|
||||||
|
const std::string &version,
|
||||||
|
const std::string &url) {
|
||||||
|
emit versionUpdateCheckResultReceived(core, result, version, url);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,21 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
#include "model/listener/Listener.hpp"
|
||||||
#include "model/logger/LoggerModel.hpp"
|
#include "model/logger/LoggerModel.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
class CoreModel : public QObject {
|
class CoreModel : public ::Listener<linphone::Core, linphone::CoreListener>,
|
||||||
|
public linphone::CoreListener,
|
||||||
|
public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CoreModel(const QString &configPath, QThread *parent);
|
CoreModel(const QString &configPath, QThread *parent);
|
||||||
~CoreModel();
|
~CoreModel();
|
||||||
static QSharedPointer<CoreModel> create(const QString &configPath, QThread *parent);
|
static std::shared_ptr<CoreModel> create(const QString &configPath, QThread *parent);
|
||||||
static QSharedPointer<CoreModel> getInstance();
|
static std::shared_ptr<CoreModel> getInstance();
|
||||||
|
|
||||||
std::shared_ptr<linphone::Core> getCore();
|
std::shared_ptr<linphone::Core> getCore();
|
||||||
|
|
||||||
|
|
@ -61,7 +65,162 @@ private:
|
||||||
void setPathsAfterCreation();
|
void setPathsAfterCreation();
|
||||||
void setPathAfterStart();
|
void setPathAfterStart();
|
||||||
|
|
||||||
static QSharedPointer<CoreModel> gCoreModel;
|
static std::shared_ptr<CoreModel> gCoreModel;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// LINPHONE
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
virtual void onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Account> &account,
|
||||||
|
linphone::RegistrationState state,
|
||||||
|
const std::string &message) override;
|
||||||
|
virtual void onAuthenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
||||||
|
linphone::AuthMethod method) override;
|
||||||
|
virtual void onCallEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
bool on,
|
||||||
|
const std::string &authenticationToken) override;
|
||||||
|
virtual void onCallLogUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::CallLog> &callLog) override;
|
||||||
|
virtual void onCallStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state,
|
||||||
|
const std::string &message) override;
|
||||||
|
virtual void onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats) override;
|
||||||
|
virtual void onCallCreated(const std::shared_ptr<linphone::Core> &lc,
|
||||||
|
const std::shared_ptr<linphone::Call> &call) override;
|
||||||
|
virtual void onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom) override;
|
||||||
|
virtual void onChatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
linphone::ChatRoom::State state) override;
|
||||||
|
virtual void
|
||||||
|
onConferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) override;
|
||||||
|
virtual void onConfiguringStatus(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Config::ConfiguringState status,
|
||||||
|
const std::string &message) override;
|
||||||
|
virtual void onDtmfReceived(const std::shared_ptr<linphone::Core> &lc,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
int dtmf) override;
|
||||||
|
virtual void onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::EcCalibratorStatus status,
|
||||||
|
int delayMs) override;
|
||||||
|
virtual void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::GlobalState gstate,
|
||||||
|
const std::string &message) override;
|
||||||
|
virtual void onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room) override;
|
||||||
|
virtual void onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Core::LogCollectionUploadState state,
|
||||||
|
const std::string &info) override;
|
||||||
|
virtual void onLogCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc,
|
||||||
|
size_t offset,
|
||||||
|
size_t total) override;
|
||||||
|
virtual void onMessageReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message) override;
|
||||||
|
virtual void onMessagesReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages) override;
|
||||||
|
virtual void onNewMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction) override;
|
||||||
|
virtual void
|
||||||
|
onNotifyPresenceReceivedForUriOrTel(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
||||||
|
const std::string &uriOrTel,
|
||||||
|
const std::shared_ptr<const linphone::PresenceModel> &presenceModel) override;
|
||||||
|
virtual void onNotifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend) override;
|
||||||
|
virtual void onQrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result) override;
|
||||||
|
virtual void onReactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::Address> &address) override;
|
||||||
|
virtual void onTransferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state) override;
|
||||||
|
virtual void onVersionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::VersionUpdateCheckResult result,
|
||||||
|
const std::string &version,
|
||||||
|
const std::string &url) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void accountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Account> &account,
|
||||||
|
linphone::RegistrationState state,
|
||||||
|
const std::string &message);
|
||||||
|
void authenticationRequested(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::AuthInfo> &authInfo,
|
||||||
|
linphone::AuthMethod method);
|
||||||
|
void callEncryptionChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
bool on,
|
||||||
|
const std::string &authenticationToken);
|
||||||
|
void callLogUpdated(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::CallLog> &callLog);
|
||||||
|
void callStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state,
|
||||||
|
const std::string &message);
|
||||||
|
void callStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
const std::shared_ptr<const linphone::CallStats> &stats);
|
||||||
|
void callCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call);
|
||||||
|
void chatRoomRead(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
||||||
|
void chatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
linphone::ChatRoom::State state);
|
||||||
|
void conferenceInfoReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo);
|
||||||
|
void configuringStatus(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Config::ConfiguringState status,
|
||||||
|
const std::string &message);
|
||||||
|
void dtmfReceived(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call, int dtmf);
|
||||||
|
void
|
||||||
|
ecCalibrationResult(const std::shared_ptr<linphone::Core> &core, linphone::EcCalibratorStatus status, int delayMs);
|
||||||
|
void globalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::GlobalState gstate,
|
||||||
|
const std::string &message);
|
||||||
|
void isComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room);
|
||||||
|
void logCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::Core::LogCollectionUploadState state,
|
||||||
|
const std::string &info);
|
||||||
|
void logCollectionUploadProgressIndication(const std::shared_ptr<linphone::Core> &lc, size_t offset, size_t total);
|
||||||
|
void messageReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message);
|
||||||
|
void messagesReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||||
|
const std::list<std::shared_ptr<linphone::ChatMessage>> &messages);
|
||||||
|
void newMessageReaction(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::ChatMessageReaction> &reaction);
|
||||||
|
void notifyPresenceReceivedForUriOrTel(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend,
|
||||||
|
const std::string &uriOrTel,
|
||||||
|
const std::shared_ptr<const linphone::PresenceModel> &presenceModel);
|
||||||
|
void notifyPresenceReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Friend> &linphoneFriend);
|
||||||
|
void qrcodeFound(const std::shared_ptr<linphone::Core> &core, const std::string &result);
|
||||||
|
void reactionRemoved(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<linphone::ChatMessage> &message,
|
||||||
|
const std::shared_ptr<const linphone::Address> &address);
|
||||||
|
void transferStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
|
linphone::Call::State state);
|
||||||
|
void versionUpdateCheckResultReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
|
linphone::VersionUpdateCheckResult result,
|
||||||
|
const std::string &version,
|
||||||
|
const std::string &url);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ template <class LinphoneClass, class ListenerClass>
|
||||||
class Listener : public ListenerPrivate {
|
class Listener : public ListenerPrivate {
|
||||||
public:
|
public:
|
||||||
Listener(std::shared_ptr<LinphoneClass> monitor, QObject *parent = nullptr) {
|
Listener(std::shared_ptr<LinphoneClass> monitor, QObject *parent = nullptr) {
|
||||||
mMonitor = monitor;
|
setMonitor(monitor);
|
||||||
}
|
}
|
||||||
~Listener() {
|
~Listener() {
|
||||||
qDebug() << "Destroying Listener";
|
qDebug() << "Destroying Listener";
|
||||||
|
|
@ -50,10 +50,15 @@ public:
|
||||||
virtual void onRemoveListener() {
|
virtual void onRemoveListener() {
|
||||||
setSelf(nullptr);
|
setSelf(nullptr);
|
||||||
}
|
}
|
||||||
|
void setMonitor(std::shared_ptr<LinphoneClass> monitor) {
|
||||||
|
if (mMonitor && mSelf) mMonitor->removeListener(mSelf);
|
||||||
|
mMonitor = monitor;
|
||||||
|
if (mMonitor && mSelf) mMonitor->addListener(mSelf);
|
||||||
|
}
|
||||||
void setSelf(const std::shared_ptr<ListenerClass> &self) {
|
void setSelf(const std::shared_ptr<ListenerClass> &self) {
|
||||||
if (mMonitor && mSelf) mMonitor->removeListener(mSelf);
|
if (mMonitor && mSelf) mMonitor->removeListener(mSelf);
|
||||||
mSelf = self;
|
mSelf = self;
|
||||||
if (self) mMonitor->addListener(self);
|
if (mMonitor && mSelf) mMonitor->addListener(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ void LoggerModel::init() {
|
||||||
mListener = std::make_shared<LoggerListener>();
|
mListener = std::make_shared<LoggerListener>();
|
||||||
connect(mListener.get(), &LoggerListener::logReceived, this, &LoggerModel::onLinphoneLog);
|
connect(mListener.get(), &LoggerListener::logReceived, this, &LoggerModel::onLinphoneLog);
|
||||||
{
|
{
|
||||||
std::shared_ptr<linphone::LoggingService> loggingService = linphone::LoggingService::get();
|
std::shared_ptr<linphone::LoggingService> loggingService = mLoginService = linphone::LoggingService::get();
|
||||||
loggingService->setDomain(Constants::AppDomain);
|
loggingService->setDomain(Constants::AppDomain);
|
||||||
loggingService->setLogLevel(linphone::LogLevel::Debug);
|
loggingService->setLogLevel(linphone::LogLevel::Debug);
|
||||||
loggingService->addListener(mListener);
|
loggingService->addListener(mListener);
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,15 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void init(const std::shared_ptr<linphone::Config> &config);
|
void init(const std::shared_ptr<linphone::Config> &config);
|
||||||
|
|
||||||
|
void onQtLog(QtMsgType type, QString file, int contextLine, QString msg); // Received from Qt
|
||||||
void onQtLog(QtMsgType type, QString file, int contextLine, QString msg);// Received from Qt
|
|
||||||
void onLinphoneLog(const std::shared_ptr<linphone::LoggingService> &,
|
void onLinphoneLog(const std::shared_ptr<linphone::LoggingService> &,
|
||||||
const std::string &domain,
|
const std::string &domain,
|
||||||
linphone::LogLevel level,
|
linphone::LogLevel level,
|
||||||
const std::string &message);// Received from SDK
|
const std::string &message); // Received from SDK
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void linphoneLogReceived(const std::string &domain, linphone::LogLevel level, const std::string &message); // Send to Qt
|
void
|
||||||
|
linphoneLogReceived(const std::string &domain, linphone::LogLevel level, const std::string &message); // Send to Qt
|
||||||
void verboseEnabledChanged();
|
void verboseEnabledChanged();
|
||||||
void qtOnlyEnabledChanged();
|
void qtOnlyEnabledChanged();
|
||||||
|
|
||||||
|
|
@ -62,6 +62,7 @@ private:
|
||||||
bool mVerboseEnabled = false;
|
bool mVerboseEnabled = false;
|
||||||
bool mQtOnlyEnabled = false;
|
bool mQtOnlyEnabled = false;
|
||||||
std::shared_ptr<LoggerListener> mListener;
|
std::shared_ptr<LoggerListener> mListener;
|
||||||
|
std::shared_ptr<linphone::LoggingService> mLoginService; // Need to store one instance to avoid unwanted cleanup.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,31 +23,40 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
|
#include "core/App.hpp"
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(VariantObject)
|
DEFINE_ABSTRACT_OBJECT(VariantObject)
|
||||||
|
|
||||||
VariantObject::VariantObject(QObject *parent) {
|
VariantObject::VariantObject(QObject *parent) {
|
||||||
|
mThreadLocation = false;
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
|
mCoreObject = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantObject::VariantObject(QVariant value, QObject *parent) : mValue(value) {
|
VariantObject::VariantObject(QVariant value, QObject *parent) : mValue(value) {
|
||||||
|
mThreadLocation = true;
|
||||||
mustBeInMainThread(getClassName());
|
mustBeInMainThread(getClassName());
|
||||||
connect(this, &VariantObject::updateValue, this, &VariantObject::setValue);
|
connect(this, &VariantObject::valueUpdated, this, &VariantObject::setValue);
|
||||||
mCoreObject = new VariantObject();
|
mCoreObject = new VariantObject(nullptr);
|
||||||
|
mCoreObject->moveToThread(CoreModel::getInstance()->thread());
|
||||||
connect(mCoreObject, &VariantObject::valueChanged, this, &VariantObject::setValue);
|
connect(mCoreObject, &VariantObject::valueChanged, this, &VariantObject::setValue);
|
||||||
connect(mCoreObject, &VariantObject::valueChanged, mCoreObject, &QObject::deleteLater);
|
connect(mCoreObject, &VariantObject::valueChanged, mCoreObject, &QObject::deleteLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantObject::~VariantObject() {
|
VariantObject::~VariantObject() {
|
||||||
mustBeInMainThread("~" + getClassName());
|
if (mThreadLocation) mustBeInMainThread("~" + getClassName());
|
||||||
|
else mustBeInLinphoneThread("~" + getClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant VariantObject::getValue() const {
|
QVariant VariantObject::getValue() const {
|
||||||
mustBeInMainThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
if (mThreadLocation) mustBeInMainThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
||||||
|
else mustBeInLinphoneThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
||||||
return mValue;
|
return mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VariantObject::setValue(QVariant value) {
|
void VariantObject::setValue(QVariant value) {
|
||||||
mustBeInMainThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
if (mThreadLocation) mustBeInMainThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
||||||
|
else mustBeInLinphoneThread(QString(gClassName) + " : " + Q_FUNC_INFO);
|
||||||
if (value != mValue) {
|
if (value != mValue) {
|
||||||
mValue = value;
|
mValue = value;
|
||||||
emit valueChanged(mValue);
|
emit valueChanged(mValue);
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,17 @@ public:
|
||||||
QVariant getValue() const;
|
QVariant getValue() const;
|
||||||
void setValue(QVariant value);
|
void setValue(QVariant value);
|
||||||
|
|
||||||
|
// mCoreObject must be used to request update value : this object will be not be deleted by GUI so it is safe to use
|
||||||
|
// inside model thread. call emit updateValue() from coreObject to set value from model.
|
||||||
VariantObject *mCoreObject; // Ensure to use DeleteLater() after updating value
|
VariantObject *mCoreObject; // Ensure to use DeleteLater() after updating value
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void valueChanged(QVariant value);
|
void valueChanged(QVariant value);
|
||||||
void updateValue(QVariant value);
|
void valueUpdated(QVariant value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant mValue;
|
QVariant mValue;
|
||||||
|
bool mThreadLocation = true; // true=Core, false=Model
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ToolModel.hpp"
|
#include "ToolModel.hpp"
|
||||||
|
#include "core/App.hpp"
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
|
|
@ -67,3 +67,58 @@ QString ToolModel::getDisplayName(QString address) {
|
||||||
QString displayName = getDisplayName(interpretUrl(address));
|
QString displayName = getDisplayName(interpretUrl(address));
|
||||||
return displayName.isEmpty() ? address : displayName;
|
return displayName.isEmpty() ? address : displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Call *ToolModel::startAudioCall(const QString &sipAddress,
|
||||||
|
const QString &prepareTransfertAddress,
|
||||||
|
const QHash<QString, QString> &headers) {
|
||||||
|
bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall()
|
||||||
|
std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore();
|
||||||
|
|
||||||
|
std::shared_ptr<linphone::Address> address = interpretUrl(sipAddress);
|
||||||
|
if (!address) {
|
||||||
|
qCritical() << "[" + QString(gClassName) + "] The calling address is not an interpretable SIP address: "
|
||||||
|
<< sipAddress;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
|
||||||
|
params->enableVideo(false);
|
||||||
|
|
||||||
|
QHashIterator<QString, QString> iterator(headers);
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
iterator.next();
|
||||||
|
params->addCustomHeader(Utils::appStringToCoreString(iterator.key()),
|
||||||
|
Utils::appStringToCoreString(iterator.value()));
|
||||||
|
}
|
||||||
|
if (core->getDefaultAccount()) params->setAccount(core->getDefaultAccount());
|
||||||
|
// CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
|
||||||
|
auto call = core->inviteAddressWithParams(address, params);
|
||||||
|
return call ? new Call(call) : nullptr;
|
||||||
|
|
||||||
|
/* TODO transfer
|
||||||
|
|
||||||
|
std::shared_ptr<linphone::Account> currentAccount = core->getDefaultAccount();
|
||||||
|
if (currentAccount) {
|
||||||
|
if (!waitRegistrationForCall || currentAccount->getState() == linphone::RegistrationState::Ok) {
|
||||||
|
qWarning() << "prepareTransfert not impolemented";
|
||||||
|
// CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Waiting registration not implemented";
|
||||||
|
|
||||||
|
// QObject *context = new QObject();
|
||||||
|
// QObject::connect(
|
||||||
|
// CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged, context,
|
||||||
|
// [address, core, params, currentAccount, prepareTransfertAddress, context](
|
||||||
|
// const std::shared_ptr<linphone::Account> &account, linphone::RegistrationState state) mutable {
|
||||||
|
// if (context && account == currentAccount && state == linphone::RegistrationState::Ok) {
|
||||||
|
// CallModel::prepareTransfert(core->inviteAddressWithParams(address, params),
|
||||||
|
// prepareTransfertAddress);
|
||||||
|
// context->deleteLater();
|
||||||
|
// context = nullptr;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
} else qWarning() << "prepareTransfert not impolemented";
|
||||||
|
// CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@
|
||||||
#ifndef TOOL_MODEL_H_
|
#ifndef TOOL_MODEL_H_
|
||||||
#define TOOL_MODEL_H_
|
#define TOOL_MODEL_H_
|
||||||
|
|
||||||
|
#include "core/call/Call.hpp"
|
||||||
#include "tool/AbstractObject.hpp"
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
|
@ -37,6 +39,10 @@ public:
|
||||||
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
|
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
|
||||||
static QString getDisplayName(QString address);
|
static QString getDisplayName(QString address);
|
||||||
|
|
||||||
|
static Call *startAudioCall(const QString &sipAddress,
|
||||||
|
const QString &prepareTransfertAddress = "",
|
||||||
|
const QHash<QString, QString> &headers = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
void LinphoneEnums::registerMetaTypes() {
|
void LinphoneEnums::registerMetaTypes() {
|
||||||
|
qRegisterMetaType<LinphoneEnums::CallState>();
|
||||||
qRegisterMetaType<LinphoneEnums::CallStatus>();
|
qRegisterMetaType<LinphoneEnums::CallStatus>();
|
||||||
qRegisterMetaType<LinphoneEnums::ChatMessageState>();
|
qRegisterMetaType<LinphoneEnums::ChatMessageState>();
|
||||||
qRegisterMetaType<LinphoneEnums::ChatRoomState>();
|
qRegisterMetaType<LinphoneEnums::ChatRoomState>();
|
||||||
|
|
@ -81,6 +82,13 @@ LinphoneEnums::ChatRoomState LinphoneEnums::fromLinphone(const linphone::ChatRoo
|
||||||
return static_cast<LinphoneEnums::ChatRoomState>(data);
|
return static_cast<LinphoneEnums::ChatRoomState>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
linphone::Call::State LinphoneEnums::toLinphone(const LinphoneEnums::CallState &data) {
|
||||||
|
return static_cast<linphone::Call::State>(data);
|
||||||
|
}
|
||||||
|
LinphoneEnums::CallState LinphoneEnums::fromLinphone(const linphone::Call::State &data) {
|
||||||
|
return static_cast<LinphoneEnums::CallState>(data);
|
||||||
|
}
|
||||||
|
|
||||||
linphone::Call::Status LinphoneEnums::toLinphone(const LinphoneEnums::CallStatus &data) {
|
linphone::Call::Status LinphoneEnums::toLinphone(const LinphoneEnums::CallStatus &data) {
|
||||||
return static_cast<linphone::Call::Status>(data);
|
return static_cast<linphone::Call::Status>(data);
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +96,25 @@ LinphoneEnums::CallStatus LinphoneEnums::fromLinphone(const linphone::Call::Stat
|
||||||
return static_cast<LinphoneEnums::CallStatus>(data);
|
return static_cast<LinphoneEnums::CallStatus>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString LinphoneEnums::toString(const LinphoneEnums::CallStatus &data) {
|
||||||
|
switch (data) {
|
||||||
|
case LinphoneEnums::CallStatus::Declined:
|
||||||
|
return "Declined";
|
||||||
|
case LinphoneEnums::CallStatus::Missed:
|
||||||
|
return "Missed";
|
||||||
|
case LinphoneEnums::CallStatus::Success:
|
||||||
|
return "Success";
|
||||||
|
case LinphoneEnums::CallStatus::Aborted:
|
||||||
|
return "Aborted";
|
||||||
|
case LinphoneEnums::CallStatus::EarlyAborted:
|
||||||
|
return "EarlyAborted";
|
||||||
|
case LinphoneEnums::CallStatus::AcceptedElsewhere:
|
||||||
|
return "AcceptedElsewhere";
|
||||||
|
case LinphoneEnums::CallStatus::DeclinedElsewhere:
|
||||||
|
return "DeclinedElsewhere";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
linphone::Conference::Layout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout &layout) {
|
linphone::Conference::Layout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout &layout) {
|
||||||
if (layout != LinphoneEnums::ConferenceLayout::AudioOnly) return static_cast<linphone::Conference::Layout>(layout);
|
if (layout != LinphoneEnums::ConferenceLayout::AudioOnly) return static_cast<linphone::Conference::Layout>(layout);
|
||||||
else return linphone::Conference::Layout::Grid; // Audio Only mode
|
else return linphone::Conference::Layout::Grid; // Audio Only mode
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
namespace LinphoneEnums {
|
namespace LinphoneEnums {
|
||||||
Q_NAMESPACE
|
Q_NAMESPACE
|
||||||
|
Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") // Avoid name clashes
|
||||||
|
|
||||||
void registerMetaTypes();
|
void registerMetaTypes();
|
||||||
|
|
||||||
|
|
@ -115,6 +116,34 @@ Q_ENUM_NS(ChatRoomState)
|
||||||
linphone::ChatRoom::State toLinphone(const LinphoneEnums::ChatRoomState &data);
|
linphone::ChatRoom::State toLinphone(const LinphoneEnums::ChatRoomState &data);
|
||||||
LinphoneEnums::ChatRoomState fromLinphone(const linphone::ChatRoom::State &data);
|
LinphoneEnums::ChatRoomState fromLinphone(const linphone::ChatRoom::State &data);
|
||||||
|
|
||||||
|
enum class CallState {
|
||||||
|
Idle = int(linphone::Call::State::Idle),
|
||||||
|
IncomingReceived = int(linphone::Call::State::IncomingReceived),
|
||||||
|
PushIncomingReceived = int(linphone::Call::State::PushIncomingReceived),
|
||||||
|
OutgoingInit = int(linphone::Call::State::OutgoingInit),
|
||||||
|
OutgoingProgress = int(linphone::Call::State::OutgoingProgress),
|
||||||
|
OutgoingRinging = int(linphone::Call::State::OutgoingRinging),
|
||||||
|
OutgoingEarlyMedia = int(linphone::Call::State::OutgoingEarlyMedia),
|
||||||
|
Connected = int(linphone::Call::State::Connected),
|
||||||
|
StreamsRunning = int(linphone::Call::State::StreamsRunning),
|
||||||
|
Pausing = int(linphone::Call::State::Pausing),
|
||||||
|
Paused = int(linphone::Call::State::Paused),
|
||||||
|
Resuming = int(linphone::Call::State::Resuming),
|
||||||
|
Referred = int(linphone::Call::State::Referred),
|
||||||
|
Error = int(linphone::Call::State::Error),
|
||||||
|
End = int(linphone::Call::State::End),
|
||||||
|
PausedByRemote = int(linphone::Call::State::PausedByRemote),
|
||||||
|
UpdatedByRemote = int(linphone::Call::State::UpdatedByRemote),
|
||||||
|
IncomingEarlyMedia = int(linphone::Call::State::IncomingEarlyMedia),
|
||||||
|
Updating = int(linphone::Call::State::Updating),
|
||||||
|
Released = int(linphone::Call::State::Released),
|
||||||
|
EarlyUpdatedByRemote = int(linphone::Call::State::EarlyUpdatedByRemote),
|
||||||
|
EarlyUpdating = int(linphone::Call::State::EarlyUpdating)
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(CallState)
|
||||||
|
linphone::Call::State toLinphone(const LinphoneEnums::CallState &data);
|
||||||
|
LinphoneEnums::CallState fromLinphone(const linphone::Call::State &data);
|
||||||
|
|
||||||
enum class CallStatus {
|
enum class CallStatus {
|
||||||
Declined = int(linphone::Call::Status::Declined),
|
Declined = int(linphone::Call::Status::Declined),
|
||||||
Missed = int(linphone::Call::Status::Missed),
|
Missed = int(linphone::Call::Status::Missed),
|
||||||
|
|
@ -126,8 +155,9 @@ enum class CallStatus {
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(CallStatus)
|
Q_ENUM_NS(CallStatus)
|
||||||
|
|
||||||
linphone::Call::Status toLinphone(const LinphoneEnums::CallStatus &capability);
|
linphone::Call::Status toLinphone(const LinphoneEnums::CallStatus &data);
|
||||||
LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &capability);
|
LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &data);
|
||||||
|
QString toString(const LinphoneEnums::CallStatus &data);
|
||||||
|
|
||||||
enum class ConferenceLayout {
|
enum class ConferenceLayout {
|
||||||
Grid = int(linphone::Conference::Layout::Grid),
|
Grid = int(linphone::Conference::Layout::Grid),
|
||||||
|
|
@ -227,7 +257,8 @@ LinphoneEnums::TransportType fromLinphone(const linphone::TransportType &type);
|
||||||
QString toString(const LinphoneEnums::TransportType &type);
|
QString toString(const LinphoneEnums::TransportType &type);
|
||||||
void fromString(const QString &transportType, LinphoneEnums::TransportType *transport);
|
void fromString(const QString &transportType, LinphoneEnums::TransportType *transport);
|
||||||
} // namespace LinphoneEnums
|
} // namespace LinphoneEnums
|
||||||
|
/*
|
||||||
|
Q_DECLARE_METATYPE(LinphoneEnums::CallState)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::CallStatus)
|
Q_DECLARE_METATYPE(LinphoneEnums::CallStatus)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::ChatMessageState)
|
Q_DECLARE_METATYPE(LinphoneEnums::ChatMessageState)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::ChatRoomState)
|
Q_DECLARE_METATYPE(LinphoneEnums::ChatRoomState)
|
||||||
|
|
@ -242,5 +273,5 @@ Q_DECLARE_METATYPE(LinphoneEnums::RecorderState)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::RegistrationState)
|
Q_DECLARE_METATYPE(LinphoneEnums::RegistrationState)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode)
|
Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode)
|
||||||
Q_DECLARE_METATYPE(LinphoneEnums::TransportType)
|
Q_DECLARE_METATYPE(LinphoneEnums::TransportType)
|
||||||
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
|
#include "model/call/CallModel.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
|
|
||||||
|
|
@ -43,7 +44,25 @@ VariantObject *Utils::getDisplayName(const QString &address) {
|
||||||
VariantObject *data = new VariantObject(address); // Scope : GUI
|
VariantObject *data = new VariantObject(address); // Scope : GUI
|
||||||
App::postModelAsync([coreObject = data->mCoreObject, address]() mutable {
|
App::postModelAsync([coreObject = data->mCoreObject, address]() mutable {
|
||||||
QString displayName = ToolModel::getDisplayName(address);
|
QString displayName = ToolModel::getDisplayName(address);
|
||||||
emit coreObject->valueChanged(displayName);
|
coreObject->setValue(displayName);
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VariantObject *Utils::startAudioCall(const QString &sipAddress,
|
||||||
|
const QString &prepareTransfertAddress,
|
||||||
|
const QHash<QString, QString> &headers) {
|
||||||
|
VariantObject *data = new VariantObject(QVariant()); // Scope : GUI
|
||||||
|
qDebug() << "Calling " << sipAddress;
|
||||||
|
App::postModelAsync([coreObject = data->mCoreObject, sipAddress, prepareTransfertAddress, headers]() mutable {
|
||||||
|
auto call = ToolModel::startAudioCall(sipAddress, prepareTransfertAddress, headers);
|
||||||
|
if (call && coreObject) {
|
||||||
|
call->moveToThread(App::getInstance()->thread());
|
||||||
|
coreObject->setValue(QVariant::fromValue(call));
|
||||||
|
// App::postCoreAsync([data, call]() { data->setValue(QVariant::fromValue(call)); });
|
||||||
|
// emit coreObject->valueChanged(call);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
||||||
|
Q_INVOKABLE static VariantObject *startAudioCall(const QString &sipAddress,
|
||||||
|
const QString &prepareTransfertAddress = "",
|
||||||
|
const QHash<QString, QString> &headers = {});
|
||||||
|
|
||||||
static inline QString coreStringToAppString(const std::string &str) {
|
static inline QString coreStringToAppString(const std::string &str) {
|
||||||
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,12 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
view/Item/Carousel.qml
|
view/Item/Carousel.qml
|
||||||
view/Item/CheckBox.qml
|
view/Item/CheckBox.qml
|
||||||
view/Item/ComboBox.qml
|
view/Item/ComboBox.qml
|
||||||
|
view/Item/DesktopPopup.qml
|
||||||
view/Item/DigitInput.qml
|
view/Item/DigitInput.qml
|
||||||
|
|
||||||
|
view/Item/Notification/Notification.qml
|
||||||
|
view/Item/Notification/NotificationReceivedCall.qml
|
||||||
|
|
||||||
view/Item/PhoneNumberComboBox.qml
|
view/Item/PhoneNumberComboBox.qml
|
||||||
view/Item/PhoneNumberInput.qml
|
view/Item/PhoneNumberInput.qml
|
||||||
view/Item/RadioButton.qml
|
view/Item/RadioButton.qml
|
||||||
|
|
@ -35,6 +40,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
# Prototypes
|
# Prototypes
|
||||||
view/Prototype/PhoneNumberPrototype.qml
|
view/Prototype/PhoneNumberPrototype.qml
|
||||||
view/Prototype/AccountsPrototype.qml
|
view/Prototype/AccountsPrototype.qml
|
||||||
|
view/Prototype/CallPrototype.qml
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND _LINPHONEAPP_QML_SINGLETONS
|
list(APPEND _LINPHONEAPP_QML_SINGLETONS
|
||||||
|
|
|
||||||
187
Linphone/view/Item/DesktopPopup.qml
Normal file
187
Linphone/view/Item/DesktopPopup.qml
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Window 2.2
|
||||||
|
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Qt.labs.platform 1.0
|
||||||
|
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
Window {
|
||||||
|
id: mainItem
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
property bool requestActivate: false
|
||||||
|
//property int flags: Qt.SplashScreen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
default property alias _content: content.data
|
||||||
|
property bool _isOpen: false
|
||||||
|
signal isOpened()
|
||||||
|
signal isClosed()
|
||||||
|
signal dataChanged()
|
||||||
|
|
||||||
|
on_ContentChanged: dataChanged(_content)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function open () {
|
||||||
|
_isOpen = true;
|
||||||
|
isOpened();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
function close () {
|
||||||
|
_isOpen = false
|
||||||
|
isClosed()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
objectName: '__internalWindow'
|
||||||
|
property bool isFrameLess : false;
|
||||||
|
property bool showAsTool : false
|
||||||
|
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
|
||||||
|
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
|
||||||
|
opacity: 1.0
|
||||||
|
height: _content[0] != null ? _content[0].height : 0
|
||||||
|
width: _content[0] != null ? _content[0].width : 0
|
||||||
|
visible:true
|
||||||
|
Item {
|
||||||
|
id: content
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
property var $parent: mainItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
states: State {
|
||||||
|
name: 'opening'
|
||||||
|
when: _isOpen
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
opacity: 1.0
|
||||||
|
target: window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: ''
|
||||||
|
to: 'opening'
|
||||||
|
ScriptAction {
|
||||||
|
script: {
|
||||||
|
if (wrapper.requestActivate) {
|
||||||
|
window.requestActivate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: '*'
|
||||||
|
to: ''
|
||||||
|
ScriptAction {
|
||||||
|
script: window.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Item {
|
||||||
|
id: wrapper
|
||||||
|
objectName: '__internalWrapper'
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
property alias popupX: window.x
|
||||||
|
property alias popupY: window.y
|
||||||
|
property bool requestActivate: false
|
||||||
|
property int flags: Qt.SplashScreen
|
||||||
|
|
||||||
|
readonly property alias popupWidth: window.width
|
||||||
|
readonly property alias popupHeight: window.height
|
||||||
|
|
||||||
|
default property alias _content: content.data
|
||||||
|
property bool _isOpen: false
|
||||||
|
signal isOpened()
|
||||||
|
signal isClosed()
|
||||||
|
signal dataChanged()
|
||||||
|
|
||||||
|
on_ContentChanged: dataChanged(_content)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function open () {
|
||||||
|
_isOpen = true;
|
||||||
|
isOpened();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close () {
|
||||||
|
_isOpen = false
|
||||||
|
isClosed()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// No size, no position.
|
||||||
|
height: 0
|
||||||
|
width: 0
|
||||||
|
visible:true
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: window
|
||||||
|
objectName: '__internalWindow'
|
||||||
|
property bool isFrameLess : false;
|
||||||
|
property bool showAsTool : false
|
||||||
|
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
|
||||||
|
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
|
||||||
|
onXChanged: console.log(x)
|
||||||
|
opacity: 1.0
|
||||||
|
height: _content[0] != null ? _content[0].height : 0
|
||||||
|
width: _content[0] != null ? _content[0].width : 0
|
||||||
|
visible:true
|
||||||
|
Item {
|
||||||
|
id: content
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
property var $parent: wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
states: State {
|
||||||
|
name: 'opening'
|
||||||
|
when: _isOpen
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
opacity: 1.0
|
||||||
|
target: window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: ''
|
||||||
|
to: 'opening'
|
||||||
|
ScriptAction {
|
||||||
|
script: {
|
||||||
|
if (wrapper.requestActivate) {
|
||||||
|
window.requestActivate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: '*'
|
||||||
|
to: ''
|
||||||
|
ScriptAction {
|
||||||
|
script: window.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
57
Linphone/view/Item/Notification/Notification.qml
Normal file
57
Linphone/view/Item/Notification/Notification.qml
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
DesktopPopup {
|
||||||
|
id: notification
|
||||||
|
|
||||||
|
|
||||||
|
property var notificationData: ({
|
||||||
|
timelineModel : null
|
||||||
|
})
|
||||||
|
property int overrodeHeight
|
||||||
|
default property alias _content: content.data
|
||||||
|
|
||||||
|
signal deleteNotification (var notification)
|
||||||
|
|
||||||
|
// Use as an intermediate between signal/slot without propagate the notification var : last signal parameter will be the last notification instance
|
||||||
|
function deleteNotificationSlot(){
|
||||||
|
deleteNotification(notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
function _close (cb) {
|
||||||
|
if (cb) {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
deleteNotificationSlot();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "#FFFFFF"
|
||||||
|
height: overrodeHeight || 120
|
||||||
|
width: 300
|
||||||
|
|
||||||
|
border {
|
||||||
|
color: "#A1A1A1"
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: iconSign
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
top: parent.top
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Linphone/view/Item/Notification/NotificationReceivedCall.qml
Normal file
54
Linphone/view/Item/Notification/NotificationReceivedCall.qml
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
Notification {
|
||||||
|
id: notification
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
readonly property var call: notificationData && notificationData.call
|
||||||
|
property var state: call.state
|
||||||
|
onStateChanged:{
|
||||||
|
if(state != LinphoneEnums.CallState.IncomingReceived){
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.rightMargin: 15
|
||||||
|
anchors.bottomMargin:15
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Action buttons.
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Button {
|
||||||
|
text: 'Accept'
|
||||||
|
Layout.rightMargin: 20
|
||||||
|
onClicked: {
|
||||||
|
notification.call.lAccept()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: 'Reject'
|
||||||
|
Layout.rightMargin: 20
|
||||||
|
onClicked: {
|
||||||
|
notification.call.lDecline()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
Linphone/view/Prototype/CallPrototype.qml
Normal file
80
Linphone/view/Prototype/CallPrototype.qml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Layouts 1.0
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import Linphone
|
||||||
|
import UtilsCpp 1.0
|
||||||
|
|
||||||
|
// Snippet
|
||||||
|
Window{
|
||||||
|
id: mainItem
|
||||||
|
height: 400
|
||||||
|
width: 800
|
||||||
|
onWidthChanged: console.log(width)
|
||||||
|
property var callVarObject
|
||||||
|
property var call: callVarObject ? callVarObject.value : null
|
||||||
|
property var callState: call && call.state
|
||||||
|
onCallStateChanged: console.log("State:" +callState)
|
||||||
|
visible: true
|
||||||
|
onCallChanged: console.log('New Call:' +call)
|
||||||
|
ColumnLayout{
|
||||||
|
anchors.fill: parent
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
LoginForm{
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
Layout.preferredWidth: 50
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
|
||||||
|
color: LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Ok
|
||||||
|
? 'green'
|
||||||
|
: LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.Failed || LoginPageCpp.registrationState === LinphoneEnums.RegistrationState.None
|
||||||
|
? 'red'
|
||||||
|
: 'orange'
|
||||||
|
}
|
||||||
|
TextInput {
|
||||||
|
id: usernameToCall
|
||||||
|
label: "Username to call"
|
||||||
|
textInputWidth: 250
|
||||||
|
}
|
||||||
|
Button{
|
||||||
|
text: 'Call'
|
||||||
|
onClicked: {
|
||||||
|
mainItem.callVarObject = UtilsCpp.startAudioCall(usernameToCall.inputText + "@sip.linphone.org")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
color: call
|
||||||
|
? call.state === LinphoneEnums.CallState.StreamsRunning
|
||||||
|
? 'green'
|
||||||
|
: call.state === LinphoneEnums.CallState.Released
|
||||||
|
? 'pink'
|
||||||
|
: 'orange'
|
||||||
|
: 'red'
|
||||||
|
Rectangle{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: 'white'
|
||||||
|
width: stateText.contentWidth
|
||||||
|
height: stateText.contentHeight
|
||||||
|
Text{
|
||||||
|
id: stateText
|
||||||
|
text: "State:"+(mainItem.callState ? mainItem.callState : 'None')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
id: errorMessageText
|
||||||
|
text: mainItem.call ? mainItem.call.lastErrorMessage : ''
|
||||||
|
color: 'red'
|
||||||
|
}
|
||||||
|
Item{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
2
external/linphone-sdk
vendored
2
external/linphone-sdk
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8756a37ad10399a0c27d32590a0d1cc87ea97c2e
|
Subproject commit aaeaad94a6e63f182f50318ed1a209c83b152d73
|
||||||
Loading…
Reference in a new issue