mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-29 17:59:21 +00:00
- Download configuration file if it is a webfile
- Download the configuration file directly to the config path and overwrite old file - Add an interface to config directory path - Prevent a crash from the deletion of the Handler where we are still using it - Add synchronous mechanism to download file and Instance Manager deletion - Add Command parser features : clean specific keys, parse from list of arguments - Reorder config search to avoid unwanted config file overwrite - Move CLI execution at the end of initialization - Based openAppAfterInit on Manager and not on Handler - Add Call feature to Command line (--call=<SipAddress>) - Launch a call on request - Add generic parameters on show and call method to CLI - Replace connectOnce function that didn't fully work by a connection on context where it is manage by Qt - Remove redundant parser initializations - Update SDK to fix configuration updates and FEC
This commit is contained in:
parent
b378ac59d3
commit
2629e2461d
26 changed files with 450 additions and 141 deletions
|
|
@ -100,6 +100,7 @@ job-centos7-ninja-gcc-package:
|
|||
artifacts:
|
||||
paths:
|
||||
- build/OUTPUT/Packages/*.AppImage
|
||||
when: always
|
||||
expire_in: 1 week
|
||||
|
||||
#################################################
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ job-macosx-makefile-package:
|
|||
- codesign --options runtime,library --verbose -s "$MACOS_SIGNING_IDENTITY" OUTPUT/Packages/Linphone*.dmg
|
||||
- ./../tools/app_notarization.sh
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build/OUTPUT/*
|
||||
when: always
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ job-windows-vs2017-package:
|
|||
artifacts:
|
||||
paths:
|
||||
- results\*
|
||||
when: always
|
||||
expire_in: 1 weeks
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,12 @@ endforeach()
|
|||
if(ENABLE_BUILD_VERBOSE)
|
||||
message("User Args : ${USER_ARGS}")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_GENERATOR_PLATFORM AND WIN32)
|
||||
if(WIN32)
|
||||
if(NOT ${CMAKE_GENERATOR} MATCHES "Ninja")
|
||||
set(CMAKE_GENERATOR_PLATFORM "Win32")
|
||||
message(STATUS "Setting Platform to ${CMAKE_GENERATOR_PLATFORM}")
|
||||
if(NOT CMAKE_GENERATOR_PLATFORM)
|
||||
set(CMAKE_GENERATOR_PLATFORM "Win32")
|
||||
message(STATUS "Setting Platform to ${CMAKE_GENERATOR_PLATFORM}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ if( WIN32)
|
|||
endif()
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)#useful for config.h
|
||||
|
||||
set(QT5_PACKAGES Core Gui Quick Widgets QuickControls2 Svg LinguistTools Concurrent Network)
|
||||
set(QT5_PACKAGES Core Gui Quick Widgets QuickControls2 Svg LinguistTools Concurrent Network Test)
|
||||
if (UNIX AND NOT APPLE)
|
||||
list(APPEND QT5_PACKAGES DBus)
|
||||
endif ()
|
||||
|
|
|
|||
|
|
@ -92,6 +92,22 @@
|
|||
<source>about</source>
|
||||
<translation>About</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>commandLineOptionFetchConfig</source>
|
||||
<translation>specify the %1 configuration file to be fetch. It will be merged with the current configuration.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>commandLineOptionFetchConfigArg</source>
|
||||
<translation>url, path or file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>commandLineOptionCall</source>
|
||||
<translation>make a call</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>commandLineOptionCallArg</source>
|
||||
<translation>sip address</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AssistantAbstractView</name>
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ Exec=@EXECUTABLE_NAME@ %u
|
|||
Icon=@EXECUTABLE_NAME@
|
||||
Terminal=false
|
||||
Categories=Network;Telephony;
|
||||
MimeType=x-scheme-handler/sip-linphone;x-scheme-handler/sip;x-scheme-handler/sips-linphone;x-scheme-handler/sips;x-scheme-handler/tel;x-scheme-handler/callto;
|
||||
MimeType=x-scheme-handler/sip-linphone;x-scheme-handler/sip;x-scheme-handler/sips-linphone;x-scheme-handler/sips;x-scheme-handler/tel;x-scheme-handler/callto;x-scheme-handler/linphone-config;
|
||||
X-PulseAudio-Properties=media.role=phone
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
<string>sips-linphone</string>
|
||||
<string>tel</string>
|
||||
<string>callto</string>
|
||||
<string>linphone-config</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ WriteRegStr HKCR "sip" "URL Protocol" ""
|
|||
WriteRegStr HKCR "sip-linphone" "" "URL:sip-linphone Protocol"
|
||||
WriteRegStr HKCR "sip-linphone" "URL Protocol" ""
|
||||
|
||||
WriteRegStr HKCR "linphone-config" "" "URL:linphone-config Protocol"
|
||||
WriteRegStr HKCR "linphone-config" "URL Protocol" ""
|
||||
|
||||
WriteRegStr HKCR "sips" "" "URL:sips Protocol"
|
||||
WriteRegStr HKCR "sips" "URL Protocol" ""
|
||||
|
||||
|
|
@ -62,6 +65,13 @@ WriteRegStr HKCR "@APPLICATION_NAME@.sips-linphone\Shell\Open" "" ""
|
|||
WriteRegStr HKCR "@APPLICATION_NAME@.sips-linphone\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\""
|
||||
WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "sips-linphone" "@APPLICATION_NAME@.sips-linphone"
|
||||
|
||||
## LINPHONE-CONFIG
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.linphone-config" "" "@APPLICATION_NAME@ linphone-config Protocol"
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.linphone-config\Shell" "" ""
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.linphone-config\Shell\Open" "" ""
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.linphone-config\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\""
|
||||
WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "linphone-config" "@APPLICATION_NAME@.linphone-config"
|
||||
|
||||
## TEL
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.tel" "" "@APPLICATION_NAME@ tel Protocol"
|
||||
WriteRegStr HKCR "@APPLICATION_NAME@.tel\Shell" "" ""
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ DeleteRegKey HKCR "@APPLICATION_NAME@.sip"
|
|||
DeleteRegKey HKCR "@APPLICATION_NAME@.sip-linphone"
|
||||
DeleteRegKey HKCR "@APPLICATION_NAME@.sips"
|
||||
DeleteRegKey HKCR "@APPLICATION_NAME@.sips-linphone"
|
||||
DeleteRegKey HKCR "@APPLICATION_NAME@.linphone-config"
|
||||
DeleteRegKey HKCR "@APPLICATION_NAME@.tel"
|
||||
DeleteRegKey HKCR "@APPLICATION_NAME@.callto"
|
||||
|
||||
|
|
|
|||
|
|
@ -156,18 +156,50 @@ static inline bool installLocale (App &app, QTranslator &translator, const QLoca
|
|||
return translator.load(locale, LanguagePath) && app.installTranslator(&translator);
|
||||
}
|
||||
|
||||
static inline shared_ptr<linphone::Config> getConfigIfExists (const QCommandLineParser &parser) {
|
||||
string configPath(Paths::getConfigFilePath(parser.value("config"), false));
|
||||
if (!Paths::filePathExists(configPath))
|
||||
configPath.clear();
|
||||
static inline string getConfigPathIfExists (const QCommandLineParser &parser) {
|
||||
QString filePath = parser.value("config");
|
||||
string configPath;
|
||||
if(!QUrl(filePath).isRelative()){
|
||||
configPath = Utils::appStringToCoreString(FileDownloader::synchronousDownload(filePath, Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true));
|
||||
}
|
||||
if( configPath == "")
|
||||
configPath = Paths::getConfigFilePath(filePath, false);
|
||||
if( configPath == "" )
|
||||
configPath = Paths::getConfigFilePath("", false);
|
||||
return configPath;
|
||||
}
|
||||
|
||||
static inline shared_ptr<linphone::Config> getConfigIfExists (const string &configPath) {
|
||||
string factoryPath(Paths::getFactoryConfigFilePath());
|
||||
if (!Paths::filePathExists(factoryPath))
|
||||
factoryPath.clear();
|
||||
|
||||
return linphone::Config::newWithFactory(configPath, factoryPath);
|
||||
}
|
||||
|
||||
bool App::setFetchConfig (QCommandLineParser *parser) {
|
||||
bool fetched = false;
|
||||
QString filePath = parser->value("fetch-config");
|
||||
if( !filePath.isEmpty()){
|
||||
if(QUrl(filePath).isRelative()){// this is a file path
|
||||
filePath = Utils::coreStringToAppString(Paths::getConfigFilePath(filePath, false));
|
||||
if(!filePath.isEmpty())
|
||||
filePath = "file://"+filePath;
|
||||
}
|
||||
if(!filePath.isEmpty()){
|
||||
auto instance = CoreManager::getInstance();
|
||||
if(instance){
|
||||
auto core = instance->getCore();
|
||||
if(core){
|
||||
filePath.replace('\\','/');
|
||||
core->setProvisioningUri(Utils::appStringToCoreString(filePath));
|
||||
parser->process(cleanParserKeys(parser, QStringList("fetch-config")));// Remove this parameter from the parser
|
||||
fetched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fetched;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
||||
|
|
@ -180,7 +212,7 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
|
|||
mParser->process(*this);
|
||||
|
||||
// Initialize logger.
|
||||
shared_ptr<linphone::Config> config = getConfigIfExists(*mParser);
|
||||
shared_ptr<linphone::Config> config = getConfigIfExists(getConfigPathIfExists(*mParser));
|
||||
Logger::init(config);
|
||||
if (mParser->isSet("verbose"))
|
||||
Logger::getInstance()->setVerbose(true);
|
||||
|
|
@ -195,7 +227,6 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
|
|||
initLocale(config);
|
||||
|
||||
if (mParser->isSet("help")) {
|
||||
createParser();
|
||||
mParser->showHelp();
|
||||
}
|
||||
|
||||
|
|
@ -221,6 +252,30 @@ App::~App () {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
QStringList App::cleanParserKeys(QCommandLineParser * parser, QStringList keys){
|
||||
QStringList oldArguments = parser->optionNames();
|
||||
QStringList parameters;
|
||||
parameters << "dummy";
|
||||
for(int i = 0 ; i < oldArguments.size() ; ++i){
|
||||
if( !keys.contains(oldArguments[i])){
|
||||
if( mParser->value(oldArguments[i]).isEmpty())
|
||||
parameters << "--"+oldArguments[i];
|
||||
else
|
||||
parameters << "--"+oldArguments[i]+"="+parser->value(oldArguments[i]);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void App::processArguments(QHash<QString,QString> args){
|
||||
QList<QString> keys = args.keys();
|
||||
QStringList parameters = cleanParserKeys(mParser, keys);
|
||||
for(auto i = keys.begin() ; i != keys.end() ; ++i){
|
||||
parameters << "--"+(*i)+"="+args.value(*i);
|
||||
}
|
||||
mParser->process(parameters);
|
||||
}
|
||||
|
||||
static QQuickWindow *createSubWindow (QQmlApplicationEngine *engine, const char *path) {
|
||||
qInfo() << QStringLiteral("Creating subwindow: `%1`.").arg(path);
|
||||
|
||||
|
|
@ -243,18 +298,22 @@ static QQuickWindow *createSubWindow (QQmlApplicationEngine *engine, const char
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
void App::initContentApp () {
|
||||
shared_ptr<linphone::Config> config = getConfigIfExists(*mParser);
|
||||
std::string configPath;
|
||||
shared_ptr<linphone::Config> config;
|
||||
bool mustBeIconified = false;
|
||||
bool needRestart = true;
|
||||
|
||||
// Destroy qml components and linphone core if necessary.
|
||||
if (mEngine) {
|
||||
needRestart = false;
|
||||
setFetchConfig(mParser);
|
||||
setOpened(false);
|
||||
qInfo() << QStringLiteral("Restarting app...");
|
||||
delete mEngine;
|
||||
|
||||
mNotifier = nullptr;
|
||||
mSystemTrayIcon = nullptr;
|
||||
|
||||
//
|
||||
CoreManager::uninit();
|
||||
removeTranslator(mTranslator);
|
||||
removeTranslator(mDefaultTranslator);
|
||||
|
|
@ -262,8 +321,12 @@ void App::initContentApp () {
|
|||
delete mDefaultTranslator;
|
||||
mTranslator = new DefaultTranslator(this);
|
||||
mDefaultTranslator = new DefaultTranslator(this);
|
||||
configPath = getConfigPathIfExists(*mParser);
|
||||
config = getConfigIfExists(configPath);
|
||||
initLocale(config);
|
||||
} else {
|
||||
configPath = getConfigPathIfExists(*mParser);
|
||||
config = getConfigIfExists(configPath);
|
||||
// Update and download codecs.
|
||||
VideoCodecsModel::updateCodecs();
|
||||
VideoCodecsModel::downloadUpdatableCodecs(this);
|
||||
|
|
@ -289,18 +352,8 @@ void App::initContentApp () {
|
|||
mColors->useConfig(config);
|
||||
|
||||
// Init core.
|
||||
CoreManager::init(this, mParser->value("config"));
|
||||
CoreManager::init(this, Utils::coreStringToAppString(configPath));
|
||||
|
||||
// Execute command argument if needed.
|
||||
if (!mEngine) {
|
||||
const QString commandArgument = getCommandArgument();
|
||||
if (!commandArgument.isEmpty()) {
|
||||
Cli::CommandFormat format;
|
||||
Cli::executeCommand(commandArgument, &format);
|
||||
if (format == Cli::UriFormat)
|
||||
mustBeIconified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Init engine content.
|
||||
mEngine = new QQmlApplicationEngine();
|
||||
|
|
@ -343,12 +396,22 @@ void App::initContentApp () {
|
|||
qFatal("Unable to open main window.");
|
||||
|
||||
QObject::connect(
|
||||
CoreManager::getInstance()->getHandlers().get(),
|
||||
&CoreHandlers::coreStarted,
|
||||
[this, mustBeIconified]() {
|
||||
openAppAfterInit(mustBeIconified);
|
||||
CoreManager::getInstance(),
|
||||
&CoreManager::coreStarted, CoreManager::getInstance(),
|
||||
[this, mustBeIconified]() mutable {
|
||||
if(CoreManager::getInstance()->started())
|
||||
openAppAfterInit(mustBeIconified);
|
||||
}
|
||||
);
|
||||
|
||||
// Execute command argument if needed.
|
||||
const QString commandArgument = getCommandArgument();
|
||||
if (!commandArgument.isEmpty()) {
|
||||
Cli::CommandFormat format;
|
||||
Cli::executeCommand(commandArgument, &format);
|
||||
if (format == Cli::UriFormat || format == Cli::UrlFormat )
|
||||
mustBeIconified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -434,6 +497,8 @@ void App::createParser () {
|
|||
{ "cli-help", tr("commandLineOptionCliHelp").replace("%1", APPLICATION_NAME) },
|
||||
{ { "v", "version" }, tr("commandLineOptionVersion") },
|
||||
{ "config", tr("commandLineOptionConfig").replace("%1", EXECUTABLE_NAME), tr("commandLineOptionConfigArg") },
|
||||
{ "fetch-config", tr("commandLineOptionFetchConfig").replace("%1", EXECUTABLE_NAME), tr("commandLineOptionFetchConfigArg") },
|
||||
{ { "c", "call" }, tr("commandLineOptionCall").replace("%1", EXECUTABLE_NAME),tr("commandLineOptionCallArg") },
|
||||
#ifndef Q_OS_MACOS
|
||||
{ "iconified", tr("commandLineOptionIconified") },
|
||||
#endif // ifndef Q_OS_MACOS
|
||||
|
|
@ -782,14 +847,14 @@ void App::setAutoStart (bool enabled) {
|
|||
|
||||
void App::openAppAfterInit (bool mustBeIconified) {
|
||||
qInfo() << QStringLiteral("Open " APPLICATION_NAME " app.");
|
||||
|
||||
auto coreManager = CoreManager::getInstance();
|
||||
// Create other windows.
|
||||
mCallsWindow = createSubWindow(mEngine, QmlViewCallsWindow);
|
||||
mSettingsWindow = createSubWindow(mEngine, QmlViewSettingsWindow);
|
||||
QObject::connect(mSettingsWindow, &QWindow::visibilityChanged, this, [](QWindow::Visibility visibility) {
|
||||
QObject::connect(mSettingsWindow, &QWindow::visibilityChanged, this, [coreManager](QWindow::Visibility visibility) {
|
||||
if (visibility == QWindow::Hidden) {
|
||||
qInfo() << QStringLiteral("Update nat policy.");
|
||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||
shared_ptr<linphone::Core> core = coreManager->getCore();
|
||||
core->setNatPolicy(core->getNatPolicy());
|
||||
}
|
||||
});
|
||||
|
|
@ -802,16 +867,10 @@ void App::openAppAfterInit (bool mustBeIconified) {
|
|||
qWarning("System tray not found on this system.");
|
||||
else
|
||||
setTrayIcon();
|
||||
|
||||
if (!mustBeIconified)
|
||||
smartShowWindow(mainWindow);
|
||||
#else
|
||||
Q_UNUSED(mustBeIconified);
|
||||
smartShowWindow(mainWindow);
|
||||
#endif // ifndef __APPLE__
|
||||
|
||||
// Display Assistant if it does not exist proxy config.
|
||||
if (CoreManager::getInstance()->getCore()->getProxyConfigList().empty())
|
||||
if (coreManager->getCore()->getProxyConfigList().empty())
|
||||
QMetaObject::invokeMethod(mainWindow, "setView", Q_ARG(QVariant, AssistantViewName), Q_ARG(QVariant, QString("")));
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECK
|
||||
|
|
@ -824,7 +883,36 @@ void App::openAppAfterInit (bool mustBeIconified) {
|
|||
checkForUpdate();
|
||||
#endif // ifdef ENABLE_UPDATE_CHECK
|
||||
|
||||
setOpened(true);
|
||||
if(setFetchConfig(mParser))
|
||||
restart();
|
||||
else{
|
||||
// Launch call if wanted and clean parser
|
||||
if( mParser->isSet("call")){
|
||||
QString sipAddress = mParser->value("call");
|
||||
mParser->parse(cleanParserKeys(mParser, QStringList("call")));// Clean call from parser
|
||||
if(coreManager->started()){
|
||||
coreManager->getCallsListModel()->launchAudioCall(sipAddress);
|
||||
}else{
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(CoreManager::getInstance(), &CoreManager::coreStarted,context,
|
||||
[sipAddress,coreManager, context]() mutable {
|
||||
if(context){
|
||||
delete context;
|
||||
context = nullptr;
|
||||
coreManager->getCallsListModel()->launchAudioCall(sipAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
if (!mustBeIconified)
|
||||
smartShowWindow(mainWindow);
|
||||
#else
|
||||
Q_UNUSED(mustBeIconified);
|
||||
smartShowWindow(mainWindow);
|
||||
#endif
|
||||
setOpened(true);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -55,9 +55,13 @@ public:
|
|||
~App ();
|
||||
|
||||
void initContentApp ();
|
||||
QStringList cleanParserKeys(QCommandLineParser * parser, QStringList keys);// Get all options from parser and remove the selected keys. Return the result that can be passed to parser process.
|
||||
void processArguments(QHash<QString,QString> args);
|
||||
|
||||
QString getCommandArgument ();
|
||||
|
||||
bool setFetchConfig (QCommandLineParser *parser);
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
bool event (QEvent *event) override;
|
||||
#endif // ifdef Q_OS_MACOS
|
||||
|
|
|
|||
|
|
@ -67,7 +67,17 @@ AppController::AppController (int &argc, char *argv[]) {
|
|||
#endif // ifdef Q_OS_MACOS
|
||||
|
||||
QString command = mApp->getCommandArgument();
|
||||
mApp->sendMessage(command.isEmpty() ? "show" : command.toLocal8Bit(), -1);
|
||||
if( command.isEmpty()){
|
||||
command = "show";
|
||||
QStringList parametersList;
|
||||
for(int i = 1 ; i < argc ; ++i){
|
||||
QString a = argv[i];
|
||||
if(a.startsWith("--"))// show is a command : remove <-->-style parameters
|
||||
a.remove(0,2);
|
||||
command += " "+a;
|
||||
}
|
||||
}
|
||||
mApp->sendMessage(command.toLocal8Bit(), -1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,24 @@ using namespace std;
|
|||
// API.
|
||||
// =============================================================================
|
||||
|
||||
static void cliShow (QHash<QString, QString> &) {
|
||||
static void cliShow (QHash<QString, QString> &args) {
|
||||
App *app = App::getInstance();
|
||||
if( args.size() > 0){
|
||||
app->processArguments(args);
|
||||
app->initContentApp();
|
||||
}
|
||||
app->smartShowWindow(app->getMainWindow());
|
||||
}
|
||||
|
||||
static void cliCall (QHash<QString, QString> &args) {
|
||||
CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sip-address"]);
|
||||
if(args.size() > 1){// Call with options
|
||||
App *app = App::getInstance();
|
||||
args["call"] = args["sip-address"];// Swap cli def to parser
|
||||
args.remove("sip-address");
|
||||
app->processArguments(args);
|
||||
app->initContentApp();
|
||||
}else
|
||||
CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sip-address"]);
|
||||
}
|
||||
|
||||
static void cliJoinConference (QHash<QString, QString> &args) {
|
||||
|
|
@ -247,24 +258,26 @@ Cli::Command::Command (
|
|||
const QString &functionName,
|
||||
const char *functionDescription,
|
||||
Cli::Function function,
|
||||
const QHash<QString, Cli::Argument> &argsScheme
|
||||
const QHash<QString, Cli::Argument> &argsScheme,
|
||||
const bool &genericArguments
|
||||
) :
|
||||
mFunctionName(functionName),
|
||||
mFunctionDescription(functionDescription),
|
||||
mFunction(function),
|
||||
mArgsScheme(argsScheme) {}
|
||||
mArgsScheme(argsScheme),
|
||||
mGenericArguments(genericArguments) {}
|
||||
|
||||
void Cli::Command::execute (QHash<QString, QString> &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;
|
||||
if(!mGenericArguments){// 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 (!mArgsScheme[argName].isOptional && (!args.contains(argName) || args[argName].isEmpty())) {
|
||||
|
|
@ -281,16 +294,38 @@ void Cli::Command::execute (QHash<QString, QString> &args) const {
|
|||
(*mFunction)(args);
|
||||
} else {
|
||||
Function f = mFunction;
|
||||
Utils::connectOnce(app, &App::opened, app, [f, args] {
|
||||
qInfo() << QStringLiteral("Execute deferred command:") << args;
|
||||
QHash<QString, QString> fuckConst = args;
|
||||
(*f)(fuckConst);
|
||||
});
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(app, &App::opened,
|
||||
[f, args, context]()mutable {
|
||||
if(context){
|
||||
delete context;
|
||||
context = nullptr;
|
||||
qInfo() << QStringLiteral("Execute deferred command:") << args;
|
||||
QHash<QString, QString> fuckConst = args;
|
||||
(*f)(fuckConst);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Cli::Command::executeUri (const shared_ptr<linphone::Address> &address) const {
|
||||
QHash<QString, QString> args;
|
||||
QString qAddress = Utils::coreStringToAppString(address->asString());
|
||||
QUrl url(qAddress);
|
||||
QString query = url.query();
|
||||
|
||||
QStringList parameters = query.split('&');
|
||||
for(int i = 0 ; i < parameters.size() ; ++i){
|
||||
QStringList parameter = parameters[i].split('=');
|
||||
if( parameter[0] != "method"){
|
||||
if(parameter.size() > 1)
|
||||
args[parameter[0]] = QByteArray::fromBase64(parameter[1].toUtf8() );
|
||||
else
|
||||
args[parameter[0]] = "";
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check if there is too much headers.
|
||||
for (const auto &argName : mArgsScheme.keys()) {
|
||||
const string header = address->getHeader(Utils::appStringToCoreString(argName));
|
||||
|
|
@ -301,6 +336,25 @@ void Cli::Command::executeUri (const shared_ptr<linphone::Address> &address) con
|
|||
execute(args);
|
||||
}
|
||||
|
||||
// pUrl can be `anytoken?p1=x&p2=y` or `p1=x&p2=y`. It will only use p1 and p2
|
||||
void Cli::Command::executeUrl (const QString &pUrl) const {
|
||||
QHash<QString, QString> args;
|
||||
QUrl url(pUrl);
|
||||
QString query = (url.hasQuery()?url.query():pUrl);
|
||||
|
||||
QStringList parameters = query.split('&');
|
||||
for(int i = 0 ; i < parameters.size() ; ++i){
|
||||
QStringList parameter = parameters[i].split('=');
|
||||
if( parameter[0] != "method"){
|
||||
if(parameter.size() > 1)
|
||||
args[parameter[0]] = QByteArray::fromBase64(parameter[1].toUtf8() );
|
||||
else
|
||||
args[parameter[0]] = "";
|
||||
}
|
||||
}
|
||||
execute(args);
|
||||
}
|
||||
|
||||
QString Cli::Command::getFunctionSyntax () const {
|
||||
QString functionSyntax;
|
||||
functionSyntax += QStringLiteral("\"");
|
||||
|
|
@ -333,10 +387,10 @@ QRegExp Cli::mRegExpArgs("(?:(?:([\\w-]+)\\s*)=\\s*(?:\"([^\"\\\\]*(?:\\\\.[^\"\
|
|||
QRegExp Cli::mRegExpFunctionName("^\\s*([a-z-]+)\\s*");
|
||||
|
||||
QMap<QString, Cli::Command> Cli::mCommands = {
|
||||
createCommand("show", QT_TR_NOOP("showFunctionDescription"), cliShow),
|
||||
createCommand("show", QT_TR_NOOP("showFunctionDescription"), cliShow, QHash<QString, Argument>(), true),
|
||||
createCommand("call", QT_TR_NOOP("callFunctionDescription"), cliCall, {
|
||||
{ "sip-address", {} }
|
||||
}),
|
||||
}, true),
|
||||
createCommand("initiate-conference", QT_TR_NOOP("initiateConferenceFunctionDescription"), cliInitiateConference, {
|
||||
{ "sip-address", {} }, { "conference-id", {} }
|
||||
}),
|
||||
|
|
@ -364,43 +418,52 @@ void Cli::executeCommand (const QString &command, CommandFormat *format) {
|
|||
QHash<QString, QString> args = parseArgs(command);
|
||||
mCommands[functionName].execute(args);
|
||||
}
|
||||
|
||||
if (format)
|
||||
*format = CliFormat;
|
||||
|
||||
return;
|
||||
}else{
|
||||
string scheme = address->getScheme();
|
||||
bool ok = false;
|
||||
for (const string &validScheme : { "sip", "sip-linphone", "sips", "sips-linphone", "tel", "callto", "linphone-config" })
|
||||
if (scheme == validScheme)
|
||||
ok = true;
|
||||
if( !ok){
|
||||
qWarning() << QStringLiteral("Not a valid uri: `%1` Unsupported scheme: `%2`.").arg(command).arg(Utils::coreStringToAppString(scheme));
|
||||
return;
|
||||
}else{
|
||||
if( scheme == "linphone-config" ){
|
||||
QHash<QString, QString> args = parseArgs(command);
|
||||
if(args.contains("fetch-config"))
|
||||
args["fetch-config"] = QByteArray::fromBase64(args["fetch-config"].toUtf8() );
|
||||
else {
|
||||
QUrl url(command);
|
||||
url.setScheme("https");
|
||||
args["fetch-config"] = url.toString();
|
||||
}
|
||||
if (format)
|
||||
*format = CliFormat;
|
||||
mCommands["show"].execute(args);
|
||||
}else{
|
||||
if (format)
|
||||
*format = UriFormat;
|
||||
// Execute uri command.
|
||||
qInfo() << QStringLiteral("Detecting uri command: `%1`...").arg(command);
|
||||
if (address->getUsername().empty()) {
|
||||
qWarning() << QStringLiteral("Failed to execute command. No username given.");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format)
|
||||
*format = UriFormat;
|
||||
|
||||
// Execute uri command.
|
||||
qInfo() << QStringLiteral("Detecting uri command: `%1`...").arg(command);
|
||||
|
||||
if (address->getUsername().empty()) {
|
||||
qWarning() << QStringLiteral("Failed to execute command. No username given.");
|
||||
return;
|
||||
}
|
||||
|
||||
string scheme = address->getScheme();
|
||||
for (const string &validScheme : { "sip", "sip-linphone", "sips", "sips-linphone", "tel", "callto" })
|
||||
if (scheme == validScheme)
|
||||
goto success;
|
||||
qWarning() << QStringLiteral("Not a valid uri: `%1` Unsupported scheme: `%2`.")
|
||||
.arg(command).arg(Utils::coreStringToAppString(scheme));
|
||||
return;
|
||||
|
||||
success:
|
||||
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);
|
||||
}
|
||||
|
||||
void Cli::showHelp () {
|
||||
|
|
@ -425,9 +488,10 @@ pair<QString, Cli::Command> Cli::createCommand (
|
|||
const QString &functionName,
|
||||
const char *functionDescription,
|
||||
Function function,
|
||||
const QHash<QString, Argument> &argsScheme
|
||||
const QHash<QString, Argument> &argsScheme,
|
||||
const bool &genericArguments
|
||||
) {
|
||||
return { functionName, Cli::Command(functionName, functionDescription, function, argsScheme) };
|
||||
return { functionName, Cli::Command(functionName, functionDescription, function, argsScheme, genericArguments) };
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -59,11 +59,13 @@ class Cli : public QObject {
|
|||
const QString &functionName,
|
||||
const char *functionDescription,
|
||||
Function function,
|
||||
const QHash<QString, Argument> &argsScheme
|
||||
const QHash<QString, Argument> &argsScheme,
|
||||
const bool &genericArguments=false
|
||||
);
|
||||
|
||||
void execute (QHash<QString, QString> &args) const;
|
||||
void executeUri (const std::shared_ptr<linphone::Address> &address) const;
|
||||
void executeUrl (const QString &url) const;
|
||||
|
||||
const char *getFunctionDescription () const {
|
||||
return mFunctionDescription;
|
||||
|
|
@ -76,13 +78,15 @@ class Cli : public QObject {
|
|||
const char *mFunctionDescription;
|
||||
Function mFunction = nullptr;
|
||||
QHash<QString, Argument> mArgsScheme;
|
||||
bool mGenericArguments=false;// Used to avoid check on arguments
|
||||
};
|
||||
|
||||
public:
|
||||
enum CommandFormat {
|
||||
UnknownFormat,
|
||||
CliFormat,
|
||||
UriFormat
|
||||
UriFormat, // Parameters are in base64
|
||||
UrlFormat
|
||||
};
|
||||
|
||||
static void executeCommand (const QString &command, CommandFormat *format = nullptr);
|
||||
|
|
@ -96,7 +100,8 @@ private:
|
|||
const QString &functionName,
|
||||
const char *functionDescription,
|
||||
Function function,
|
||||
const QHash<QString, Argument> &argsScheme = QHash<QString, Argument>()
|
||||
const QHash<QString, Argument> &argsScheme = QHash<QString, Argument>(),
|
||||
const bool &genericArguments=false
|
||||
);
|
||||
|
||||
static QString parseFunctionName (const QString &command);
|
||||
|
|
|
|||
|
|
@ -215,11 +215,25 @@ string Paths::getCodecsDirPath () {
|
|||
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PathCodecs);
|
||||
}
|
||||
|
||||
string Paths::getConfigFilePath (const QString &configPath, bool writable) {
|
||||
const QString path = configPath.isEmpty()
|
||||
? getAppConfigFilePath()
|
||||
: QFileInfo(configPath).absoluteFilePath();
|
||||
string Paths::getConfigDirPath (bool writable) {
|
||||
return writable ? getWritableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)+QDir::separator()) : getReadableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)+QDir::separator());
|
||||
}
|
||||
|
||||
string Paths::getConfigFilePath (const QString &configPath, bool writable) {
|
||||
QString path;
|
||||
if( !configPath.isEmpty()){
|
||||
QFileInfo file(configPath);
|
||||
if( !writable && (!file.exists() || !file.isFile())){// This file cannot be found. Check if it exists in standard folder
|
||||
QString defaultConfigPath = Utils::coreStringToAppString(getConfigDirPath(false));
|
||||
file = QFileInfo(defaultConfigPath+QDir::separator()+configPath);
|
||||
if( !file.exists() || !file.isFile())
|
||||
path = "";
|
||||
else
|
||||
path = file.absoluteFilePath();
|
||||
}else
|
||||
path = file.absoluteFilePath();
|
||||
}else
|
||||
path = getAppConfigFilePath();
|
||||
return writable ? getWritableFilePath(path) : getReadableFilePath(path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace Paths {
|
|||
std::string getCallHistoryFilePath ();
|
||||
std::string getCapturesDirPath ();
|
||||
std::string getCodecsDirPath ();
|
||||
std::string getConfigDirPath (bool writable = true);
|
||||
std::string getConfigFilePath (const QString &configPath = QString(), bool writable = true);
|
||||
std::string getDownloadDirPath ();
|
||||
std::string getFactoryConfigFilePath ();
|
||||
|
|
|
|||
|
|
@ -113,7 +113,23 @@ void CallsListModel::launchAudioCall (const QString &sipAddress, const QHash<QSt
|
|||
}
|
||||
params->setProxyConfig(core->getDefaultProxyConfig());
|
||||
CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
|
||||
core->inviteAddressWithParams(address, params);
|
||||
shared_ptr<linphone::ProxyConfig> currentProxyConfig = core->getDefaultProxyConfig();
|
||||
if(currentProxyConfig){
|
||||
if(currentProxyConfig->getState() == linphone::RegistrationState::Ok)
|
||||
core->inviteAddressWithParams(address, params);
|
||||
else{
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged,context,
|
||||
[address,core,params,currentProxyConfig, context](const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state) mutable {
|
||||
if(context && proxyConfig==currentProxyConfig && state==linphone::RegistrationState::Ok){
|
||||
delete context;
|
||||
context = nullptr;
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
}else
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
|
||||
void CallsListModel::launchVideoCall (const QString &sipAddress) const {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ CoreHandlers::CoreHandlers (CoreManager *coreManager) {
|
|||
|
||||
CoreHandlers::~CoreHandlers () {
|
||||
delete mCoreStartedLock;
|
||||
mCoreStartedLock = nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -66,7 +67,6 @@ void CoreHandlers::handleCoreCreated () {
|
|||
Q_ASSERT(mCoreCreated == false);
|
||||
mCoreCreated = true;
|
||||
notifyCoreStarted();
|
||||
|
||||
mCoreStartedLock->unlock();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <QtConcurrent>
|
||||
#include <QTimer>
|
||||
#include <QFile>
|
||||
|
||||
#include <QTest>
|
||||
#include "config.h"
|
||||
|
||||
#include "app/paths/Paths.hpp"
|
||||
|
|
@ -79,6 +79,7 @@ CoreManager::CoreManager (QObject *parent, const QString &configPath) :
|
|||
createLinphoneCore(configPath);
|
||||
qInfo() << QStringLiteral("Core created. Enable iterate.");
|
||||
mInstance->mCbsTimer->start();
|
||||
std::shared_ptr<CoreHandlers> h = mInstance->getHandlers();// Protect handler as we will enter its function where it can be deleted (like while restarting)
|
||||
emit mInstance->coreCreated();
|
||||
});
|
||||
|
||||
|
|
@ -171,8 +172,17 @@ void CoreManager::init (QObject *parent, const QString &configPath) {
|
|||
|
||||
void CoreManager::uninit () {
|
||||
if (mInstance) {
|
||||
delete mInstance;
|
||||
mInstance = nullptr;
|
||||
connect(mInstance, &QObject::destroyed, []()mutable{
|
||||
mInstance = nullptr;
|
||||
qInfo() << "Linphone Core is destroyed";
|
||||
});
|
||||
mInstance->mCbsTimer->stop();
|
||||
mInstance->deleteLater();// Ensure to take time to delete the instance
|
||||
QTest::qWaitFor([&]() {return mInstance == nullptr;},10000);
|
||||
if( mInstance){
|
||||
qWarning() << "Linphone Core couldn't destroy in time. It may lead to have multiple session of Linphone Core";
|
||||
mInstance = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ public:
|
|||
}
|
||||
|
||||
std::shared_ptr<linphone::Core> getCore () {
|
||||
Q_CHECK_PTR(mCore);
|
||||
return mCore;
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +109,11 @@ public:
|
|||
return mAccountSettingsModel;
|
||||
}
|
||||
|
||||
static CoreManager *getInstance () {
|
||||
Q_CHECK_PTR(mInstance);
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Initialization.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -117,11 +121,6 @@ public:
|
|||
static void init (QObject *parent, const QString &configPath);
|
||||
static void uninit ();
|
||||
|
||||
static CoreManager *getInstance () {
|
||||
Q_CHECK_PTR(mInstance);
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Must be used in a qml scene.
|
||||
|
|
@ -136,6 +135,8 @@ public:
|
|||
int getMissedCallCount(const QString &peerAddress, const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines)
|
||||
int getMissedCallCountFromLocal(const QString &localAddress) const;// Get missed call count from a chat (useful for showing bubbles on Timelines)
|
||||
|
||||
static bool isInstanciated(){return mInstance!=nullptr;}
|
||||
|
||||
signals:
|
||||
void coreCreated ();
|
||||
void coreStarted ();
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void EventCountNotifier::notifyEventCount (int n) {
|
|||
|
||||
void EventCountNotifier::update () {
|
||||
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
|
||||
Q_CHECK_PTR(sysTrayIcon);
|
||||
sysTrayIcon->setIcon(QIcon(mDisplayCounter ? *mBufWithCounter : *mBuf));
|
||||
if(sysTrayIcon)
|
||||
sysTrayIcon->setIcon(QIcon(mDisplayCounter ? *mBufWithCounter : *mBuf));
|
||||
mDisplayCounter = !mDisplayCounter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QTest>
|
||||
#include "app/paths/Paths.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
|
|
@ -31,13 +32,15 @@ namespace {
|
|||
constexpr char cDefaultFileName[] = "download";
|
||||
}
|
||||
|
||||
static QString getDownloadFilePath (const QString &folder, const QUrl &url) {
|
||||
static QString getDownloadFilePath (const QString &folder, const QUrl &url, const bool& overwrite) {
|
||||
QFileInfo fileInfo(url.path());
|
||||
QString fileName = fileInfo.fileName();
|
||||
if (fileName.isEmpty())
|
||||
fileName = cDefaultFileName;
|
||||
|
||||
fileName.prepend(folder);
|
||||
if( overwrite && QFile::exists(fileName))
|
||||
QFile::remove(fileName);
|
||||
if (!QFile::exists(fileName))
|
||||
return fileName;
|
||||
|
||||
|
|
@ -89,12 +92,15 @@ void FileDownloader::download () {
|
|||
#endif
|
||||
|
||||
if (mDownloadFolder.isEmpty()) {
|
||||
mDownloadFolder = CoreManager::getInstance()->getSettingsModel()->getDownloadFolder();
|
||||
if(CoreManager::isInstanciated())
|
||||
mDownloadFolder = CoreManager::getInstance()->getSettingsModel()->getDownloadFolder();
|
||||
else
|
||||
mDownloadFolder = QDir::cleanPath(Utils::coreStringToAppString(Paths::getDownloadDirPath ()) + QDir::separator());
|
||||
emit downloadFolderChanged(mDownloadFolder);
|
||||
}
|
||||
|
||||
Q_ASSERT(!mDestinationFile.isOpen());
|
||||
mDestinationFile.setFileName(getDownloadFilePath(QDir::cleanPath(mDownloadFolder) + QDir::separator(), mUrl));
|
||||
mDestinationFile.setFileName(getDownloadFilePath(QDir::cleanPath(mDownloadFolder) + QDir::separator(), mUrl, mOverwriteFile));
|
||||
if (!mDestinationFile.open(QIODevice::WriteOnly))
|
||||
emitOutputError();
|
||||
else {
|
||||
|
|
@ -210,6 +216,43 @@ void FileDownloader::setDownloadFolder (const QString &downloadFolder) {
|
|||
}
|
||||
}
|
||||
|
||||
QString FileDownloader::getDestinationFileName () const{
|
||||
return mDestinationFile.fileName();
|
||||
}
|
||||
|
||||
void FileDownloader::setOverwriteFile(const bool &overwrite){
|
||||
mOverwriteFile = overwrite;
|
||||
}
|
||||
|
||||
QString FileDownloader::synchronousDownload(const QUrl &url, const QString &destinationFolder, const bool &overwriteFile){
|
||||
QString filePath;
|
||||
FileDownloader downloader;
|
||||
if(url.isRelative())
|
||||
qWarning() << "FileDownloader: The specified URL is not valid";
|
||||
else{
|
||||
bool isOver = false;
|
||||
bool * pIsOver = &isOver;
|
||||
downloader.setUrl(url);
|
||||
downloader.setOverwriteFile(overwriteFile);
|
||||
downloader.setDownloadFolder(destinationFolder);
|
||||
connect(&downloader, &FileDownloader::downloadFinished, [pIsOver]()mutable{
|
||||
*pIsOver=true;
|
||||
});
|
||||
connect(&downloader, &FileDownloader::downloadFailed, [pIsOver]()mutable{
|
||||
*pIsOver=true;
|
||||
});
|
||||
downloader.download();
|
||||
if(QTest::qWaitFor([&]() {return isOver;}, DefaultTimeout)){
|
||||
filePath = downloader.getDestinationFileName();
|
||||
if(!QFile::exists(filePath)) {
|
||||
filePath = "";
|
||||
qWarning() << "FileDownloader: Cannot download the specified file";
|
||||
}
|
||||
}
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
qint64 FileDownloader::getReadBytes () const {
|
||||
return mReadBytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,13 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QtNetwork>
|
||||
#include <QThread>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class QSslError;
|
||||
|
||||
class FileDownloader : public QObject {
|
||||
class FileDownloader : public QObject{
|
||||
Q_OBJECT;
|
||||
|
||||
// TODO: Add an error property to use in UI.
|
||||
|
|
@ -57,6 +58,11 @@ public:
|
|||
QString getDownloadFolder () const;
|
||||
void setDownloadFolder (const QString &downloadFolder);
|
||||
|
||||
QString getDestinationFileName () const;
|
||||
|
||||
void setOverwriteFile(const bool &overwrite);
|
||||
static QString synchronousDownload(const QUrl &url, const QString &destinationFolder, const bool &overwriteFile);// Return the filpath. Empty if nof file could be downloaded
|
||||
|
||||
signals:
|
||||
void urlChanged (const QUrl &url);
|
||||
void downloadFolderChanged (const QString &downloadFolder);
|
||||
|
|
@ -95,6 +101,7 @@ private:
|
|||
qint64 mReadBytes = 0;
|
||||
qint64 mTotalBytes = 0;
|
||||
bool mDownloading = false;
|
||||
bool mOverwriteFile = false;
|
||||
|
||||
QPointer<QNetworkReply> mNetworkReply;
|
||||
QNetworkAccessManager mManager;
|
||||
|
|
|
|||
|
|
@ -263,37 +263,51 @@ QStringList SettingsModel::getPlaybackDevices () const {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
QString SettingsModel::getCaptureDevice () const {
|
||||
return Utils::coreStringToAppString(
|
||||
CoreManager::getInstance()->getCore()->getCaptureDevice()
|
||||
);
|
||||
auto audioDevice = CoreManager::getInstance()->getCore()->getInputAudioDevice();
|
||||
return Utils::coreStringToAppString(audioDevice? audioDevice->getId() : CoreManager::getInstance()->getCore()->getCaptureDevice());
|
||||
}
|
||||
|
||||
void SettingsModel::setCaptureDevice (const QString &device) {
|
||||
CoreManager::getInstance()->getCore()->setCaptureDevice(
|
||||
Utils::appStringToCoreString(device)
|
||||
);
|
||||
emit captureDeviceChanged(device);
|
||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||
createCaptureGraph();
|
||||
}
|
||||
std::string devId = Utils::appStringToCoreString(device);
|
||||
auto list = CoreManager::getInstance()->getCore()->getExtendedAudioDevices();
|
||||
auto audioDevice = find_if(list.cbegin(), list.cend(), [&] ( const std::shared_ptr<linphone::AudioDevice> & audioItem) {
|
||||
return audioItem->getId() == devId;
|
||||
});
|
||||
if(audioDevice != list.cend()){
|
||||
CoreManager::getInstance()->getCore()->setCaptureDevice(devId);
|
||||
CoreManager::getInstance()->getCore()->setInputAudioDevice(*audioDevice);
|
||||
emit captureDeviceChanged(device);
|
||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||
createCaptureGraph();
|
||||
}
|
||||
}else
|
||||
qWarning() << "Cannot set Capture device. The ID cannot be matched with an existant device : " << device;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
QString SettingsModel::getPlaybackDevice () const {
|
||||
return Utils::coreStringToAppString(
|
||||
CoreManager::getInstance()->getCore()->getPlaybackDevice()
|
||||
);
|
||||
auto audioDevice = CoreManager::getInstance()->getCore()->getOutputAudioDevice();
|
||||
return Utils::coreStringToAppString(audioDevice? audioDevice->getId() : CoreManager::getInstance()->getCore()->getPlaybackDevice());
|
||||
}
|
||||
|
||||
void SettingsModel::setPlaybackDevice (const QString &device) {
|
||||
CoreManager::getInstance()->getCore()->setPlaybackDevice(
|
||||
Utils::appStringToCoreString(device)
|
||||
);
|
||||
emit playbackDeviceChanged(device);
|
||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||
createCaptureGraph();
|
||||
}
|
||||
std::string devId = Utils::appStringToCoreString(device);
|
||||
|
||||
auto list = CoreManager::getInstance()->getCore()->getExtendedAudioDevices();
|
||||
auto audioDevice = find_if(list.cbegin(), list.cend(), [&] ( const std::shared_ptr<linphone::AudioDevice> & audioItem) {
|
||||
return audioItem->getId() == devId;
|
||||
});
|
||||
if(audioDevice != list.cend()){
|
||||
|
||||
CoreManager::getInstance()->getCore()->setPlaybackDevice(devId);
|
||||
CoreManager::getInstance()->getCore()->setOutputAudioDevice(*audioDevice);
|
||||
emit playbackDeviceChanged(device);
|
||||
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
|
||||
createCaptureGraph();
|
||||
}
|
||||
}else
|
||||
qWarning() << "Cannot set Playback device. The ID cannot be matched with an existant device : " << device;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit c8700f691113dc7771d24e80feb339e1cf0970a0
|
||||
Subproject commit 3609b38153ce4b715e93389673538003425cbac2
|
||||
Loading…
Add table
Reference in a new issue