Add 02_IncomingCall qt tutorial.

feature/add-qt-tutorial
Ghislain MARY 5 months ago
parent 28c66b6398
commit dfad6c515f

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.22)
project(02_IncomingCall LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 REQUIRED COMPONENTS Core Gui Qml Quick)
find_package(LinphoneCxx REQUIRED)
set(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
set(SOURCES
"src/main.cpp"
"src/App.cpp"
"src/CoreHandler.cpp"
"src/CoreListener.cpp"
"src/CoreManager.cpp"
)
set(QRC_RESOURCES resources.qrc)
set(QML_SOURCES)
file(STRINGS ${QRC_RESOURCES} QRC_RESOURCES_CONTENT)
foreach(line ${QRC_RESOURCES_CONTENT})
set(result)
string(REGEX REPLACE
"^[ \t]*<[ \t]*file[ \t]*>[ \t]*(.+\\.[a-z]+)[ \t]*<[ \t]*/[ \t]*file[ \t]*>[ \t]*$"
"\\1"
result
"${line}"
)
string(REGEX MATCH "\\.[a-z]+$" is_ui ${result})
if(NOT ${is_ui} STREQUAL "")
list(APPEND QML_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${result}")
endif()
endforeach()
get_filename_component(SDK_PATH "${CMAKE_PREFIX_PATH}" REALPATH)
find_path(MSPLUGINS_PATH "plugins" PATH_SUFFIXES "lib/mediastreamer" "lib64/mediastreamer" REQUIRED)
set(MSPLUGINS_PATH "${MSPLUGINS_PATH}/plugins")
add_executable(02_IncomingCall ${SOURCES} ${QML_SOURCES} ${QRC_RESOURCES})
target_compile_definitions(02_IncomingCall PRIVATE "SDK_PATH=\"${SDK_PATH}\"" "MSPLUGINS_PATH=\"${MSPLUGINS_PATH}\"")
target_include_directories(02_IncomingCall PRIVATE ${LINPHONECXX_INCLUDE_DIRS})
target_link_libraries(02_IncomingCall PRIVATE Qt5::Core Qt5::Gui Qt5::Qml Qt5::Quick ${LINPHONECXX_LIBRARIES})
set_target_properties(02_IncomingCall PROPERTIES AUTORCC ON)
set_target_properties(02_IncomingCall PROPERTIES
WIN32_EXECUTABLE ON
MACOSX_BUNDLE ON
)

@ -0,0 +1,15 @@
# Incoming call tutorial
This time we are going to receive our first calls!
If you don't have SIP friends to test with, you can also install Linphone on your mobile device (Android or iOS) and call yourself with a different account.
## How to build
In the following instructions, replace **<PATH-TO-SDK>** by the real path where your SDK is located, e.g. *~/projects/linphone-sdk/build-default/linphone-sdk/desktop/*
mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=<PATH-TO-SDK>
cmake --build .

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>ui/MainPage.qml</file>
<file>ui/CallPage.qml</file>
<file>ui/RegistrationPage.qml</file>
</qresource>
</RCC>

@ -0,0 +1,49 @@
#include <QDir>
#include <QQmlContext>
#include "App.hpp"
#include "CoreManager.hpp"
using namespace std;
using namespace linphone;
App::App(int &argc, char *argv[]) : QGuiApplication(argc, argv)
{
setOrganizationName("Belledonne Communications");
setOrganizationDomain("belledonne-communications.com");
setApplicationName(QFileInfo(applicationFilePath()).baseName());
}
App::~App()
{
}
void App::init()
{
registerTypes();
mEngine = new QQmlApplicationEngine();
mEngine->load(QUrl("qrc:/ui/MainPage.qml"));
if (mEngine->rootObjects().isEmpty())
qFatal("Unable to open main window.");
// Initialize the CoreManager singleton and add it to the Qml context.
CoreManager::init(this);
auto coreManager = CoreManager::getInstance();
QQmlContext *ctx = mEngine->rootContext();
ctx->setContextProperty("coreManager", coreManager);
}
void App::stop()
{
CoreManager::uninit();
}
void App::registerTypes()
{
qRegisterMetaType<string>();
qRegisterMetaType<RegistrationState>();
qRegisterMetaType<shared_ptr<Account>>();
qRegisterMetaType<Call::State>();
qRegisterMetaType<shared_ptr<Call>>();
}

@ -0,0 +1,27 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <linphone++/linphone.hh>
class App : public QGuiApplication
{
Q_OBJECT
public:
App(int &argc, char *argv[]);
~App();
void init();
void stop();
private:
void registerTypes();
QQmlApplicationEngine *mEngine = nullptr;
};
Q_DECLARE_METATYPE(std::string);
Q_DECLARE_METATYPE(linphone::RegistrationState);
Q_DECLARE_METATYPE(std::shared_ptr<linphone::Account>);
Q_DECLARE_METATYPE(linphone::Call::State);
Q_DECLARE_METATYPE(std::shared_ptr<linphone::Call>);

@ -0,0 +1,75 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* 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 <QDebug>
#include "CoreHandler.hpp"
#include "CoreListener.hpp"
#include "CoreManager.hpp"
CoreHandler::CoreHandler()
{
mCoreListener = std::make_shared<CoreListener>();
connectTo(mCoreListener.get());
}
void CoreHandler::setListener(std::shared_ptr<linphone::Core> core)
{
core->addListener(mCoreListener);
}
void CoreHandler::removeListener(std::shared_ptr<linphone::Core> core)
{
core->removeListener(mCoreListener);
}
void CoreHandler::onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &, const std::shared_ptr<linphone::Account> &account, linphone::RegistrationState state, const std::string &message)
{
emit registrationStateChanged(account, state, message);
}
void CoreHandler::onCallStateStateChanged(const std::shared_ptr<linphone::Core> &, const std::shared_ptr<linphone::Call> &call, linphone::Call::State state, const std::string &message)
{
emit callStateChanged(call, state, message);
}
void CoreHandler::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &, linphone::GlobalState state, const std::string &message)
{
switch (state)
{
case linphone::GlobalState::On:
qInfo() << "Core is running " << QString::fromStdString(message);
break;
case linphone::GlobalState::Off:
qInfo() << "Core is stopped " << QString::fromStdString(message);
emit coreStopped();
break;
case linphone::GlobalState::Startup:
qInfo() << "Core is starting" << QString::fromStdString(message);
emit coreStarting();
break;
default:
break;
}
}
void CoreHandler::connectTo(CoreListener *listener)
{
connect(listener, &CoreListener::accountRegistrationStateChanged, this, &CoreHandler::onAccountRegistrationStateChanged);
connect(listener, &CoreListener::callStateChanged, this, &CoreHandler::onCallStateStateChanged);
connect(listener, &CoreListener::globalStateChanged, this, &CoreHandler::onGlobalStateChanged);
}

@ -0,0 +1,49 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* 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/>.
*/
#pragma once
#include <linphone++/linphone.hh>
#include <QObject>
class CoreListener;
class CoreHandler : public QObject
{
Q_OBJECT
public:
CoreHandler();
void setListener(std::shared_ptr<linphone::Core> core);
void removeListener(std::shared_ptr<linphone::Core> core);
signals:
void coreStarting();
void coreStopped();
void callStateChanged(const std::shared_ptr<linphone::Call>, linphone::Call::State state, const std::string &message);
void registrationStateChanged(const std::shared_ptr<linphone::Account> &account, linphone::RegistrationState state, const std::string &message);
public slots:
void onAccountRegistrationStateChanged(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Account> &account, linphone::RegistrationState state, const std::string &message);
void onCallStateStateChanged(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Call> &call, linphone::Call::State state, const std::string &message);
void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core, linphone::GlobalState gstate, const std::string &message);
private:
void connectTo(CoreListener *listener);
std::shared_ptr<CoreListener> mCoreListener;
};

@ -0,0 +1,37 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* 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)
{
}
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::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::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core, linphone::GlobalState gstate, const std::string &message)
{
emit globalStateChanged(core, gstate, message);
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* 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/>.
*/
#pragma once
#include <linphone++/linphone.hh>
#include <QObject>
class CoreListener : public QObject, public linphone::CoreListener
{
Q_OBJECT
public:
CoreListener(QObject *parent = nullptr);
virtual ~CoreListener() = default;
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 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 onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core, linphone::GlobalState gstate, const std::string &message) 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 callStateChanged(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::Call> &call, linphone::Call::State state, const std::string &message);
void globalStateChanged(const std::shared_ptr<linphone::Core> &core, linphone::GlobalState gstate, const std::string &message);
};

