main/core: changed code so that headless would run truly headless with QCoreApplication instead of QApplication
QApplication is designed for GUI/widget programs and thus fails to launch if no window system is available. For a true headless mode, we must swap out with QCoreApplication. However, what complicates this is that QCommandLineParser - the class we use to determine whether we should run in GUI mode or not - requires an active application instance to work. This creates an unfortunate catch-22 that ultimately ended in writing a custom command line parser. Now we can correctly swap out with QCoreApplication, however this has exposed other issues regarding functions that unnecessarily rely on QWidget functions. So they'll need to be sorted out eventually.
This commit is contained in:
@@ -21,6 +21,8 @@ set(OLIVE_SOURCES
|
|||||||
common/cancelableobject.h
|
common/cancelableobject.h
|
||||||
common/channellayout.h
|
common/channellayout.h
|
||||||
common/clamp.h
|
common/clamp.h
|
||||||
|
common/commandlineparser.h
|
||||||
|
common/commandlineparser.cpp
|
||||||
common/crashhandler.h
|
common/crashhandler.h
|
||||||
common/crashhandler.cpp
|
common/crashhandler.cpp
|
||||||
common/crashpadinterface.cpp
|
common/crashpadinterface.cpp
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
/***
|
||||||
|
|
||||||
|
Olive - Non-Linear Video Editor
|
||||||
|
Copyright (C) 2019 Olive Team
|
||||||
|
|
||||||
|
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 "commandlineparser.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
CommandLineParser::~CommandLineParser()
|
||||||
|
{
|
||||||
|
foreach (const KnownOption& o, options_) {
|
||||||
|
delete o.option;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const KnownPositionalArgument& a, positional_args_) {
|
||||||
|
delete a.option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommandLineParser::Option *CommandLineParser::AddOption(const QStringList &strings, const QString &description)
|
||||||
|
{
|
||||||
|
Option* o = new Option();
|
||||||
|
|
||||||
|
options_.append({strings, description, o});
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommandLineParser::PositionalArgument *CommandLineParser::AddPositionalArgument(const QString &name, const QString &description, bool required)
|
||||||
|
{
|
||||||
|
PositionalArgument* a = new PositionalArgument();
|
||||||
|
|
||||||
|
positional_args_.append({name, description, a, required});
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineParser::Process(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int positional_index = 0;
|
||||||
|
|
||||||
|
for (int i=1; i<argc; i++) {
|
||||||
|
if (argv[i][0] == '-') {
|
||||||
|
// Must be an option
|
||||||
|
|
||||||
|
// Skip past first dashes
|
||||||
|
const char* arg_basename = &argv[i][1];
|
||||||
|
|
||||||
|
bool matched_known = false;
|
||||||
|
|
||||||
|
for (int j=0; j<options_.size(); j++) {
|
||||||
|
KnownOption& o = options_[j];
|
||||||
|
|
||||||
|
foreach (const QString& s, o.args) {
|
||||||
|
if (!s.compare(arg_basename, Qt::CaseInsensitive)) {
|
||||||
|
// Flag discovered!
|
||||||
|
o.option->Set();
|
||||||
|
matched_known = true;
|
||||||
|
goto found_flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
found_flag:
|
||||||
|
if (!matched_known) {
|
||||||
|
qWarning() << "Unknown parameter:" << argv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Must be a positional flag
|
||||||
|
if (positional_index < positional_args_.size()) {
|
||||||
|
positional_args_[positional_index].option->SetSetting(argv[i]);
|
||||||
|
positional_index++;
|
||||||
|
} else {
|
||||||
|
qWarning() << "Unknown parameter:" << argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineParser::PrintHelp(const char* filename)
|
||||||
|
{
|
||||||
|
printf("%s %s\n",
|
||||||
|
QCoreApplication::applicationName().toUtf8().constData(),
|
||||||
|
QCoreApplication::applicationVersion().toUtf8().constData());
|
||||||
|
|
||||||
|
printf("Copyright (C) 2018-2020 Olive Team\n");
|
||||||
|
|
||||||
|
QString positional_args;
|
||||||
|
for (int i=0; i<positional_args_.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
positional_args.append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
positional_args.append('[');
|
||||||
|
positional_args.append(positional_args_.at(i).name);
|
||||||
|
positional_args.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* basename;
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
basename = strrchr(filename, '\\');
|
||||||
|
if (!basename) {
|
||||||
|
basename = strrchr(filename, '/');
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
basename = strrchr(filename, '/');
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("Usage: %s [options] %s\n\n", basename + 1, positional_args.toUtf8().constData());
|
||||||
|
|
||||||
|
foreach (const KnownOption& o, options_) {
|
||||||
|
QString all_args;
|
||||||
|
|
||||||
|
for (int i=0; i<o.args.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
all_args.append(QStringLiteral(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& this_arg = o.args.at(i);
|
||||||
|
|
||||||
|
all_args.append('-');
|
||||||
|
all_args.append(this_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" %s\n", all_args.toUtf8().constData());
|
||||||
|
|
||||||
|
printf(" %s\n\n", o.description.toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/***
|
||||||
|
|
||||||
|
Olive - Non-Linear Video Editor
|
||||||
|
Copyright (C) 2019 Olive Team
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***/
|
||||||
|
|
||||||
|
#ifndef COMMANDLINEPARSER_H
|
||||||
|
#define COMMANDLINEPARSER_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "common/define.h"
|
||||||
|
|
||||||
|
class CommandLineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~CommandLineParser();
|
||||||
|
|
||||||
|
DISABLE_COPY_MOVE(CommandLineParser);
|
||||||
|
|
||||||
|
class Option {
|
||||||
|
public:
|
||||||
|
Option()
|
||||||
|
{
|
||||||
|
is_set_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSet() const
|
||||||
|
{
|
||||||
|
return is_set_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set()
|
||||||
|
{
|
||||||
|
is_set_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_set_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class PositionalArgument
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PositionalArgument() = default;
|
||||||
|
|
||||||
|
const QString& GetSetting() const
|
||||||
|
{
|
||||||
|
return setting_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSetting(const QString& s)
|
||||||
|
{
|
||||||
|
setting_ = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString setting_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandLineParser() = default;
|
||||||
|
|
||||||
|
const Option* AddOption(const QStringList& strings, const QString& description);
|
||||||
|
|
||||||
|
const PositionalArgument* AddPositionalArgument(const QString& name, const QString& description, bool required = false);
|
||||||
|
|
||||||
|
void Process(int argc, char** argv);
|
||||||
|
|
||||||
|
void PrintHelp(const char* filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct KnownOption {
|
||||||
|
QStringList args;
|
||||||
|
QString description;
|
||||||
|
Option* option;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KnownPositionalArgument {
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
PositionalArgument* option;
|
||||||
|
bool required;
|
||||||
|
};
|
||||||
|
|
||||||
|
QVector<KnownOption> options_;
|
||||||
|
|
||||||
|
QVector<KnownPositionalArgument> positional_args_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMMANDLINEPARSER_H
|
||||||
+44
-88
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -64,93 +63,23 @@
|
|||||||
|
|
||||||
OLIVE_NAMESPACE_ENTER
|
OLIVE_NAMESPACE_ENTER
|
||||||
|
|
||||||
Core Core::instance_;
|
Core* Core::instance_ = nullptr;
|
||||||
|
|
||||||
Core::Core() :
|
Core::Core(const CoreParams& params) :
|
||||||
main_window_(nullptr),
|
main_window_(nullptr),
|
||||||
tool_(Tool::kPointer),
|
tool_(Tool::kPointer),
|
||||||
addable_object_(Tool::kAddableEmpty),
|
addable_object_(Tool::kAddableEmpty),
|
||||||
snapping_(true),
|
snapping_(true),
|
||||||
gui_active_(false)
|
core_params_(params)
|
||||||
{
|
{
|
||||||
|
// Store reference to this object, making the assumption that Core will only ever be made in
|
||||||
|
// main(). This will obviously break if not.
|
||||||
|
instance_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core *Core::instance()
|
Core *Core::instance()
|
||||||
{
|
{
|
||||||
return &instance_;
|
return instance_;
|
||||||
}
|
|
||||||
|
|
||||||
int Core::execute(QCoreApplication* a)
|
|
||||||
{
|
|
||||||
int exit_code = 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parse command line arguments
|
|
||||||
//
|
|
||||||
|
|
||||||
QCommandLineParser parser;
|
|
||||||
QCommandLineOption help_option = parser.addHelpOption();
|
|
||||||
QCommandLineOption version_option = parser.addVersionOption();
|
|
||||||
|
|
||||||
// Project from command line option
|
|
||||||
// FIXME: What's the correct way to make a visually "optional" positional argument, or is manually adding square
|
|
||||||
// brackets like this correct?
|
|
||||||
parser.addPositionalArgument("[project]", tr("Project to open on startup"));
|
|
||||||
|
|
||||||
// Create fullscreen option
|
|
||||||
QCommandLineOption fullscreen_option({"f", "fullscreen"}, tr("Start in full screen mode"));
|
|
||||||
parser.addOption(fullscreen_option);
|
|
||||||
|
|
||||||
// Create headless export option
|
|
||||||
QCommandLineOption headless_export_option({"x", "export"}, tr("Export project from command line"));
|
|
||||||
parser.addOption(headless_export_option);
|
|
||||||
|
|
||||||
// Parse options
|
|
||||||
parser.process(*a);
|
|
||||||
|
|
||||||
if (parser.isSet(help_option) || parser.isSet(version_option)) {
|
|
||||||
// These options don't launch any of the application proper
|
|
||||||
return a->exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start core
|
|
||||||
OLIVE_NAMESPACE::Core::instance()->Start();
|
|
||||||
|
|
||||||
QStringList args = parser.positionalArguments();
|
|
||||||
|
|
||||||
// Detect project to load on startup
|
|
||||||
if (!args.isEmpty()) {
|
|
||||||
startup_project_ = args.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
gui_active_ = !parser.isSet(headless_export_option);
|
|
||||||
|
|
||||||
if (gui_active_) {
|
|
||||||
|
|
||||||
// Start GUI
|
|
||||||
StartGUI(parser.isSet(fullscreen_option));
|
|
||||||
|
|
||||||
// If we have a startup
|
|
||||||
QMetaObject::invokeMethod(this, "OpenStartupProject", Qt::QueuedConnection);
|
|
||||||
|
|
||||||
// Run application loop and receive exit code
|
|
||||||
exit_code = a->exec();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (parser.isSet(headless_export_option)) {
|
|
||||||
// Start a headless export
|
|
||||||
if (StartHeadlessExport()) {
|
|
||||||
exit_code = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear core memory
|
|
||||||
OLIVE_NAMESPACE::Core::instance()->Stop();
|
|
||||||
|
|
||||||
return exit_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::DeclareTypesForQt()
|
void Core::DeclareTypesForQt()
|
||||||
@@ -204,6 +133,22 @@ void Core::Start()
|
|||||||
//
|
//
|
||||||
|
|
||||||
qInfo() << "Using Qt version:" << qVersion();
|
qInfo() << "Using Qt version:" << qVersion();
|
||||||
|
|
||||||
|
switch (core_params_.run_mode()) {
|
||||||
|
case CoreParams::kRunNormal:
|
||||||
|
// Start GUI
|
||||||
|
StartGUI(core_params_.fullscreen());
|
||||||
|
|
||||||
|
// If we have a startup
|
||||||
|
QMetaObject::invokeMethod(this, "OpenStartupProject", Qt::QueuedConnection);
|
||||||
|
break;
|
||||||
|
case CoreParams::kHeadlessExport:
|
||||||
|
qInfo() << "Headless export is not fully implemented yet";
|
||||||
|
break;
|
||||||
|
case CoreParams::kHeadlessPreCache:
|
||||||
|
qInfo() << "Headless pre-cache is not fully implemented yet";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Stop()
|
void Core::Stop()
|
||||||
@@ -571,18 +516,20 @@ void Core::ProjectWasModified(bool e)
|
|||||||
|
|
||||||
bool Core::StartHeadlessExport()
|
bool Core::StartHeadlessExport()
|
||||||
{
|
{
|
||||||
if (startup_project_.isEmpty()) {
|
const QString& startup_project = core_params_.startup_project();
|
||||||
|
|
||||||
|
if (startup_project.isEmpty()) {
|
||||||
qCritical().noquote() << tr("You must specify a project file to export");
|
qCritical().noquote() << tr("You must specify a project file to export");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QFileInfo::exists(startup_project_)) {
|
if (!QFileInfo::exists(startup_project)) {
|
||||||
qCritical().noquote() << tr("Specified project does not exist");
|
qCritical().noquote() << tr("Specified project does not exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a load task and try running it
|
// Start a load task and try running it
|
||||||
ProjectLoadTask plm(startup_project_);
|
ProjectLoadTask plm(startup_project);
|
||||||
CLITaskDialog task_dialog(&plm);
|
CLITaskDialog task_dialog(&plm);
|
||||||
|
|
||||||
if (task_dialog.Run()) {
|
if (task_dialog.Run()) {
|
||||||
@@ -651,21 +598,24 @@ bool Core::StartHeadlessExport()
|
|||||||
|
|
||||||
void Core::OpenStartupProject()
|
void Core::OpenStartupProject()
|
||||||
{
|
{
|
||||||
|
const QString& startup_project = core_params_.startup_project();
|
||||||
|
bool startup_project_exists = !startup_project.isEmpty() && QFileInfo::exists(startup_project);
|
||||||
|
|
||||||
// Load startup project
|
// Load startup project
|
||||||
if (!startup_project_.isEmpty() && !QFileInfo::exists(startup_project_)) {
|
if (!startup_project_exists && !startup_project.isEmpty()) {
|
||||||
QMessageBox::warning(main_window_,
|
QMessageBox::warning(main_window_,
|
||||||
tr("Failed to open startup file"),
|
tr("Failed to open startup file"),
|
||||||
tr("The project \"%1\" doesn't exist. A new project will be started instead.").arg(startup_project_),
|
tr("The project \"%1\" doesn't exist. "
|
||||||
|
"A new project will be started instead.").arg(startup_project),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
|
|
||||||
startup_project_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startup_project_.isEmpty()) {
|
if (startup_project_exists) {
|
||||||
|
// If a startup project was set and exists, open it now
|
||||||
|
OpenProjectInternal(startup_project);
|
||||||
|
} else {
|
||||||
// If no load project is set, create a new one on open
|
// If no load project is set, create a new one on open
|
||||||
CreateNewProject();
|
CreateNewProject();
|
||||||
} else {
|
|
||||||
OpenProjectInternal(startup_project_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1228,4 +1178,10 @@ void Core::OpenProject()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::CoreParams::CoreParams() :
|
||||||
|
mode_(kRunNormal),
|
||||||
|
run_fullscreen_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
OLIVE_NAMESPACE_EXIT
|
OLIVE_NAMESPACE_EXIT
|
||||||
|
|||||||
+58
-13
@@ -52,12 +52,62 @@ class Core : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
class CoreParams
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CoreParams();
|
||||||
|
|
||||||
|
enum RunMode {
|
||||||
|
kRunNormal,
|
||||||
|
kHeadlessExport,
|
||||||
|
kHeadlessPreCache
|
||||||
|
};
|
||||||
|
|
||||||
|
bool fullscreen() const
|
||||||
|
{
|
||||||
|
return run_fullscreen_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_fullscreen(bool e)
|
||||||
|
{
|
||||||
|
run_fullscreen_ = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunMode run_mode() const
|
||||||
|
{
|
||||||
|
return mode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_run_mode(RunMode m)
|
||||||
|
{
|
||||||
|
mode_ = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString startup_project() const
|
||||||
|
{
|
||||||
|
return startup_project_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_startup_project(const QString& p)
|
||||||
|
{
|
||||||
|
startup_project_ = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RunMode mode_;
|
||||||
|
|
||||||
|
QString startup_project_;
|
||||||
|
|
||||||
|
bool run_fullscreen_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Core Constructor
|
* @brief Core Constructor
|
||||||
*
|
*
|
||||||
* Currently empty
|
* Currently empty
|
||||||
*/
|
*/
|
||||||
Core();
|
Core(const CoreParams& params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Core object accessible from anywhere in the code
|
* @brief Core object accessible from anywhere in the code
|
||||||
@@ -66,7 +116,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
static Core* instance();
|
static Core* instance();
|
||||||
|
|
||||||
int execute(QCoreApplication *a);
|
const CoreParams& core_params() const
|
||||||
|
{
|
||||||
|
return core_params_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start Olive Core
|
* @brief Start Olive Core
|
||||||
@@ -407,14 +460,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
MainWindow* main_window_;
|
MainWindow* main_window_;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Internal startup project object
|
|
||||||
*
|
|
||||||
* If the user specifies a project file on the command line, the command line parser in Start() will write the
|
|
||||||
* project URL here to be loaded once Olive has finished initializing.
|
|
||||||
*/
|
|
||||||
QString startup_project_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief List of currently open projects
|
* @brief List of currently open projects
|
||||||
*/
|
*/
|
||||||
@@ -456,14 +501,14 @@ private:
|
|||||||
QStringList recent_projects_;
|
QStringList recent_projects_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Internal variable for whether the GUI is active
|
* @brief Parameters set up in main() determining how the program should run
|
||||||
*/
|
*/
|
||||||
bool gui_active_;
|
CoreParams core_params_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Static singleton core instance
|
* @brief Static singleton core instance
|
||||||
*/
|
*/
|
||||||
static Core instance_;
|
static Core* instance_;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SaveAutorecovery();
|
void SaveAutorecovery();
|
||||||
|
|||||||
+90
-21
@@ -34,34 +34,23 @@ extern "C" {
|
|||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QCommandLineParser>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
#include "common/commandlineparser.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
|
||||||
#ifdef USE_CRASHPAD
|
#ifdef USE_CRASHPAD
|
||||||
#include "common/crashpadinterface.h"
|
#include "common/crashpadinterface.h"
|
||||||
#endif // USE_CRASHPAD
|
#endif // USE_CRASHPAD
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[])
|
||||||
// Set OpenGL display profile (3.2 Core)
|
{
|
||||||
QSurfaceFormat format;
|
// Set up debug handler
|
||||||
format.setVersion(3, 2);
|
qInstallMessageHandler(OLIVE_NAMESPACE::DebugHandler);
|
||||||
format.setDepthBufferSize(24);
|
|
||||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
|
||||||
|
|
||||||
//QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
||||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
||||||
|
|
||||||
// Create application instance
|
|
||||||
QApplication a(argc, argv);
|
|
||||||
|
|
||||||
// Set application metadata
|
|
||||||
QCoreApplication::setOrganizationName("olivevideoeditor.org");
|
|
||||||
QCoreApplication::setOrganizationDomain("olivevideoeditor.org");
|
|
||||||
QCoreApplication::setApplicationName("Olive");
|
|
||||||
|
|
||||||
|
// Generate version string
|
||||||
QString app_version = APPVERSION;
|
QString app_version = APPVERSION;
|
||||||
#ifdef GITHASH
|
#ifdef GITHASH
|
||||||
// Anything after the hyphen is considered "unimportant" information. Text BEFORE the hyphen is used in version
|
// Anything after the hyphen is considered "unimportant" information. Text BEFORE the hyphen is used in version
|
||||||
@@ -70,14 +59,85 @@ int main(int argc, char *argv[]) {
|
|||||||
app_version.append(GITHASH);
|
app_version.append(GITHASH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Set application metadata
|
||||||
|
QCoreApplication::setOrganizationName("olivevideoeditor.org");
|
||||||
|
QCoreApplication::setOrganizationDomain("olivevideoeditor.org");
|
||||||
|
QCoreApplication::setApplicationName("Olive");
|
||||||
|
|
||||||
QCoreApplication::setApplicationVersion(app_version);
|
QCoreApplication::setApplicationVersion(app_version);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
|
||||||
QGuiApplication::setDesktopFileName("org.olivevideoeditor.Olive");
|
QGuiApplication::setDesktopFileName("org.olivevideoeditor.Olive");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set up debug handler
|
//
|
||||||
qInstallMessageHandler(OLIVE_NAMESPACE::DebugHandler);
|
// Parse command line arguments
|
||||||
|
//
|
||||||
|
|
||||||
|
OLIVE_NAMESPACE::Core::CoreParams startup_params;
|
||||||
|
|
||||||
|
CommandLineParser parser;
|
||||||
|
|
||||||
|
const CommandLineParser::Option* help_option =
|
||||||
|
parser.AddOption({QStringLiteral("h"), QStringLiteral("-help")},
|
||||||
|
QCoreApplication::translate("main", "Show this help text"));
|
||||||
|
|
||||||
|
const CommandLineParser::Option* version_option =
|
||||||
|
parser.AddOption({QStringLiteral("v"), QStringLiteral("-version")},
|
||||||
|
QCoreApplication::translate("main", "Show application version"));
|
||||||
|
|
||||||
|
const CommandLineParser::Option* fullscreen_option =
|
||||||
|
parser.AddOption({QStringLiteral("f"), QStringLiteral("-fullscreen")},
|
||||||
|
QCoreApplication::translate("main", "Start in full-screen mode"));
|
||||||
|
|
||||||
|
const CommandLineParser::Option* export_option =
|
||||||
|
parser.AddOption({QStringLiteral("x"), QStringLiteral("-export")},
|
||||||
|
QCoreApplication::translate("main", "Export only (No GUI)"));
|
||||||
|
|
||||||
|
const CommandLineParser::PositionalArgument* project_argument =
|
||||||
|
parser.AddPositionalArgument(QStringLiteral("project"),
|
||||||
|
QCoreApplication::translate("main", "Project to open on startup"));
|
||||||
|
|
||||||
|
parser.Process(argc, argv);
|
||||||
|
|
||||||
|
if (help_option->IsSet()) {
|
||||||
|
// Show help
|
||||||
|
parser.PrintHelp(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_option->IsSet()) {
|
||||||
|
// Print version
|
||||||
|
printf("%s\n", app_version.toUtf8().constData());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (export_option->IsSet()) {
|
||||||
|
startup_params.set_run_mode(OLIVE_NAMESPACE::Core::CoreParams::kHeadlessExport);
|
||||||
|
}
|
||||||
|
|
||||||
|
startup_params.set_fullscreen(fullscreen_option->IsSet());
|
||||||
|
|
||||||
|
startup_params.set_startup_project(project_argument->GetSetting());
|
||||||
|
|
||||||
|
// Set OpenGL display profile (3.2 Core)
|
||||||
|
QSurfaceFormat format;
|
||||||
|
format.setVersion(3, 2);
|
||||||
|
format.setDepthBufferSize(24);
|
||||||
|
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
|
|
||||||
|
// Enable application automatically using higher resolution images from icons
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
|
||||||
|
// Create application instance
|
||||||
|
std::unique_ptr<QCoreApplication> a;
|
||||||
|
|
||||||
|
if (startup_params.run_mode() == OLIVE_NAMESPACE::Core::CoreParams::kRunNormal) {
|
||||||
|
a.reset(new QApplication(argc, argv));
|
||||||
|
} else {
|
||||||
|
a.reset(new QCoreApplication(argc, argv));
|
||||||
|
}
|
||||||
|
|
||||||
// Register FFmpeg codecs and filters (deprecated in 4.0+)
|
// Register FFmpeg codecs and filters (deprecated in 4.0+)
|
||||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
|
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
|
||||||
@@ -94,5 +154,14 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
#endif // USE_CRASHPAD
|
#endif // USE_CRASHPAD
|
||||||
|
|
||||||
return OLIVE_NAMESPACE::Core::instance()->execute(&a);
|
// Start core
|
||||||
|
OLIVE_NAMESPACE::Core c(startup_params);
|
||||||
|
c.Start();
|
||||||
|
|
||||||
|
int ret = a->exec();
|
||||||
|
|
||||||
|
// Clear core memory
|
||||||
|
c.Stop();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user