diff --git a/assets/languages/en.ts b/assets/languages/en.ts
index f3715d375..387755f89 100644
--- a/assets/languages/en.ts
+++ b/assets/languages/en.ts
@@ -421,6 +421,14 @@ Server url not configured.
showFunctionCall
+
+ joinConferenceFunctionDescription
+
+
+
+ initiateConferenceFunctionDescription
+
+
CodecsViewer
diff --git a/assets/languages/fr.ts b/assets/languages/fr.ts
index 3ec1c7674..7b0442fba 100644
--- a/assets/languages/fr.ts
+++ b/assets/languages/fr.ts
@@ -421,6 +421,14 @@ Url du serveur non configurée.
showFunctionCall
+
+ joinConferenceFunctionDescription
+
+
+
+ initiateConferenceFunctionDescription
+
+
CodecsViewer
diff --git a/assets/linphone.desktop b/assets/linphone.desktop
index 8235d9514..98e74659d 100644
--- a/assets/linphone.desktop
+++ b/assets/linphone.desktop
@@ -7,6 +7,7 @@ Exec=linphone %u
Icon=linphone
Terminal=false
Categories=Network;Telephony;
+MimeType=x-scheme-handler/sip-linphone;x-scheme-handler/sip;
# Translations
diff --git a/cmake_builder/linphone_package/CMakeLists.txt b/cmake_builder/linphone_package/CMakeLists.txt
index 8882375e3..d4abf17da 100644
--- a/cmake_builder/linphone_package/CMakeLists.txt
+++ b/cmake_builder/linphone_package/CMakeLists.txt
@@ -310,7 +310,8 @@ if(WIN32)
string(REPLACE "\\" "\\\\" ESCAPED_DOS_STYLE_SOURCE_DIR "${DOS_STYLE_SOURCE_DIR}")
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" DOS_STYLE_BINARY_DIR)
string(REPLACE "\\" "\\\\" ESCAPED_DOS_STYLE_BINARY_DIR "${DOS_STYLE_BINARY_DIR}")
-
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/uri-handler-install.nsi.in" "${CMAKE_CURRENT_BINARY_DIR}/uri-handler-install.nsi" @ONLY)
+ set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\uri-handler-install.nsi\\\"")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/uninstall.nsi" "${CMAKE_CURRENT_BINARY_DIR}/uninstall.nsi" COPYONLY)
set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\uninstall.nsi\\\"")
if(ENABLE_OPENH264)
diff --git a/cmake_builder/linphone_package/Info.plist.in b/cmake_builder/linphone_package/Info.plist.in
index 18ac851cc..956a842eb 100644
--- a/cmake_builder/linphone_package/Info.plist.in
+++ b/cmake_builder/linphone_package/Info.plist.in
@@ -1,37 +1,48 @@
-
+
- CFBundleDevelopmentRegion
- English
- CFBundleName
- Linphone
- CFBundleDisplayName
- Linphone
- CFBundleExecutable
- linphone
- CFBundleGetInfoString
- @PACKAGE_VERSION@, (C) 2011-2017 The linphone team http://www.linphone.org
- CFBundleIconFile
- linphone.icns
- CFBundleIdentifier
- org.linphone.linphone
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- @PACKAGE_VERSION@
- CFBundleSignature
- ????
- CFBundleVersion
- @PACKAGE_VERSION@
- NSHumanReadableCopyright
- Copyright 2011-2017 Belledonne Communications
- LSMinimumSystemVersion
- @CMAKE_OSX_DEPLOYMENT_TARGET@
- NSAppSleepDisabled
- YES
+ CFBundleDevelopmentRegion
+ English
+ CFBundleName
+ Linphone
+ CFBundleDisplayName
+ Linphone
+ CFBundleExecutable
+ linphone
+ CFBundleGetInfoString
+ @PACKAGE_VERSION@, (C) 2011-2017 The linphone team http://www.linphone.org
+ CFBundleIconFile
+ linphone.icns
+ CFBundleIdentifier
+ org.linphone.linphone
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ @PACKAGE_VERSION@
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ @PACKAGE_VERSION@
+ NSHumanReadableCopyright
+ Copyright 2011-2017 Belledonne Communications
+ LSMinimumSystemVersion
+ @CMAKE_OSX_DEPLOYMENT_TARGET@
+ NSAppSleepDisabled
+ YES
+ CFBundleURLTypes
+
+
+ CFBundleURLName
+ com.belldonnecommunications.linphone
+ CFBundleURLSchemes
+
+ sip
+ sip-linphone
+
+
+
-
diff --git a/cmake_builder/linphone_package/uninstall.nsi b/cmake_builder/linphone_package/uninstall.nsi
index 0645bb0d8..84a21ede6 100644
--- a/cmake_builder/linphone_package/uninstall.nsi
+++ b/cmake_builder/linphone_package/uninstall.nsi
@@ -5,3 +5,5 @@ Abort
notRunningInUninstall:
+DeleteRegKey HKCR "sip"
+DeleteRegKey HKCR "sip-linphone"
diff --git a/cmake_builder/linphone_package/uri-handler-install.nsi.in b/cmake_builder/linphone_package/uri-handler-install.nsi.in
new file mode 100644
index 000000000..871a8de96
--- /dev/null
+++ b/cmake_builder/linphone_package/uri-handler-install.nsi.in
@@ -0,0 +1,13 @@
+WriteRegStr HKCR "sip" "" "URL:sip Protocol"
+WriteRegStr HKCR "sip" "URL Protocol" ""
+WriteRegExpandStr HKCR "sip\DefaultIcon" "" "@LINPHONE_DESKTOP_DIR@/assets/linphone.ico,1"
+WriteRegStr HKCR "sip\shell" "" "open"
+WriteRegStr HKCR "sip\shell\open" "" "command"
+WriteRegStr HKCR "sip\shell\open\command" "" "$INSTDIR\bin\linphone.exe $\"%1$\""
+
+WriteRegStr HKCR "sip-linphone" "" "URL:sip-linphone Protocol"
+WriteRegStr HKCR "sip-linphone" "URL Protocol" ""
+WriteRegExpandStr HKCR "sip-linphone\DefaultIcon" "" "@LINPHONE_DESKTOP_DIR@/assets/linphone.ico,1"
+WriteRegStr HKCR "sip-linphone\shell" "" "open"
+WriteRegStr HKCR "sip-linphone\shell\open" "" "command"
+WriteRegStr HKCR "sip-linphone\shell\open\command" "" "$INSTDIR\bin\linphone.exe $\"%1$\""
\ No newline at end of file
diff --git a/src/app/App.cpp b/src/app/App.cpp
index aa029324b..09e43ba7a 100644
--- a/src/app/App.cpp
+++ b/src/app/App.cpp
@@ -215,6 +215,13 @@ void App::initContentApp () {
if (mEngine->rootObjects().isEmpty())
qFatal("Unable to open main window.");
+ // Execute command argument if needed.
+ {
+ const QString commandArgument = getCommandArgument();
+ if (!commandArgument.isEmpty())
+ mCli->executeCommand(commandArgument);
+ }
+
QObject::connect(
CoreManager::getInstance()->getHandlers().get(),
&CoreHandlers::coreStarted,
@@ -225,13 +232,39 @@ void App::initContentApp () {
// -----------------------------------------------------------------------------
QString App::getCommandArgument () {
- // TODO: Remove me when cmd option will be available.
- return QString("");
- // return mParser->value("cmd");
+ const QStringList &arguments = mParser->positionalArguments();
+ return arguments.empty() ? QString("") : arguments[0];
}
// -----------------------------------------------------------------------------
+void App::executeCommand (const QString &command) {
+ Q_CHECK_PTR(mCli);
+ mCli->executeCommand(command);
+}
+
+// -----------------------------------------------------------------------------
+
+#ifdef Q_OS_MACOS
+
+ bool App::event (QEvent *event) {
+ if (event->type() == QEvent::FileOpen) {
+ const QString url = static_cast(event)->url().toString();
+ if (isSecondary()) {
+ sendMessage(url.toLocal8Bit(), -1);
+ ::exit(EXIT_SUCCESS);
+ }
+
+ executeCommand(url);
+ }
+
+ return SingleApplication::event(event);
+ }
+
+#endif // ifdef Q_OS_MACOS
+
+// -----------------------------------------------------------------------------
+
QQuickWindow *App::getCallsWindow () {
if (!mCallsWindow)
mCallsWindow = ::createSubWindow(mEngine, QML_VIEW_CALLS_WINDOW);
@@ -281,30 +314,19 @@ bool App::hasFocus () const {
// -----------------------------------------------------------------------------
void App::createParser () {
- // TODO: Remove me in the future.
- static const char *disabledOptions[] = {
- QT_TR_NOOP("commandLineOptionCmd"),
- QT_TR_NOOP("commandLineOptionCmdArg")
- };
- (void)disabledOptions;
-
- if (mParser)
- delete mParser;
+ delete mParser;
mParser = new QCommandLineParser();
-
mParser->setApplicationDescription(tr("applicationDescription"));
mParser->addOptions({
{ { "h", "help" }, tr("commandLineOptionHelp") },
{ { "v", "version" }, tr("commandLineOptionVersion") },
{ "config", tr("commandLineOptionConfig"), tr("commandLineOptionConfigArg") },
+ { { "c", "cmd" }, tr("commandLineOptionCmd"), tr("commandLineOptionCmdArg") },
#ifndef Q_OS_MACOS
{ "iconified", tr("commandLineOptionIconified") },
#endif // ifndef Q_OS_MACOS
{ { "V", "verbose" }, tr("commandLineOptionVerbose") }
- // TODO: Enable me in future version!
- // ,
- // { { "c", "cmd" }, tr("commandLineOptionCmd"), tr("commandLineOptionCmdArg") }
});
}
diff --git a/src/app/App.hpp b/src/app/App.hpp
index 06d825e40..3ef9fce75 100644
--- a/src/app/App.hpp
+++ b/src/app/App.hpp
@@ -54,6 +54,11 @@ public:
void initContentApp ();
QString getCommandArgument ();
+ void executeCommand (const QString &command);
+
+ #ifdef Q_OS_MACOS
+ bool event (QEvent *event) override;
+ #endif // ifdef Q_OS_MACOS
QQmlEngine *getEngine () {
return mEngine;
@@ -117,11 +122,11 @@ private:
return qVersion();
}
- QCommandLineParser *mParser = nullptr;
-
QVariantList mAvailableLocales;
QString mLocale;
+ QCommandLineParser *mParser = nullptr;
+
QQmlApplicationEngine *mEngine = nullptr;
DefaultTranslator *mTranslator = nullptr;
diff --git a/src/app/AppController.cpp b/src/app/AppController.cpp
index 7453b3e6f..f63c7478e 100644
--- a/src/app/AppController.cpp
+++ b/src/app/AppController.cpp
@@ -84,8 +84,13 @@ AppController::AppController (int &argc, char *argv[]) {
mApp = new App(argc, argv);
if (mApp->isSecondary()) {
+ #ifdef Q_OS_MACOS
+ mApp->processEvents();
+ #endif // ifdef Q_OS_MACOS
+
QString command = mApp->getCommandArgument();
mApp->sendMessage(command.isEmpty() ? "show" : command.toLocal8Bit(), -1);
+
return;
}
diff --git a/src/app/cli/Cli.cpp b/src/app/cli/Cli.cpp
index d3115be12..deeb73ab8 100644
--- a/src/app/cli/Cli.cpp
+++ b/src/app/cli/Cli.cpp
@@ -20,9 +20,8 @@
* Author: Nicolas Follet
*/
-#include
-
#include "../../components/core/CoreManager.hpp"
+#include "../../utils/Utils.hpp"
#include "../App.hpp"
#include "Cli.hpp"
@@ -33,13 +32,64 @@ using namespace std;
// API.
// =============================================================================
-static void cliShow (const QHash &) {
+static void cliShow (QHash &) {
App *app = App::getInstance();
app->smartShowWindow(app->getMainWindow());
}
-static void cliCall (const QHash &args) {
- CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sipAddress"]);
+static void cliCall (QHash &args) {
+ CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sip-address"]);
+}
+
+static void cliJoinConference (QHash &args) {
+ const QString sipAddress = args.take("sip-address");
+ args["method"] = QStringLiteral("join-conference");
+ CoreManager::getInstance()->getCallsListModel()->launchAudioCall(sipAddress, args);
+}
+
+static void cliInitiateConference (QHash &args) {
+ shared_ptr core = CoreManager::getInstance()->getCore();
+
+ // Check identity.
+ {
+ shared_ptr address = core->interpretUrl(::Utils::appStringToCoreString(args["sip-address"]));
+ address->clean();
+
+ const string sipAddress = address->asString();
+ const string identity = core->getIdentity();
+ if (sipAddress != identity) {
+ qWarning() << QStringLiteral("Received different sip address from identity : `%1 != %2`.")
+ .arg(::Utils::coreStringToAppString(identity))
+ .arg(::Utils::coreStringToAppString(sipAddress));
+ return;
+ }
+ }
+
+ shared_ptr conference = core->getConference();
+ const QString id = args["conference-id"];
+
+ if (conference) {
+ if (conference->getId() == ::Utils::appStringToCoreString(id)) {
+ qInfo() << QStringLiteral("Conference `%1` already exists.").arg(id);
+ // TODO: Set the view to the "waiting call view".
+ return;
+ }
+
+ qInfo() << QStringLiteral("Remove existing conference with id: `%1`.")
+ .arg(::Utils::coreStringToAppString(conference->getId()));
+ core->terminateConference();
+ }
+
+ qInfo() << QStringLiteral("Create conference with id: `%1`.").arg(id);
+ conference = core->createConferenceWithParams(core->createConferenceParams());
+ conference->setId(::Utils::appStringToCoreString(id));
+
+ if (core->enterConference() == -1) {
+ qWarning() << QStringLiteral("Unable to join created conference: `%1`.").arg(id);
+ return;
+ }
+
+ // TODO: Set the view to the "waiting call view".
}
// =============================================================================
@@ -55,7 +105,18 @@ Cli::Command::Command (
mFunction(function),
mArgsScheme(argsScheme) {}
-void Cli::Command::execute (const QHash &args) {
+void Cli::Command::execute (QHash &args) const {
+ // Check arguments validity.
+ for (const auto &argName : args.keys()) {
+ if (!mArgsScheme.contains(argName)) {
+ qWarning() << QStringLiteral("Command with invalid argument: `%1 (%2)`.")
+ .arg(mFunctionName).arg(argName);
+
+ return;
+ }
+ }
+
+ // Check missing arguments.
for (const auto &argName : mArgsScheme.keys()) {
if (!args.contains(argName) && !mArgsScheme[argName].isOptional) {
qWarning() << QStringLiteral("Missing argument for command: `%1 (%2)`.")
@@ -64,14 +125,34 @@ void Cli::Command::execute (const QHash &args) {
}
}
- (*mFunction)(args);
+ // Execute!
+ CoreManager *coreManager = CoreManager::getInstance();
+
+ if (coreManager->started())
+ (*mFunction)(args);
+ else {
+ Function f = mFunction;
+ ::Utils::connectOnce(coreManager->getHandlers().get(), &CoreHandlers::coreStarted, coreManager, [f, args] {
+ QHash fuckConst = args;
+ (*f)(fuckConst);
+ });
+ }
+}
+
+void Cli::Command::executeUri (const shared_ptr &address) const {
+ QHash args;
+ for (const auto &argName : mArgsScheme.keys())
+ args[argName] = ::Utils::coreStringToAppString(address->getHeader(::Utils::appStringToCoreString(argName)));
+ args["sip-address"] = ::Utils::coreStringToAppString(address->asString());
+
+ execute(args);
}
// =============================================================================
// FIXME: Do not accept args without value like: cmd toto.
// In the future `toto` could be a boolean argument.
-QRegExp Cli::mRegExpArgs("(?:(?:(\\w+)\\s*)=\\s*(?:\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|([^\\s]+)\\s*))");
+QRegExp Cli::mRegExpArgs("(?:(?:([\\w-]+)\\s*)=\\s*(?:\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|([^\\s]+)\\s*))");
QRegExp Cli::mRegExpFunctionName("^\\s*([a-z-]+)\\s*");
Cli::Cli (QObject *parent) : QObject(parent) {
@@ -79,6 +160,12 @@ Cli::Cli (QObject *parent) : QObject(parent) {
addCommand("call", tr("showFunctionCall"), ::cliCall, {
{ "sip-address", {} }
});
+ addCommand("initiate-conference", tr("initiateConferenceFunctionDescription"), ::cliInitiateConference, {
+ { "sip-address", {} }, { "conference-id", {} }
+ });
+ addCommand("join-conference", tr("joinConferenceFunctionDescription"), ::cliJoinConference, {
+ { "sip-address", {} }, { "conference-id", {} }
+ });
}
// -----------------------------------------------------------------------------
@@ -88,7 +175,7 @@ void Cli::addCommand (
const QString &description,
Function function,
const QHash &argsScheme
-) noexcept {
+) {
if (mCommands.contains(functionName))
qWarning() << QStringLiteral("Command already exists: `%1`.").arg(functionName);
else
@@ -97,22 +184,44 @@ void Cli::addCommand (
// -----------------------------------------------------------------------------
-void Cli::executeCommand (const QString &command) noexcept {
- const QString functionName = parseFunctionName(command);
- if (functionName.isEmpty())
- return;
+void Cli::executeCommand (const QString &command) const {
+ shared_ptr address = linphone::Factory::get()->createAddress(
+ ::Utils::appStringToCoreString(command)
+ );
- bool soFarSoGood;
- const QHash &args = parseArgs(command, functionName, soFarSoGood);
- if (!soFarSoGood)
- return;
+ // Execute cli command.
+ if (!address) {
+ const QString &functionName = parseFunctionName(command);
+ if (!functionName.isEmpty()) {
+ QHash args = parseArgs(command);
+ mCommands[functionName].execute(args);
+ }
- mCommands[functionName].execute(args);
+ return;
+ }
+
+ // Execute uri command.
+ string scheme = address->getScheme();
+ if (address->getUsername().empty() || (scheme != "sip" && scheme != "sip-linphone")) {
+ qWarning() << QStringLiteral("Not a valid uri: `%1`.").arg(command);
+ return;
+ }
+
+ const QString functionName = ::Utils::coreStringToAppString(address->getHeader("method")).isEmpty()
+ ? QStringLiteral("call")
+ : ::Utils::coreStringToAppString(address->getHeader("method"));
+
+ if (!functionName.isEmpty() && !mCommands.contains(functionName)) {
+ qWarning() << QStringLiteral("This command doesn't exist: `%1`.").arg(functionName);
+ return;
+ }
+
+ mCommands[functionName].executeUri(address);
}
// -----------------------------------------------------------------------------
-const QString Cli::parseFunctionName (const QString &command) noexcept {
+QString Cli::parseFunctionName (const QString &command) const {
mRegExpFunctionName.indexIn(command);
if (mRegExpFunctionName.pos(1) == -1) {
qWarning() << QStringLiteral("Unable to parse function name of command: `%1`.").arg(command);
@@ -130,26 +239,12 @@ const QString Cli::parseFunctionName (const QString &command) noexcept {
return functionName;
}
-const QHash Cli::parseArgs (
- const QString &command,
- const QString functionName,
- bool &soFarSoGood
-) noexcept {
+QHash Cli::parseArgs (const QString &command) const {
QHash args;
int pos = 0;
- soFarSoGood = true;
-
while ((pos = mRegExpArgs.indexIn(command, pos)) != -1) {
pos += mRegExpArgs.matchedLength();
- if (!mCommands[functionName].argNameExists(mRegExpArgs.cap(1))) {
- qWarning() << QStringLiteral("Command with invalid argument(s): `%1 (%2)`.")
- .arg(functionName).arg(mRegExpArgs.cap(1));
-
- soFarSoGood = false;
- return args;
- }
-
args[mRegExpArgs.cap(1)] = (mRegExpArgs.cap(2).isEmpty() ? mRegExpArgs.cap(3) : mRegExpArgs.cap(2));
}
diff --git a/src/app/cli/Cli.hpp b/src/app/cli/Cli.hpp
index 7d8444968..299b8fcb6 100644
--- a/src/app/cli/Cli.hpp
+++ b/src/app/cli/Cli.hpp
@@ -23,15 +23,21 @@
#ifndef CLI_H_
#define CLI_H_
+#include
+
#include
#include
// =============================================================================
+namespace linphone {
+class Address;
+}
+
class Cli : public QObject {
Q_OBJECT;
- typedef void (*Function)(const QHash &);
+ typedef void (*Function)(QHash &);
enum ArgumentType {
STRING
@@ -50,13 +56,15 @@ class Cli : public QObject {
class Command {
public:
Command () = default;
- Command (const QString &functionName, const QString &description, Function function, const QHash &argsScheme);
+ Command (
+ const QString &functionName,
+ const QString &description,
+ Function function,
+ const QHash &argsScheme
+ );
- void execute (const QHash &args);
-
- bool argNameExists (const QString &argName) {
- return mArgsScheme.contains(argName);
- }
+ void execute (QHash &args) const;
+ void executeUri (const std::shared_ptr &address) const;
private:
QString mFunctionName;
@@ -69,13 +77,18 @@ public:
Cli (QObject *parent = Q_NULLPTR);
~Cli () = default;
- void executeCommand (const QString &command) noexcept;
+ void executeCommand (const QString &command) const;
private:
- void addCommand (const QString &functionName, const QString &description, Function function, const QHash &argsScheme = {}) noexcept;
+ void addCommand (
+ const QString &functionName,
+ const QString &description,
+ Function function,
+ const QHash &argsScheme = QHash()
+ );
- const QString parseFunctionName (const QString &command) noexcept;
- const QHash parseArgs (const QString &command, const QString functionName, bool &soFarSoGood) noexcept;
+ QString parseFunctionName (const QString &command) const;
+ QHash parseArgs (const QString &command) const;
QHash mCommands;
diff --git a/src/components/calls/CallsListModel.cpp b/src/components/calls/CallsListModel.cpp
index 41897885d..aa4dadd2b 100644
--- a/src/components/calls/CallsListModel.cpp
+++ b/src/components/calls/CallsListModel.cpp
@@ -24,6 +24,8 @@
#include "../../app/App.hpp"
#include "../../utils/Utils.hpp"
+#include "../conference/ConferenceAddModel.hpp"
+#include "../conference/ConferenceHelperModel.hpp"
#include "../core/CoreManager.hpp"
#include "CallsListModel.hpp"
@@ -89,7 +91,7 @@ void CallsListModel::askForTransfer (CallModel *callModel) {
// -----------------------------------------------------------------------------
-void CallsListModel::launchAudioCall (const QString &sipUri) const {
+void CallsListModel::launchAudioCall (const QString &sipUri, const QHash &headers) const {
shared_ptr core = CoreManager::getInstance()->getCore();
shared_ptr address = core->interpretUrl(::Utils::appStringToCoreString(sipUri));
@@ -100,6 +102,12 @@ void CallsListModel::launchAudioCall (const QString &sipUri) const {
params->enableVideo(false);
CallModel::setRecordFile(params);
+ QHashIterator iterator(headers);
+ while (iterator.hasNext()) {
+ iterator.next();
+ params->addCustomHeader(::Utils::appStringToCoreString(iterator.key()), ::Utils::appStringToCoreString(iterator.value()));
+ }
+
core->inviteAddressWithParams(address, params);
}
@@ -137,8 +145,50 @@ void CallsListModel::terminateAllCalls () const {
void CallsListModel::handleCallStateChanged (const shared_ptr &call, linphone::CallState state) {
switch (state) {
- case linphone::CallStateIncomingReceived:
+ case linphone::CallStateIncomingReceived: {
+ // _______________________________________________________________________________________________________________________________________
+ // _______________________________________________________________________________________________________________________________________
+ addCall(call);
+ if (!call->getToHeader("method").empty()) {
+ shared_ptr core = CoreManager::getInstance()->getCore();
+ qInfo() << QStringLiteral("----Header method----") << Utils::coreStringToAppString(call->getToHeader("method"));
+ if (call->getToHeader("method") == "join-conference") {
+ if (core->getConference() == NULL) { // TODO change this condition, use isInConference() (need to be initiate)
+ qWarning() << QStringLiteral("Not in a conference,responding to join-conference as a call.");
+ break;
+ }
+ shared_ptr currentConference = core->getConference();
+
+ QString conferenceIdHeader = Utils::coreStringToAppString(call->getToHeader("conference-id"));
+
+ qInfo() << QStringLiteral("conference id asked: '%1'").arg(conferenceIdHeader);
+ qWarning() << QStringLiteral("current conference id: '%1'").arg(Utils::coreStringToAppString(currentConference->getId()));
+ if (currentConference->getId().empty() || currentConference->getId() != Utils::appStringToCoreString(conferenceIdHeader)) {
+ qWarning() << QStringLiteral("trying to join conference with invalid conference-id, `%1`").arg(conferenceIdHeader);
+ qWarning() << QStringLiteral("join-conference managed as a call ");
+ break;
+ }
+ qInfo() << QStringLiteral("join conference: `%1`").arg(Utils::coreStringToAppString(currentConference->getId()));
+
+ ConferenceHelperModel helperModel;
+ ConferenceHelperModel::ConferenceAddModel *addModel = helperModel.getAddModel();
+
+ CallModel *callModel = &call->getData("call-model");
+ callModel->accept();
+ addModel->addToConference(call->getRemoteAddress());
+ addModel->update();
+
+ break;
+ }
+ }
+ break;
+ }
+ // _______________________________________________________________________________________________________________________________________
+ // _______________________________________________________________________________________________________________________________________
case linphone::CallStateOutgoingInit:
+ if (!call->getToAddress()->getHeader("method").empty())
+ qInfo() << QStringLiteral("----Header method----") << Utils::coreStringToAppString(call->getToAddress()->getHeader("method"));
+
addCall(call);
break;
diff --git a/src/components/calls/CallsListModel.hpp b/src/components/calls/CallsListModel.hpp
index ae9c92e09..571765133 100644
--- a/src/components/calls/CallsListModel.hpp
+++ b/src/components/calls/CallsListModel.hpp
@@ -45,7 +45,7 @@ public:
void askForTransfer (CallModel *callModel);
- Q_INVOKABLE void launchAudioCall (const QString &sipUri) const;
+ Q_INVOKABLE void launchAudioCall (const QString &sipUri, const QHash &headers = {}) const;
Q_INVOKABLE void launchVideoCall (const QString &sipUri) const;
Q_INVOKABLE int getRunningCallsNumber () const;
diff --git a/src/components/conference/ConferenceHelperModel.cpp b/src/components/conference/ConferenceHelperModel.cpp
index f672aea32..8b4bc4722 100644
--- a/src/components/conference/ConferenceHelperModel.cpp
+++ b/src/components/conference/ConferenceHelperModel.cpp
@@ -24,7 +24,6 @@
#include "../../utils/Utils.hpp"
#include "../core/CoreManager.hpp"
#include "../sip-addresses/SipAddressesProxyModel.hpp"
-#include "ConferenceAddModel.hpp"
#include "ConferenceHelperModel.hpp"
diff --git a/src/components/conference/ConferenceHelperModel.hpp b/src/components/conference/ConferenceHelperModel.hpp
index afde60c30..3b0a51b47 100644
--- a/src/components/conference/ConferenceHelperModel.hpp
+++ b/src/components/conference/ConferenceHelperModel.hpp
@@ -27,17 +27,18 @@
#include
+#include "ConferenceHelperModel.hpp"
+
// =============================================================================
// Sip addresses not in conference.
// Can filter the sip addresses with a pattern.
// =============================================================================
class CallModel;
-class ConferenceAddModel;
namespace linphone {
- class Conference;
- class Core;
+class Conference;
+class Core;
}
class ConferenceHelperModel : public QSortFilterProxyModel {
@@ -53,6 +54,10 @@ public:
QHash roleNames () const override;
+ ConferenceAddModel *getConferenceAddModel () const {
+ return mConferenceAddModel;
+ }
+
Q_INVOKABLE void setFilter (const QString &pattern);
protected:
@@ -60,9 +65,6 @@ protected:
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
private:
- ConferenceAddModel *getConferenceAddModel () const {
- return mConferenceAddModel;
- }
ConferenceAddModel *mConferenceAddModel = nullptr;
diff --git a/src/utils/Utils.hpp b/src/utils/Utils.hpp
index 186c92be6..be8a71793 100644
--- a/src/utils/Utils.hpp
+++ b/src/utils/Utils.hpp
@@ -23,6 +23,7 @@
#ifndef UTILS_H_
#define UTILS_H_
+#include
#include
// =============================================================================
@@ -54,6 +55,46 @@ namespace Utils {
// Returns the same path given in parameter if `filePath` exists.
// Otherwise returns a safe path with a unique number before the extension.
QString getSafeFilePath (const QString &filePath, bool *soFarSoGood = nullptr);
+
+ // Connect once to a member function.
+ template
+ static inline QMetaObject::Connection connectOnce (
+ typename QtPrivate::FunctionPointer::Object *sender,
+ Func1 signal,
+ typename QtPrivate::FunctionPointer::Object *receiver,
+ Func2 slot
+ ) {
+ QMetaObject::Connection connection = QObject::connect(sender, signal, receiver, slot);
+ QMetaObject::Connection *deleter = new QMetaObject::Connection();
+
+ *deleter = QObject::connect(sender, signal, [connection, deleter] {
+ QObject::disconnect(connection);
+ QObject::disconnect(*deleter);
+ delete deleter;
+ });
+
+ return connection;
+ }
+
+ // Connect once to a function.
+ template
+ static inline QMetaObject::Connection connectOnce (
+ typename QtPrivate::FunctionPointer::Object *sender,
+ Func1 signal,
+ const QObject *receiver,
+ Func2 slot
+ ) {
+ QMetaObject::Connection connection = QObject::connect(sender, signal, receiver, slot);
+ QMetaObject::Connection *deleter = new QMetaObject::Connection();
+
+ *deleter = QObject::connect(sender, signal, [connection, deleter] {
+ QObject::disconnect(connection);
+ QObject::disconnect(*deleter);
+ delete deleter;
+ });
+
+ return connection;
+ }
}
#endif // UTILS_H_
diff --git a/submodules/bcmatroska2 b/submodules/bcmatroska2
index 4c7acea97..ac155e025 160000
--- a/submodules/bcmatroska2
+++ b/submodules/bcmatroska2
@@ -1 +1 @@
-Subproject commit 4c7acea973ac94e559d52e45312e90cf4d0f6247
+Subproject commit ac155e025efbcb13778cb436babb80e0f4fd6e72
diff --git a/submodules/belcard b/submodules/belcard
index 38eba4c26..a2e36ce33 160000
--- a/submodules/belcard
+++ b/submodules/belcard
@@ -1 +1 @@
-Subproject commit 38eba4c264b5e45c8650c8ccf05f359541d8c4ae
+Subproject commit a2e36ce337b7cba0bd6fddec5912b7134dc627ba
diff --git a/submodules/belle-sip b/submodules/belle-sip
index 647393a5e..a19b7e3e8 160000
--- a/submodules/belle-sip
+++ b/submodules/belle-sip
@@ -1 +1 @@
-Subproject commit 647393a5e4b49551f34e213c91d80b675c60a7f6
+Subproject commit a19b7e3e833dc121f91452e40658dd80f8f0c145
diff --git a/submodules/belr b/submodules/belr
index df0f66406..a6380eccb 160000
--- a/submodules/belr
+++ b/submodules/belr
@@ -1 +1 @@
-Subproject commit df0f6640647925b1225eba011a40ce988ede5c57
+Subproject commit a6380eccb56bb070712971189912f41eb7f047a3
diff --git a/submodules/linphone b/submodules/linphone
index b9b283dcd..d88e17cd3 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit b9b283dcdb0b19a976df8d5cccba43c373727ee8
+Subproject commit d88e17cd3ab831f2a9ce5ae04f796caff2a93cc2