@ -0,0 +1,285 @@
#include <QDebug>
#include "CoreHandler.hpp"
#include "CoreManager.hpp"
using namespace std;
using namespace linphone;
CoreManager *CoreManager::mInstance = nullptr;
CoreManager::CoreManager(QObject *parent) : QObject(parent)
{
mPage = QString("qrc:/ui/RegistrationPage.qml");
mHeaderText = QString("Registration Form");
mSoundButtonText = QString("Switch off sound");
mMicrophoneButtonText = QString("Mute");
mHandler = QSharedPointer<CoreHandler>::create();
CoreHandler *coreHandler = mHandler.get();
QObject::connect(coreHandler, &CoreHandler::coreStarting, this, &CoreManager::startIterate, Qt::QueuedConnection);
QObject::connect(coreHandler, &CoreHandler::coreStopped, this, &CoreManager::stopIterate, Qt::QueuedConnection);
QObject::connect(coreHandler, &CoreHandler::callStateChanged, this, &CoreManager::onCallStateChanged, Qt::QueuedConnection);
QObject::connect(coreHandler, &CoreHandler::registrationStateChanged, this, &CoreManager::onRegistrationStateChanged, Qt::QueuedConnection);
// Delay the creation of the core so that the CoreManager instance is
// already set.
QTimer::singleShot(10, [this]()
{ createLinphoneCore(); });
}
CoreManager::~CoreManager()
{
mHandler->removeListener(mCore);
mHandler = nullptr;
mCore = nullptr;
}
void CoreManager::init(QObject *parent)
{
if (mInstance)
return;
mInstance = new CoreManager(parent);
}
void CoreManager::uninit()
{
if (mInstance)
{
mInstance->stopIterate();
auto core = mInstance->mCore;
delete mInstance;
mInstance = nullptr;
core->stop();
}
}
CoreManager *CoreManager::getInstance()
{
return mInstance;
}
void CoreManager::startIterate()
{
// Start a timer to call the core iterate every 20 ms.
mIterateTimer = new QTimer(this);
mIterateTimer->setInterval(20);
QObject::connect(mIterateTimer, &QTimer::timeout, this, &CoreManager::iterate);
qInfo() << QStringLiteral("Start iterate");
mIterateTimer->start();
}
void CoreManager::stopIterate()
{
qInfo() << QStringLiteral("Stop iterate");
mIterateTimer->stop();
mIterateTimer->deleteLater(); // Allow the timer to continue its stuff
mIterateTimer = nullptr;
}
void CoreManager::login(QString identity, QString password)
{
if (mLoginButtonEnabled)
{
setProperty("loginButtonEnabled", false);
shared_ptr<Address> address = Factory::get()->createAddress(identity.toStdString());
shared_ptr<AuthInfo> authInfo = Factory::get()->createAuthInfo(address->getUsername(), "", password.toStdString(), "", "", address->getDomain());
mCore->addAuthInfo(authInfo);
shared_ptr<AccountParams> accountParams = mCore->createAccountParams();
accountParams->setIdentityAddress(address);
string serverAddr = "sip:" + address->getDomain() + ";transport=tls";
accountParams->setServerAddr(serverAddr);
accountParams->enableRegister(true);
shared_ptr<Account> account = mCore->createAccount(accountParams);
mCore->addAccount(account);
mCore->setDefaultAccount(account);
}
}
void CoreManager::logout()
{
shared_ptr<Account> account = mCore->getDefaultAccount();
if (account)
{
shared_ptr<AccountParams> accountParams = account->getParams()->clone();
accountParams->enableRegister(false);
account->setParams(accountParams);
}
}
void CoreManager::onCallStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state, const std::string &message)
{
setProperty("callStateText", QString::fromStdString("Your call state is: " + message));
switch (state)
{
case Call::State::IncomingReceived:
// When you receive a call the Call::State is incoming receive. By default you can only have one current call,
// so if a call is in progress or one is already ringing the second remote call will be decline with the reason
// "Busy". If you want to implement a multi call app you can increase Core::setMaxCalls.
// Here we store the incoming call reference so we can accept or decline the call on user input.
mIncomingCall = call;
// And we update the GUI to notify the user of the incoming call.
setProperty("incomingCallVisible", true);
setProperty("incomingCallText", QString::fromStdString(mIncomingCall->getRemoteAddress()->asString()));
break;
case Call::State::StreamsRunning:
// The StreamsRunning state is the default one during a call.
callInProgressGuiUpdates();
break;
case Call::State::Error:
case Call::State::End:
case Call::State::Released:
// By default after 30 seconds of ringing without accept or decline a call is
// automatically ended.
mIncomingCall = nullptr;
endingCallGuiUpdates();
break;
}
}
void CoreManager::onRegistrationStateChanged(const shared_ptr<Account> &account, RegistrationState state, const string &message)
{
setProperty("registerText", QString::fromStdString("Your registration state is : " + message));
switch (state)
{
// If the Account was logged out, we clear the Core.
case RegistrationState::Cleared:
case RegistrationState::None:
mCore->clearAllAuthInfo();
mCore->clearAccounts();
setProperty("loginButtonEnabled", true);
break;
case RegistrationState::Ok:
setProperty("loginButtonEnabled", false);
setProperty("headerText", QString::fromStdString("Hello " + mCore->getDefaultProxyConfig()->findAuthInfo()->getUsername()));
setProperty("page", QString("qrc:/ui/CallPage.qml"));
break;
case RegistrationState::Progress:
setProperty("loginButtonEnabled", false);
break;
case RegistrationState::Failed:
setProperty("loginButtonEnabled", true);
break;
default:
break;
}
}
void CoreManager::hangup()
{
// Simply call terminateAllCalls to hang out.
mCore->terminateAllCalls();
}
void CoreManager::soundButtonClicked()
{
if (toggleSpeaker())
{
setProperty("soundButtonText", QString("Switch on Sound"));
}
else
{
setProperty("soundButtonText", QString("Switch off Sound"));
}
}
void CoreManager::microphoneButtonClicked()
{
if (toggleMicrophone())
{
setProperty("microphoneButtonText", QString("Mute"));
}
else
{
setProperty("microphoneButtonText", QString("Unmute"));
}
}
void CoreManager::answer()
{
if (mIncomingCall)
{
// To accept a call only use the accept() method on the call object.
// If we wanted, we could create a CallParams object and answer using this object to make changes to the call configuration.
mIncomingCall->accept();
mIncomingCall = nullptr;
}
}
void CoreManager::decline()
{
if (mIncomingCall)
{
// You have to give a Reason to decline a call. This info is sent to the remote.
mIncomingCall->decline(Reason::Declined);
mIncomingCall = nullptr;
}
}
void CoreManager::createLinphoneCore()
{
// Setting linphone log level to message.
auto loggingService = LoggingService::get();
loggingService->setLogLevel(LogLevel::Message);
// Configure paths.
string assetsPath = string(SDK_PATH) + "/share";
Factory::get()->setTopResourcesDir(assetsPath);
Factory::get()->setDataResourcesDir(assetsPath);
Factory::get()->setSoundResourcesDir(assetsPath + "/sounds/linphone");
Factory::get()->setRingResourcesDir(Factory::get()->getSoundResourcesDir() + "/rings");
Factory::get()->setImageResourcesDir(assetsPath + "/images");
Factory::get()->setMspluginsDir(MSPLUGINS_PATH);
// Create a core from the factory.
mCore = Factory::get()->createCore("", "", nullptr);
mCore->setRootCa(assetsPath + "/linphone/rootca.pem");
// Listen for core events.
mHandler->setListener(mCore);
// Start the core.
mCore->start();
}
void CoreManager::iterate()
{
if (mCore)
mCore->iterate();
}
bool CoreManager::toggleSpeaker()
{
// Calling setSpeakerMuted(true) on a Call object disables the sound output of this call.
bool newValue = !mCore->getCurrentCall()->getSpeakerMuted();
mCore->getCurrentCall()->setSpeakerMuted(newValue);
return newValue;
}
bool CoreManager::toggleMicrophone()
{
// The following toggles the microphone, disabling completely / enabling the sound capture from the device microphone
bool newValue = !mCore->micEnabled();
mCore->enableMic(newValue);
return newValue;
}
void CoreManager::callInProgressGuiUpdates()
{
setProperty("incomingCallVisible", false);
setProperty("inCallButtonsEnabled", true);
}
void CoreManager::endingCallGuiUpdates()
{
setProperty("incomingCallVisible", false);
setProperty("inCallButtonsEnabled", false);
setProperty("soundButtonText", "Switch off Sound");
setProperty("microphoneButtonText", "Mute");
}

@ -0,0 +1,84 @@
#pragma once
#include <QObject>
#include <QSharedPointer>
#include <QTimer>
#include <linphone++/linphone.hh>
class CoreHandler;
class CoreManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QString page MEMBER mPage NOTIFY pageChanged);
Q_PROPERTY(QString headerText MEMBER mHeaderText NOTIFY headerTextChanged)
Q_PROPERTY(QString registerText MEMBER mRegisterText NOTIFY registerTextChanged)
Q_PROPERTY(bool loginButtonEnabled MEMBER mLoginButtonEnabled NOTIFY loginButtonEnabledChanged)
Q_PROPERTY(QString callStateText MEMBER mCallStateText NOTIFY callStateTextChanged)
Q_PROPERTY(bool incomingCallVisible MEMBER mIncomingCallVisible NOTIFY incomingCallVisibleChanged)
Q_PROPERTY(QString incomingCallText MEMBER mIncomingCallText NOTIFY incomingCallTextChanged)
Q_PROPERTY(bool inCallButtonsEnabled MEMBER mInCallButtonsEnabled NOTIFY inCallButtonsEnabledChanged)
Q_PROPERTY(QString soundButtonText MEMBER mSoundButtonText NOTIFY soundButtonTextChanged)
Q_PROPERTY(QString microphoneButtonText MEMBER mMicrophoneButtonText NOTIFY microphoneButtonTextChanged)
public:
static void init(QObject *parent);
static void uninit();
static CoreManager *getInstance();
signals:
void pageChanged(QString);
void headerTextChanged(QString);
void registerTextChanged(QString);
void loginButtonEnabledChanged(bool);
void callStateTextChanged(QString);
void incomingCallVisibleChanged(bool);
void incomingCallTextChanged(QString);
void inCallButtonsEnabledChanged(bool);
void soundButtonTextChanged(QString);
void microphoneButtonTextChanged(QString);
public slots:
void startIterate();
void stopIterate();
void login(QString identity, QString password);
void logout();
void onCallStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state, const std::string &message);
void onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account, linphone::RegistrationState state, const std::string &message);
void hangup();
void soundButtonClicked();
void microphoneButtonClicked();
void answer();
void decline();
private:
CoreManager(QObject *parent);
~CoreManager();
void createLinphoneCore();
void iterate();
bool toggleSpeaker();
bool toggleMicrophone();
void callInProgressGuiUpdates();
void endingCallGuiUpdates();
std::shared_ptr<linphone::Core> mCore = nullptr;
std::shared_ptr<linphone::Call> mIncomingCall = nullptr;
QSharedPointer<CoreHandler> mHandler;
QTimer *mIterateTimer = nullptr;
QString mPage;
QString mHeaderText;
QString mRegisterText;
bool mLoginButtonEnabled = true;
QString mCallStateText;
bool mIncomingCallVisible = false;
QString mIncomingCallText;
bool mInCallButtonsEnabled = false;
QString mSoundButtonText;
QString mMicrophoneButtonText;
static CoreManager *mInstance;
};

@ -0,0 +1,29 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* 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 <QCoreApplication>
#include "App.hpp"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
App app(argc, argv);
app.init();
app.exec();
app.stop();
}

@ -0,0 +1,77 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
GridLayout {
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true
columns: 1
ColumnLayout {
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter
Text {
text: coreManager.callStateText
}
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: 20
Button {
text: "Hang up"
enabled: coreManager.inCallButtonsEnabled
onClicked: {
coreManager.hangup()
}
}
Button {
text: coreManager.soundButtonText
enabled: coreManager.inCallButtonsEnabled
onClicked: {
coreManager.soundButtonClicked()
}
}
Button {
text: coreManager.microphoneButtonText
enabled: coreManager.inCallButtonsEnabled
onClicked: {
coreManager.microphoneButtonClicked()
}
}
}
GridLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.margins: 20
columnSpacing: 20
columns: 2
visible: coreManager.incomingCallVisible
Text {
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
text: "You have a call from: " + coreManager.incomingCallText
}
Button {
text: "Answer"
onClicked: {
coreManager.answer()
}
}
Button {
text: "Decline"
onClicked: {
coreManager.decline()
}
}
}
}

@ -0,0 +1,35 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
ApplicationWindow {
id: window
visible: true
title: "Account Login"
width: 640
height: 480
header: Rectangle {
color: "lightgray";
height: 40;
width: window.width
Text {
text: coreManager.headerText
font.bold: true
font.capitalization: Font.AllUppercase
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
height: parent.height
}
}
// Main content
Loader {
id: contentLoader
anchors.fill: parent
source: coreManager.page
}
}

@ -0,0 +1,57 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
ColumnLayout {
//Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.fillWidth: true
Layout.fillHeight: true
GridLayout {
Layout.fillWidth: true
Layout.margins: 20
columnSpacing: 20
columns: 2
Text {
text: "Identity:"
}
TextField {
id: identityTextField
Layout.fillWidth: true
text: "sip:"
}
Text {
text: "Password:"
}
TextField {
id: passwordTextField
echoMode: TextInput.Password
Layout.fillWidth: true
placeholderText: "my password"
}
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Button {
text: "Login"
enabled: coreManager.loginButtonEnabled && identityTextField.text.length !== 0 && passwordTextField.text.length !== 0
onClicked: {
coreManager.login(identityTextField.text, passwordTextField.text)
}
}
}
ColumnLayout {
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter
Text {
text: coreManager.registerText
}
}
}
Loading…
Cancel
Save